DB developers channel
📌 Самый простой вопрос из собесов на SQL. ❓ Что думаете, какой вариант даст TRUE?
😅 Всё правильно — без подвоха на собесах редко бывает.
👉 Главное помнить: NULL — это "неизвестное значение", и любые сравнения (=, !=, <, >) с ним дают FALSE (результат сравнения неопределен).
✅ Рабочие варианты проверки:
1) NULL IS NULL → TRUE
2) Использовать функции NVL, COALESCE, CASE, DECODE, SYS_OP_MAP_NONNULL
Так что троллинг удался, но польза от вопроса всё равно осталась 🚀
⚠️ Хотите проверить скрипты, но нет базы под рукой - онлайн-песочница
💎 Поддержка канала⁉️
#RealInterviewTasks #sql #Oracle #PLSQL
👉 Главное помнить: NULL — это "неизвестное значение", и любые сравнения (=, !=, <, >) с ним дают FALSE (результат сравнения неопределен).
✅ Рабочие варианты проверки:
1) NULL IS NULL → TRUE
2) Использовать функции NVL, COALESCE, CASE, DECODE, SYS_OP_MAP_NONNULL
Так что троллинг удался, но польза от вопроса всё равно осталась 🚀
⚠️ Хотите проверить скрипты, но нет базы под рукой - онлайн-песочница
💎 Поддержка канала⁉️
#RealInterviewTasks #sql #Oracle #PLSQL
💯4👎1
🎵«Тем, кто рос в тепле и неге,
Мы, конечно, не коллеги.
Мы крапивные побеги,
Парни во.
Мы всегда и всюду рады
Вызывать у всех досаду,
Для чего нам это надо,
А не для чего.»
— к/ф «Тайна Снежной королевы» 🎬
🔥 А теперь — задачи для тех, кто любит алгоритмы и процедурные языки:
1️⃣ Максимальная разница — найти максимальную разницу в массиве, где больший элемент идёт после меньшего.
2️⃣ Проверка палиндрома — определить, является ли строка палиндромом (игнорируя регистр и лишние символы).
3️⃣ Максимальный квадрат — найти самый большой квадрат из единиц в двоичной матрице.
4️⃣ Максимальная глубина дерева — вычислить максимальную глубину бинарного дерева.
5️⃣ Дом-вор — дома стоят в ряд, нельзя грабить два подряд. Найдите максимальную сумму.
👉 Пробуем решать на PL/SQL или PL/pgSQL😉
⚠️ Хотите проверить скрипты, но нет базы под рукой - онлайн-песочница
💎 Поддержка канала⁉️
#sql #Oracle #PostgreSQL #PLSQL #PLpgSQL
👎1👏1
DB developers channel
🎵«Тем, кто рос в тепле и неге, Мы, конечно, не коллеги. Мы крапивные побеги, Парни во. Мы всегда и всюду рады Вызывать у всех досаду, Для чего нам это надо, А не для чего.» — к/ф «Тайна Снежной королевы» 🎬 🔥 А теперь — задачи для тех, кто любит алгоритмы…
🎯 Задача 1. Максимальная разница
Дан массив чисел. Нужно найти максимальную разницу между двумя элементами, где больший элемент идёт после меньшего.
Пример:
😅 Сначала я решил задачу «в лоб» — двойным циклом.
🤖 Но ChatGPT подсказал вариант с одним проходом по массиву, и это действительно оптимально.
💻 Решение на PL/SQL:
⚡ Алгоритм (O(n)):
📌 minPref — минимальный элемент слева (купить дёшево).
📌 maxResidual — лучшая разница (продать дорого).
🔹 Шаги:
Инициализируем: minPref = "set"[1], maxResidual = NULL.
Для каждого следующего элемента i:
Считаем: cand = i - minPref.
Если cand > 0 и больше текущего maxResidual, обновляем результат.
Обновляем minPref = min(minPref, i).
Если так и не нашли пары → выводим «❌ пар нет».
⚠️ Хотите проверить скрипты, но нет базы под рукой - онлайн-песочница
💎 Поддержка канала⁉️
👍 Пальцы вверх — продолжаем разбирать задачи по массивам.
👎 Пальцы вниз — значит, тема не зашла.
Дамы и Господа, выбор за вами 😉
#sql #Oracle #PLSQL
Дан массив чисел. Нужно найти максимальную разницу между двумя элементами, где больший элемент идёт после меньшего.
Пример:
[1, 3, 2, 5, 8, 7, 9]
Максимальная разница = 9 - 1 = 8
😅 Сначала я решил задачу «в лоб» — двойным циклом.
🤖 Но ChatGPT подсказал вариант с одним проходом по массиву, и это действительно оптимально.
💻 Решение на PL/SQL:
DECLARE
TYPE set_tab IS TABLE OF INTEGER;
"set" set_tab := set_tab (1, 3, 2, 5, 8, 7, 9);
minPref INTEGER;
maxResidual INTEGER := NULL;
cand INTEGER;
BEGIN
minPref := "set"(1);
FOR i IN 2 .. "set".COUNT LOOP
cand := "set"(i) - minPref;
IF cand > 0 THEN
IF maxResidual IS NULL THEN
maxResidual := cand;
ELSE
maxResidual := GREATEST(maxResidual, cand);
END IF;
END IF;
minPref := LEAST(minPref, "set"(i));
END LOOP;
IF maxResidual IS NOT NULL THEN
DBMS_OUTPUT.put_line('maxResidual = ' || maxResidual);
ELSE
DBMS_OUTPUT.put_line('No residual pairs');
END IF;
END;
⚡ Алгоритм (O(n)):
📌 minPref — минимальный элемент слева (купить дёшево).
📌 maxResidual — лучшая разница (продать дорого).
🔹 Шаги:
Инициализируем: minPref = "set"[1], maxResidual = NULL.
Для каждого следующего элемента i:
Считаем: cand = i - minPref.
Если cand > 0 и больше текущего maxResidual, обновляем результат.
Обновляем minPref = min(minPref, i).
Если так и не нашли пары → выводим «❌ пар нет».
⚠️ Хотите проверить скрипты, но нет базы под рукой - онлайн-песочница
💎 Поддержка канала⁉️
👍 Пальцы вверх — продолжаем разбирать задачи по массивам.
👎 Пальцы вниз — значит, тема не зашла.
Дамы и Господа, выбор за вами 😉
#sql #Oracle #PLSQL
👍5❤1👎1
DB developers channel
🎵«Тем, кто рос в тепле и неге, Мы, конечно, не коллеги. Мы крапивные побеги, Парни во. Мы всегда и всюду рады Вызывать у всех досаду, Для чего нам это надо, А не для чего.» — к/ф «Тайна Снежной королевы» 🎬 🔥 А теперь — задачи для тех, кто любит алгоритмы…
🎯 Задача 2. Проверка палиндрома. Разбор по шагам
Цель: Проверка палиндрома: Проверьте, является ли заданная строка палиндромом, игнорируя регистр и небуквенно-цифровые символы..
📌 На входе:
"KaZAk" <=> "kAZaK"
🧠 Как работает алгоритм
1️⃣ Символ считается небуквой, если SUBSTR(lowerStr,i,1) = SUBSTR(upperStr,i,1)
(для букв lower != upper, для пробелов/знаков/цифр — одинаково; поэтому они пропускаются).
2️⃣ Сравнение идёт по буквам: SUBSTR(lowerStr, leftIndex#, 1) <=> SUBSTR(lowerStr, rightIndex#, 1).
3️⃣Если буквы совпали — сдвигаем оба индекса внутрь; если нет — isPolindrom := 'N' и выходим.
🧩 Что важно помнить
В текущей логике цифры тоже игнорируются, потому что для них lowerStr = upperStr.
Если нужен строгий режим «игнорируем только небуквенно-цифровые, но цифры учитываем», придётся скорректировать проверки.
👍 Пальцы вверх — продолжаем разбирать задачи по строкам.
👎 Пальцы вниз — значит, тема не зашла.
⚠️ Хотите проверить скрипты, но нет базы под рукой - онлайн-песочница
💎 Поддержка канала⁉️
Дамы и Господа, выбор всегда за вами 😉
#sql #Oracle #PLSQL
Цель: Проверка палиндрома: Проверьте, является ли заданная строка палиндромом, игнорируя регистр и небуквенно-цифровые символы..
📌 На входе:
str := 'K 123 a?* Z(A) k ';
"KaZAk" <=> "kAZaK"
🧠 Как работает алгоритм
1️⃣ Символ считается небуквой, если SUBSTR(lowerStr,i,1) = SUBSTR(upperStr,i,1)
(для букв lower != upper, для пробелов/знаков/цифр — одинаково; поэтому они пропускаются).
2️⃣ Сравнение идёт по буквам: SUBSTR(lowerStr, leftIndex#, 1) <=> SUBSTR(lowerStr, rightIndex#, 1).
3️⃣Если буквы совпали — сдвигаем оба индекса внутрь; если нет — isPolindrom := 'N' и выходим.
DECLARE
str VARCHAR2 (4000) := 'K 123 a?* Z(A) k ';
lowerStr VARCHAR2 (4000) := LOWER (str);
upperStr VARCHAR2 (4000) := UPPER (str);
isPolindrom VARCHAR2 (1) := 'Y';
leftIndex# INTEGER := 1;
rightIndex# INTEGER := LENGTH (str);
BEGIN
WHILE leftIndex# < rightIndex# LOOP
--DBMS_OUTPUT.put_line ('---');
--DBMS_OUTPUT.put_line ('substr(lowerStr,leftIndex#,1) = ' || substr(lowerStr,leftIndex#,1));
--DBMS_OUTPUT.put_line ('substr(lowerStr,rightIndex#,1) = ' || substr(lowerStr,rightIndex#,1));
IF SUBSTR (lowerStr, leftIndex#, 1) = SUBSTR (upperStr, leftIndex#, 1) THEN -- не буква
leftIndex# := leftIndex# + 1;
CONTINUE;
END IF;
IF SUBSTR (lowerStr, rightIndex#, 1) = SUBSTR (upperStr, rightIndex#, 1) THEN -- не буква
rightIndex# := rightIndex# - 1;
CONTINUE;
END IF;
IF SUBSTR (lowerStr, leftIndex#, 1) = SUBSTR (lowerStr, rightIndex#, 1) THEN
leftIndex# := leftIndex# + 1;
rightIndex# := rightIndex# - 1;
ELSE
isPolindrom := 'N';
EXIT;
END IF;
END LOOP;
DBMS_OUTPUT.put_line ('isPolindrom = ' || isPolindrom);
END;
🧩 Что важно помнить
В текущей логике цифры тоже игнорируются, потому что для них lowerStr = upperStr.
Если нужен строгий режим «игнорируем только небуквенно-цифровые, но цифры учитываем», придётся скорректировать проверки.
👍 Пальцы вверх — продолжаем разбирать задачи по строкам.
👎 Пальцы вниз — значит, тема не зашла.
⚠️ Хотите проверить скрипты, но нет базы под рукой - онлайн-песочница
💎 Поддержка канала⁉️
Дамы и Господа, выбор всегда за вами 😉
#sql #Oracle #PLSQL
👍5❤2👎1
Forwarded from Пишем на SQL (Ilia Khokhlov 👨💻)
Рекомендации по написанию программного кода хранимых функций и процедур
Чем больше нагрузка и больше одновременно выполняющихся транзакций, тем больше и ответственности при создании хранимых функций и процедур. Хорошо написанный программный код легко сопровождаем и не боится параллельной работы! Ниже собрал для вас основные рекомендации, которые важно учитывать при разработке хранимок (функций, процедур, триггеров).
1. Максимально эффективное обращение к данных (желательно всегда по первичным ключам и индексам);
2. Разделение сложных операций на более простые (сложный update, insert или delete с подзапросами можно упростить - сделать его по ключу, а данные, получаемые подзапросами, можно предварительно положить во временную таблицу или таблицу временного хранения данных);
3. Соблюдение идентичной последовательности работы с таблицами в разных функциях и процедурах (это позволит минимизировать вероятность взаимных блокировок);
4. Форматирование кода (соблюдение отступов, единое оформление, принятое в компании или в конкретной АС), использование регламентов оформления кода;
5. Соблюдение соответствия программы кода хранимки её назначению (процедура, открывающая вклад клиенту, должна открывать вклад клиенту и не должна дополнительно закрывать кредит);
6. Краткое и понятное комментирование неочевидных участков кода;
7. Идеальный код одной хранимки помещается на одном экране, чтобы не пришлось его прокручивать (конечно, на практике, это далеко не всегда так, но надо к этому стремиться). Если алгоритм большой, то его нужно разбивать на дополнительные функции и процедуры, которые можно использовать в коде основной функции/процедуры.
Чем больше нагрузка и больше одновременно выполняющихся транзакций, тем больше и ответственности при создании хранимых функций и процедур. Хорошо написанный программный код легко сопровождаем и не боится параллельной работы! Ниже собрал для вас основные рекомендации, которые важно учитывать при разработке хранимок (функций, процедур, триггеров).
1. Максимально эффективное обращение к данных (желательно всегда по первичным ключам и индексам);
2. Разделение сложных операций на более простые (сложный update, insert или delete с подзапросами можно упростить - сделать его по ключу, а данные, получаемые подзапросами, можно предварительно положить во временную таблицу или таблицу временного хранения данных);
3. Соблюдение идентичной последовательности работы с таблицами в разных функциях и процедурах (это позволит минимизировать вероятность взаимных блокировок);
4. Форматирование кода (соблюдение отступов, единое оформление, принятое в компании или в конкретной АС), использование регламентов оформления кода;
5. Соблюдение соответствия программы кода хранимки её назначению (процедура, открывающая вклад клиенту, должна открывать вклад клиенту и не должна дополнительно закрывать кредит);
6. Краткое и понятное комментирование неочевидных участков кода;
7. Идеальный код одной хранимки помещается на одном экране, чтобы не пришлось его прокручивать (конечно, на практике, это далеко не всегда так, но надо к этому стремиться). Если алгоритм большой, то его нужно разбивать на дополнительные функции и процедуры, которые можно использовать в коде основной функции/процедуры.
❤1👎1🤮1
Пишем на SQL
Рекомендации по написанию программного кода хранимых функций и процедур Чем больше нагрузка и больше одновременно выполняющихся транзакций, тем больше и ответственности при создании хранимых функций и процедур. Хорошо написанный программный код легко сопровождаем…
🎵«За що же ж мы боролись
За що же ж мы страждали
За що ж мы проливали нашу кровь?»
— (приписывается Борису Тимофееву)
Извините, но сегодня я включил режим "Душнилы" 🤓
Критиковать всегда проще, чем составить текст.
Все указанные правила — либо верны полностью, либо частично.
Мне стало интересно добавить другой формат — критический разбор.
1️⃣ Максимально эффективное обращение к данным
Тезис правильный 👍, но как это относится к коду? Никак.
Да, индексы и структура данных важны, но это скорее про хранение и доступ, а не про сам код.
Изначально индексы создаются с расчётом, что их будут использовать в коде. Но возможен и обратный анализ: индексы нужно добавлять, изменять или удалять, исходя из анализа кода.
2️⃣ Разделение сложных операций на простые
Операции не должны быть «простыми» или «сложными», они должны быть эффективными ⚡.
Если сложный запрос работает быстрее — переделывать его в «более простой» не нужно.
Вывод: всегда нужно проверять варианты и выбирать оптимальный. «Сложность» и «простота» — субъективны.
3️⃣ Единая последовательность работы с таблицами
В целом верно ✔️: одинаковая последовательность доступа к таблицам действительно снижает риск взаимных блокировок.
Но:
Не всегда это возможно.
Это лишь один из способов минимизации блокировок.
Закономерность есть, но правило не универсальное.
4️⃣ Форматирование кода
Тут согласен на 💯.
У каждой компании есть своё «самое лучшее» форматирование. Но к любому стилю быстро привыкаешь.
Единый стиль — это уважение к коллегам и к будущему себе.
5️⃣ Соответствие кода назначению
Полностью согласен 👍.
Метод должен делать ровно то, что написано в его имени.
Хочешь «открыть вклад» и «закрыть кредит»? Сделай три метода:
открыть_вклад
закрыть_кредит
открыть_вклад_и_закрыть_кредит
Да, странный метод 🤷, но принцип понятен: каждый метод выполняет свою задачу.
6️⃣ Комментарии в коде
Согласен, но с уточнением ✍️.
В 90% случаев комментарии появляются из-за проблем с неймингом или структурой кода.
Прежде чем написать комментарий, спроси себя:
не повторяю ли я имя метода?
не лучше ли переименовать или упростить код?
👉 В хорошем коде комментариев мало, но они цепляют внимание.
👉 В плохом коде комментариев много, и это выглядит как спам.
7️⃣ Код на одном экране
Здесь не согласен ❌.
Стремиться надо не к минимизации, а к простоте и читаемости.
Если метод состоит из 10 логических этапов, пусть будет 10 вызовов.
А вот искусственное деление ради «одного экрана» делает код трудным для анализа и изменений.
💬 Если есть возражение, согласие или негодование — милости просим в комментарии!
💎 Поддержка канала⁉️
#CodeArchitecture
За що же ж мы страждали
За що ж мы проливали нашу кровь?»
— (приписывается Борису Тимофееву)
Извините, но сегодня я включил режим "Душнилы" 🤓
Критиковать всегда проще, чем составить текст.
Все указанные правила — либо верны полностью, либо частично.
Мне стало интересно добавить другой формат — критический разбор.
1️⃣ Максимально эффективное обращение к данным
Тезис правильный 👍, но как это относится к коду? Никак.
Да, индексы и структура данных важны, но это скорее про хранение и доступ, а не про сам код.
Изначально индексы создаются с расчётом, что их будут использовать в коде. Но возможен и обратный анализ: индексы нужно добавлять, изменять или удалять, исходя из анализа кода.
2️⃣ Разделение сложных операций на простые
Операции не должны быть «простыми» или «сложными», они должны быть эффективными ⚡.
Если сложный запрос работает быстрее — переделывать его в «более простой» не нужно.
Вывод: всегда нужно проверять варианты и выбирать оптимальный. «Сложность» и «простота» — субъективны.
3️⃣ Единая последовательность работы с таблицами
В целом верно ✔️: одинаковая последовательность доступа к таблицам действительно снижает риск взаимных блокировок.
Но:
Не всегда это возможно.
Это лишь один из способов минимизации блокировок.
Закономерность есть, но правило не универсальное.
4️⃣ Форматирование кода
Тут согласен на 💯.
У каждой компании есть своё «самое лучшее» форматирование. Но к любому стилю быстро привыкаешь.
Единый стиль — это уважение к коллегам и к будущему себе.
5️⃣ Соответствие кода назначению
Полностью согласен 👍.
Метод должен делать ровно то, что написано в его имени.
Хочешь «открыть вклад» и «закрыть кредит»? Сделай три метода:
открыть_вклад
закрыть_кредит
открыть_вклад_и_закрыть_кредит
Да, странный метод 🤷, но принцип понятен: каждый метод выполняет свою задачу.
6️⃣ Комментарии в коде
Согласен, но с уточнением ✍️.
В 90% случаев комментарии появляются из-за проблем с неймингом или структурой кода.
Прежде чем написать комментарий, спроси себя:
не повторяю ли я имя метода?
не лучше ли переименовать или упростить код?
👉 В хорошем коде комментариев мало, но они цепляют внимание.
👉 В плохом коде комментариев много, и это выглядит как спам.
7️⃣ Код на одном экране
Здесь не согласен ❌.
Стремиться надо не к минимизации, а к простоте и читаемости.
Если метод состоит из 10 логических этапов, пусть будет 10 вызовов.
А вот искусственное деление ради «одного экрана» делает код трудным для анализа и изменений.
💬 Если есть возражение, согласие или негодование — милости просим в комментарии!
💎 Поддержка канала⁉️
#CodeArchitecture
👍1👎1🔥1
🎵«Я спросил у ясеня
Где моя любимая?
Ясень не ответил мне
Качая головой» — Сергей Никитин
Разбор задачи: найти максимальную глубину бинарного "ясеня".
Никогда прежде не имел опыта работы с такого рода объектами в PL/SQL.
Многому научился.😊
Возможно, правильнее все методы инкапсулировать в OBJECT node. Но для меня для тестовой задаче это уже слишком.
Где моя любимая?
Ясень не ответил мне
Качая головой» — Сергей Никитин
Разбор задачи: найти максимальную глубину бинарного "ясеня".
Никогда прежде не имел опыта работы с такого рода объектами в PL/SQL.
Многому научился.😊
Возможно, правильнее все методы инкапсулировать в OBJECT node. Но для меня для тестовой задаче это уже слишком.
CREATE OR REPLACE TYPE node IS OBJECT (
value NUMBER,
left REF node,
right REF node
);
CREATE TABLE nodes OF node;
DECLARE
root REF node;
PROCEDURE init_tree (node_amount IN INTEGER, root OUT REF node) IS
result REF node;
PROCEDURE insert_node (root IN OUT REF node, new_value IN NUMBER) IS
current node;
BEGIN
IF root IS NULL THEN
-- создаём корень
INSERT INTO nodes n
VALUES (node (VALUE => insert_node.new_value, left => NULL, right => NULL))
RETURNING REF (n)
INTO insert_node.root;
ELSE
SELECT DEREF (root) INTO current FROM DUAL;
IF new_value < current.VALUE THEN
insert_node (root => current.left, new_value => new_value);
-- обновляем left
UPDATE nodes n
SET n.left = current.left
WHERE REF (n) = insert_node.root;
ELSE
insert_node (root => current.right, new_value => new_value);
-- обновляем right
UPDATE nodes n
SET n.right = current.right
WHERE REF (n) = insert_node.root;
END IF;
END IF;
END insert_node;
BEGIN
FOR i IN 1 .. node_amount LOOP
DECLARE
newValue NUMBER := TRUNC (DBMS_RANDOM.VALUE (1, 100));
BEGIN
insert_node (root => result, new_value => newValue);
END;
END LOOP;
root := result;
END init_tree;
PROCEDURE print_tree (root IN OUT REF node) IS
current node;
skip EXCEPTION;
BEGIN
IF root IS NULL THEN
RAISE skip;
END IF;
SELECT DEREF (root) INTO current FROM DUAL;
DBMS_OUTPUT.put_line (
'node('
|| TO_CHAR (current.VALUE)
|| ','
|| CASE WHEN current.left IS NOT NULL THEN 'left = yes' ELSE 'left = no' END
|| ','
|| CASE WHEN current.right IS NOT NULL THEN 'right = yes' ELSE 'right = no' END
|| ')');
IF current.left IS NOT NULL THEN
print_tree (root => current.left);
END IF;
IF current.right IS NOT NULL THEN
print_tree (root => current.right);
END IF;
EXCEPTION
WHEN skip THEN
NULL;
END print_tree;
FUNCTION max_depth (root IN REF node)
RETURN INTEGER IS
current node;
leftDepth INTEGER;
rightDepth INTEGER;
BEGIN
IF root IS NULL THEN
RETURN 0;
END IF;
SELECT DEREF (root) INTO current FROM DUAL;
leftDepth := max_depth (current.left);
rightDepth := max_depth (current.right);
IF leftDepth > rightDepth THEN
RETURN leftDepth + 1;
ELSE
RETURN rightDepth + 1;
END IF;
END max_depth;
BEGIN
init_tree (node_amount => 10, root => root);
print_tree (root => root);
DBMS_OUTPUT.put_line ('Max depth is ' || TO_CHAR (max_depth (root => root)));
ROLLBACK;
END;
👎1🤬1
1️⃣ Подготовка структуры данных
Тип объекта:
node(value NUMBER, left REF node, right REF node) — значение и ссылки на детей.
Таблица хранения:
CREATE TABLE nodes OF node; — каждая строка — объект node.
Почему так: используется объектная модель Oracle: связи не по ID, а через REF/DEREF.🧩
2️⃣ Инициализация дерева — init_tree 🌱
Процедура init_tree (node_amount IN INTEGER, root OUT REF node) создаёт дерево и возвращает root.
Обратите внимание: в текущем виде цикл фиксирован на FOR i IN 1 .. node_amount
Внутри — вложенная процедура
insert_node(root IN OUT REF node, new_value IN NUMBER), которая строит бинарное дерево (вставляет меньшее влево, большее/равное вправо).
🧩 Ключевые моменты insert_node:
Если root IS NULL → создаём корень:
Иначе читаем текущий узел:
Рекурсивно вставляем в current.left или current.right:
insert_node(root => current.left, new_value => new_value);
Затем фиксируем изменённую ссылку в таблице:
UPDATE nodes n SET n.left = current.left WHERE REF(n) = insert_node.root; (или n.right = current.right).
Это важно, потому что мы меняли current как локальную копию, и нужно записать обновлённый REF обратно. 🧷
3️⃣ Печать дерева — print_tree 🖨️
print_tree(root IN OUT REF node) делает простой прямой обход (node → left → right):
Пропуск NULL через локальное исключение skip.
Для каждого узла — вывод value и флагов наличия детей (left = yes/no, right = yes/no).
Рекурсивный вызов для current.left и current.right.
Это удобный текстовый взгляд на структуру — помогает убедиться, что вставки шли правильно. 👀
4️⃣ Алгоритм глубины — max_depth 📏
База рекурсии: root IS NULL → 0.
Иначе DEREF(root) → current.
Рекурсивно считаем:
Возвращаем max(leftDepth, rightDepth) + 1.
Сложность:
По времени — O(n) (каждый узел посещаем ровно один раз).
По памяти стека — O(h), где h — высота дерева.
Поскольку дерево строится случайно (DBMS_RANDOM), оно не сбалансировано, и h может быть близко к n в худшем случае. 🎲
5️⃣ Точка входа блока 📦
init_tree(...) — строим дерево, получаем root.
print_tree(root) — показываем структуру.
DBMS_OUTPUT.put_line('Max depth is ' || max_depth(root)) — вывод глубины.
ROLLBACK; — данные не сохраняются: демонстрация без «мусора» в базе. ✅
6️⃣ Что важно помнить ⚠️
Работа с REF/DEREF требует обновления родителя после рекурсивной вставки — это и делает UPDATE ... WHERE REF(n) = insert_node.root;.
⚠️ Хотите проверить скрипты, но нет базы под рукой - онлайн-песочница
💎 Поддержка канала⁉️
👍 Пальцы вверх — продолжаем разбирать задачи по структурам.
👎 Пальцы вниз — значит, тема не зашла.
Дамы и Господа, выбор всегда за вами 😉
#sql #Oracle #PLSQL
Тип объекта:
node(value NUMBER, left REF node, right REF node) — значение и ссылки на детей.
Таблица хранения:
CREATE TABLE nodes OF node; — каждая строка — объект node.
Почему так: используется объектная модель Oracle: связи не по ID, а через REF/DEREF.🧩
2️⃣ Инициализация дерева — init_tree 🌱
Процедура init_tree (node_amount IN INTEGER, root OUT REF node) создаёт дерево и возвращает root.
Обратите внимание: в текущем виде цикл фиксирован на FOR i IN 1 .. node_amount
Внутри — вложенная процедура
insert_node(root IN OUT REF node, new_value IN NUMBER), которая строит бинарное дерево (вставляет меньшее влево, большее/равное вправо).
🧩 Ключевые моменты insert_node:
Если root IS NULL → создаём корень:
INSERT INTO nodes ... RETURNING REF(n) INTO insert_node.root;
Иначе читаем текущий узел:
SELECT DEREF(root) INTO current FROM DUAL;
Рекурсивно вставляем в current.left или current.right:
insert_node(root => current.left, new_value => new_value);
Затем фиксируем изменённую ссылку в таблице:
UPDATE nodes n SET n.left = current.left WHERE REF(n) = insert_node.root; (или n.right = current.right).
Это важно, потому что мы меняли current как локальную копию, и нужно записать обновлённый REF обратно. 🧷
3️⃣ Печать дерева — print_tree 🖨️
print_tree(root IN OUT REF node) делает простой прямой обход (node → left → right):
Пропуск NULL через локальное исключение skip.
Для каждого узла — вывод value и флагов наличия детей (left = yes/no, right = yes/no).
Рекурсивный вызов для current.left и current.right.
Это удобный текстовый взгляд на структуру — помогает убедиться, что вставки шли правильно. 👀
4️⃣ Алгоритм глубины — max_depth 📏
FUNCTION max_depth(root IN REF node) RETURN INTEGER:
База рекурсии: root IS NULL → 0.
Иначе DEREF(root) → current.
Рекурсивно считаем:
leftDepth := max_depth(current.left);
rightDepth := max_depth(current.right);
Возвращаем max(leftDepth, rightDepth) + 1.
Сложность:
По времени — O(n) (каждый узел посещаем ровно один раз).
По памяти стека — O(h), где h — высота дерева.
Поскольку дерево строится случайно (DBMS_RANDOM), оно не сбалансировано, и h может быть близко к n в худшем случае. 🎲
5️⃣ Точка входа блока 📦
init_tree(...) — строим дерево, получаем root.
print_tree(root) — показываем структуру.
DBMS_OUTPUT.put_line('Max depth is ' || max_depth(root)) — вывод глубины.
ROLLBACK; — данные не сохраняются: демонстрация без «мусора» в базе. ✅
6️⃣ Что важно помнить ⚠️
Работа с REF/DEREF требует обновления родителя после рекурсивной вставки — это и делает UPDATE ... WHERE REF(n) = insert_node.root;.
⚠️ Хотите проверить скрипты, но нет базы под рукой - онлайн-песочница
💎 Поддержка канала⁉️
👍 Пальцы вверх — продолжаем разбирать задачи по структурам.
👎 Пальцы вниз — значит, тема не зашла.
Дамы и Господа, выбор всегда за вами 😉
#sql #Oracle #PLSQL
👍2🤯2👎1
🎵«Пусть нету ни кола и ни двора,
Зато не платят Королю налоги
Работники ножа и топора,
Романтики с большой дороги.» — м/ф Бременские музыканты
🚨 Разбор задачи: Дом-вор 🏠💰
Условие:
Даны дома в ряд, каждый из которых имеет некоторую сумму денег.
❌ Нельзя грабить два смежных дома.
💡 Задача: найти максимальную сумму, которую можно украсть.
Пример:
Дома: 2 7 9 3 1
Максимальная сумма: 12
Формула из кода для каждого дома i:
💡 Пояснение:
matrix(i-1) — пропускаем текущий дом.
matrix(i-2) + houses(i) — грабим текущий дом, добавляем к сумме через один дом.
GREATEST выбирает максимальный вариант.
👍 Пальцы вверх — продолжаем разбирать задачи по динамическому программированию.
👎 Пальцы вниз — значит, тема не зашла.
⚠️ Хотите проверить скрипты, но нет базы под рукой - онлайн-песочница
💎 Поддержка канала⁉️
Дамы и Господа, выбор всегда за вами 😉
#sql #Oracle #PLSQL
Зато не платят Королю налоги
Работники ножа и топора,
Романтики с большой дороги.» — м/ф Бременские музыканты
🚨 Разбор задачи: Дом-вор 🏠💰
Условие:
Даны дома в ряд, каждый из которых имеет некоторую сумму денег.
❌ Нельзя грабить два смежных дома.
💡 Задача: найти максимальную сумму, которую можно украсть.
Пример:
Дома: 2 7 9 3 1
Максимальная сумма: 12
DECLARE
TYPE matrix_tab IS TABLE OF NUMBER;
houses matrix_tab := matrix_tab (2, 7, 9, 3, 1);
matrix matrix_tab := matrix_tab ();
PROCEDURE print_matrix (matrix IN OUT NOCOPY matrix_tab) IS
str VARCHAR2 (100);
BEGIN
FOR i IN 1 .. matrix.COUNT LOOP
str := str || ' ' || TO_CHAR(matrix(i));
END LOOP;
DBMS_OUTPUT.put_line(str);
END print_matrix;
PROCEDURE get_thief_matrix (houses IN OUT NOCOPY matrix_tab, matrix IN OUT NOCOPY matrix_tab) IS
BEGIN
FOR i IN 1 .. houses.COUNT LOOP
IF i = 1 THEN
matrix.EXTEND;
matrix(matrix.COUNT) := houses(1);
ELSE
matrix.EXTEND;
matrix(matrix.COUNT) := GREATEST(
matrix(i-1),
CASE WHEN i <= 2 THEN 0 ELSE matrix(i-2) END + houses(i)
);
END IF;
END LOOP;
END get_thief_matrix;
BEGIN
print_matrix(matrix => houses);
get_thief_matrix(houses => houses, matrix => matrix);
print_matrix(matrix => matrix);
END;
Формула из кода для каждого дома i:
matrix(i) := GREATEST(
matrix(i-1),
CASE
WHEN i <= 2 THEN 0
ELSE matrix(i-2)
END + houses(i)
);
💡 Пояснение:
matrix(i-1) — пропускаем текущий дом.
matrix(i-2) + houses(i) — грабим текущий дом, добавляем к сумме через один дом.
GREATEST выбирает максимальный вариант.
👍 Пальцы вверх — продолжаем разбирать задачи по динамическому программированию.
👎 Пальцы вниз — значит, тема не зашла.
⚠️ Хотите проверить скрипты, но нет базы под рукой - онлайн-песочница
💎 Поддержка канала⁉️
Дамы и Господа, выбор всегда за вами 😉
#sql #Oracle #PLSQL
👍3👎2
🎵«Если вы уже устали —
Сели-встали, сели-встали.
Не страшны вам Арктика с Антарктикой.» - В.С. Высоцкий
🚀 Простая задача с уникальными ключами и NULL 📝
Такая задача, вполне, может быть на собесе.
Спасибо подписчику Андрею. 😉
Условие:
Создаем таблицу с уникальным ограничением на два столбца и заполняем её NULL-значениями.
Нужно понять, как работает UNIQUE с NULL.
Какой будет результат?
⚠️ Хотите проверить скрипты, но нет базы под рукой - онлайн-песочница
💎 Поддержка канала⁉️
Ваши решения и сомнения туда👇
#sql #Oracle #PostgreSQL #PLSQL #PLpgSQL
Сели-встали, сели-встали.
Не страшны вам Арктика с Антарктикой.» - В.С. Высоцкий
🚀 Простая задача с уникальными ключами и NULL 📝
Такая задача, вполне, может быть на собесе.
Спасибо подписчику Андрею. 😉
Условие:
Создаем таблицу с уникальным ограничением на два столбца и заполняем её NULL-значениями.
Нужно понять, как работает UNIQUE с NULL.
CREATE TABLE dropme_tt(
id INT,
a INT,
b INT,
CONSTRAINT tt_uk UNIQUE (a, b)
);
INSERT INTO dropme_tt (id, a, b)
SELECT level AS id, NULL AS a, NULL AS b
FROM dual
CONNECT BY level < 10;
SELECT * FROM dropme_tt;
Какой будет результат?
⚠️ Хотите проверить скрипты, но нет базы под рукой - онлайн-песочница
💎 Поддержка канала⁉️
Ваши решения и сомнения туда👇
#sql #Oracle #PostgreSQL #PLSQL #PLpgSQL
👍1👎1
💬 Резюме: ИИ и будущее разработки
Вчера проходил собес (скорее, это была ознакомительная встреча) с CEO одной международной компании.
Мы также поговорили про влияние ИИ на разработку. Оказалось, что мой анализ ситуации полностью совпадает с его анализом и я решил свой анализ здесь озвучить.
🚀 Что умеет ИИ:
Решает SQL-задачи на уровне очень крепкого джуна / начинающего миддла.
Эффективен и быстрый в простых и стандартных задачах.
Инструмент для ускорения работы и тестирования.
⚠️ Ограничения:
В сложных решениях иногда ошибается.
Нужен синьор или эксперт для проверки и корректировки кода. (Пока нужен!!!)
💡 Влияние на рынок IT:
GPT, Gemini, Deepseek и другие меняют рынок:
Рутинная работа выполняется быстрее и качественнее, чем человеком.
В командах остаётся минимум людей (синьоров, экспертов).
💰 Карьерные выводы:
Зарплаты синьоров и экспертов будут расти 🚀.
Джуны будут работать за еду, в надежде когда-то стать синьорами.
✅ Общий вывод:
Ребята! Пока эта канитель внедряется в международных компаниях, но на местах она придет чуть позже.
Пока есть время!
Учитесь, перенимайте чужой опыт, не бойтесь сложных задач.
Именно, решение сложных задач поднимает из рутины.
💎 Поддержка канала⁉️
Вчера проходил собес (скорее, это была ознакомительная встреча) с CEO одной международной компании.
Мы также поговорили про влияние ИИ на разработку. Оказалось, что мой анализ ситуации полностью совпадает с его анализом и я решил свой анализ здесь озвучить.
🚀 Что умеет ИИ:
Решает SQL-задачи на уровне очень крепкого джуна / начинающего миддла.
Эффективен и быстрый в простых и стандартных задачах.
Инструмент для ускорения работы и тестирования.
⚠️ Ограничения:
В сложных решениях иногда ошибается.
Нужен синьор или эксперт для проверки и корректировки кода. (Пока нужен!!!)
💡 Влияние на рынок IT:
GPT, Gemini, Deepseek и другие меняют рынок:
Рутинная работа выполняется быстрее и качественнее, чем человеком.
В командах остаётся минимум людей (синьоров, экспертов).
💰 Карьерные выводы:
Зарплаты синьоров и экспертов будут расти 🚀.
Джуны будут работать за еду, в надежде когда-то стать синьорами.
✅ Общий вывод:
Ребята! Пока эта канитель внедряется в международных компаниях, но на местах она придет чуть позже.
Пока есть время!
Учитесь, перенимайте чужой опыт, не бойтесь сложных задач.
Именно, решение сложных задач поднимает из рутины.
💎 Поддержка канала⁉️
👍2👎1
🚀 Разбор простой, но коварной задачи про UNIQUE и NULL
(идея от подписчика Андрея — спасибо! 😉)
Вопрос: что произойдет при таком коде?
🔎 Разбор:
В UNIQUE участвуют (a, b).
В SQL NULL — это «неизвестное значение».
Два NULL не равны друг другу.
👉 Значит, для UNIQUE это разные значения, и конфликтов нет.
Да и на все NULL значения индекс B-tree не строится.
Итог: все 9 строк спокойно вставятся. Ошибки не будет.
📌 Результат в Oracle и PostgreSQL одинаковый:
Таблица заполнится строками с id = 1..9, а (a, b) везде будут (NULL, NULL).
✅ Важные замечания
Если бы на колонках стоял NOT NULL, фокус не прошёл бы.
👉 С этого и начинается консистентность данных — всегда анализируйте, может ли поле быть пустым.
На практике ограничения (CONSTRAINT ... UNIQUE) чаще создают отдельными командами:
Для DB разницы нет, а вот читать код человеку так проще.
Да и мы контролируем наименование индекса и не позволяем присваивать системные имена.
⚠️ Хотите проверить скрипты, но нет базы под рукой - онлайн-песочница
💎 Поддержка канала⁉️
#RealInterviewTasks #sql #Oracle #PostgreSQL #PLSQL #PLpgSQL
(идея от подписчика Андрея — спасибо! 😉)
Вопрос: что произойдет при таком коде?
CREATE TABLE dropme_tt(
id INT,
a INT,
b INT,
CONSTRAINT tt_uk UNIQUE (a, b)
);
INSERT INTO dropme_tt (id, a, b)
SELECT level, NULL, NULL
FROM dual
CONNECT BY level < 10;
🔎 Разбор:
В UNIQUE участвуют (a, b).
В SQL NULL — это «неизвестное значение».
Два NULL не равны друг другу.
👉 Значит, для UNIQUE это разные значения, и конфликтов нет.
Да и на все NULL значения индекс B-tree не строится.
Итог: все 9 строк спокойно вставятся. Ошибки не будет.
📌 Результат в Oracle и PostgreSQL одинаковый:
Таблица заполнится строками с id = 1..9, а (a, b) везде будут (NULL, NULL).
✅ Важные замечания
Если бы на колонках стоял NOT NULL, фокус не прошёл бы.
👉 С этого и начинается консистентность данных — всегда анализируйте, может ли поле быть пустым.
На практике ограничения (CONSTRAINT ... UNIQUE) чаще создают отдельными командами:
CREATE TABLE dropme_tt
(
id INTEGER,
a INTEGER,
b INTEGER
);
CREATE UNIQUE INDEX dropme_tt_u01
ON dropme_tt (a, b);
Для DB разницы нет, а вот читать код человеку так проще.
Да и мы контролируем наименование индекса и не позволяем присваивать системные имена.
⚠️ Хотите проверить скрипты, но нет базы под рукой - онлайн-песочница
💎 Поддержка канала⁉️
#RealInterviewTasks #sql #Oracle #PostgreSQL #PLSQL #PLpgSQL
👍2👎1
🎵 «Я вытяну счастливую карту…» — Земфира
✨ Сегодня суббота — отдыхаем от задач.
Запускаем рубрику «Полезные ресурсы» 🚀
🔗 Diffchecker (https://www.diffchecker.com/)
— простое и удобное web-средство для сравнения текста.
📌 Где может пригодиться:
быстро проверить изменения в SQL-скрипте или конфигурации;
сравнить два варианта кода;
увидеть, что именно поменялось в тексте документа.
⚡ Работает прямо в браузере, без установки.
💎 Поддержка канала⁉️
💡 Если у Вас есть свои полезные ссылки — не жадничайте, делитесь в комментах! 😉
#tools
✨ Сегодня суббота — отдыхаем от задач.
Запускаем рубрику «Полезные ресурсы» 🚀
🔗 Diffchecker (https://www.diffchecker.com/)
— простое и удобное web-средство для сравнения текста.
📌 Где может пригодиться:
быстро проверить изменения в SQL-скрипте или конфигурации;
сравнить два варианта кода;
увидеть, что именно поменялось в тексте документа.
⚡ Работает прямо в браузере, без установки.
💎 Поддержка канала⁉️
💡 Если у Вас есть свои полезные ссылки — не жадничайте, делитесь в комментах! 😉
#tools
👍3👎1
🎵 «На ель она взлетела,
А может, не взлетела,
А может быть, на пальму
Ворона взобралась» - Э. Успенский
Сегодня воскресенье, а значит — без задач ✨
Сегодня про теоретические вопросы на собесах.
Честно говоря, я не считаю это валидным способом проверки разработчика.
(Может быть, потому что сам не смогу перечислить все формы нормализации данных — они мне интуитивно понятны, но выучить не получается 🤷♂️).
Тем не менее, когда я сам был интервьюером, не раз приходилось задавать классический вопрос:
👉 «Что такое ACID?»
📌 Обычно все знают расшифровку:
Atomicity (атомарность)
Consistency (консистентность)
Isolation (изоляция)
Durability (постоянство)
Но вот зачем эти критерии нужны и как именно понимать Consistency — отвечают далеко не все.
💡 В итоге у нас есть два вопроса для обсуждения:
Зачем вообще нужны критерии ACID?
Как именно вы понимаете Consistency (консистентность)?
💎 Поддержка канала⁉️
💬 Пишите в комментах, всё что в голову придет👇
#RealInterviewTasks #sql #Oracle #PostgreSQL #PLSQL #PLpgSQL
А может, не взлетела,
А может быть, на пальму
Ворона взобралась» - Э. Успенский
Сегодня воскресенье, а значит — без задач ✨
Сегодня про теоретические вопросы на собесах.
Честно говоря, я не считаю это валидным способом проверки разработчика.
(Может быть, потому что сам не смогу перечислить все формы нормализации данных — они мне интуитивно понятны, но выучить не получается 🤷♂️).
Тем не менее, когда я сам был интервьюером, не раз приходилось задавать классический вопрос:
👉 «Что такое ACID?»
📌 Обычно все знают расшифровку:
Atomicity (атомарность)
Consistency (консистентность)
Isolation (изоляция)
Durability (постоянство)
Но вот зачем эти критерии нужны и как именно понимать Consistency — отвечают далеко не все.
💡 В итоге у нас есть два вопроса для обсуждения:
Зачем вообще нужны критерии ACID?
Как именно вы понимаете Consistency (консистентность)?
💎 Поддержка канала⁉️
💬 Пишите в комментах, всё что в голову придет👇
#RealInterviewTasks #sql #Oracle #PostgreSQL #PLSQL #PLpgSQL
👎1
DB developers channel
🎵 «На ель она взлетела, А может, не взлетела, А может быть, на пальму Ворона взобралась» - Э. Успенский Сегодня воскресенье, а значит — без задач ✨ Сегодня про теоретические вопросы на собесах. Честно говоря, я не считаю это валидным способом проверки разработчика.…
Вчера в комментах произошёл очень показательный диалог.
Комменты получились интереснее поста.
Я уважаемому подписчику (DEN) весьма благодарен 🙏 (к сожалению, не знаю, как Вас зовут).
Примерно так или почти так и звучит ответ на простые и «ничего незначащие» вопросы на собеседованиях.
Вот разбор простыми словами.
Про Consistency в ACID:
👉 если две сессии одновременно запускают один и тот же запрос — они должны получить один и тот же результат.
Важно: это не про целостность данных в таблицах (FK, ограничения, каскады).
Это про то, что база показывает всем транзакциям одну и ту же «картину мира».
Зачем нужны критерии ACID?
Чтобы отличать настоящую DB от простого или сложного «файлового хранилища».
База гарантирует в многопользовательской среде корректную обработку и сохранение транзакций.
📌 Но есть системы, которые называются «базами данных», хотя полного ACID в них нет:
MongoDB (в ранних версиях классический ACID не обеспечивался по умолчанию).
Cassandra и другие NoSQL (делают ставку на масштабирование, жертвуя частью гарантий).
Redis (in-memory key-value store, без полноценного ACID).
💡 Плюсы таких решений: скорость и горизонтальное масштабирование.
❗ Минус: «железобетонной гарантии» ACID нет, и это важно учитывать при проектировании.
⚠️ Хотите проверить скрипты, но нет базы под рукой - онлайн-песочница
💎 Поддержка канала⁉️
#RealInterviewTasks #sql #Oracle #PostgreSQL #PLSQL #PLpgSQL
Комменты получились интереснее поста.
Я уважаемому подписчику (DEN) весьма благодарен 🙏 (к сожалению, не знаю, как Вас зовут).
Примерно так или почти так и звучит ответ на простые и «ничего незначащие» вопросы на собеседованиях.
Вот разбор простыми словами.
Про Consistency в ACID:
👉 если две сессии одновременно запускают один и тот же запрос — они должны получить один и тот же результат.
Важно: это не про целостность данных в таблицах (FK, ограничения, каскады).
Это про то, что база показывает всем транзакциям одну и ту же «картину мира».
Зачем нужны критерии ACID?
Чтобы отличать настоящую DB от простого или сложного «файлового хранилища».
База гарантирует в многопользовательской среде корректную обработку и сохранение транзакций.
📌 Но есть системы, которые называются «базами данных», хотя полного ACID в них нет:
MongoDB (в ранних версиях классический ACID не обеспечивался по умолчанию).
Cassandra и другие NoSQL (делают ставку на масштабирование, жертвуя частью гарантий).
Redis (in-memory key-value store, без полноценного ACID).
💡 Плюсы таких решений: скорость и горизонтальное масштабирование.
❗ Минус: «железобетонной гарантии» ACID нет, и это важно учитывать при проектировании.
⚠️ Хотите проверить скрипты, но нет базы под рукой - онлайн-песочница
💎 Поддержка канала⁉️
#RealInterviewTasks #sql #Oracle #PostgreSQL #PLSQL #PLpgSQL
👍4👎1🤔1
Допустим, Вы получили входящий параметр income_collection типа IS TABLE OF NUMBER. Вы знаете, что там могут быть дубли, которые нужно проигнорировать. Каким бы способом Вы бы это сделали?
Anonymous Poll
34%
Функция SET
55%
SELECT DISTINCT (с TABLE() оператором)
10%
Я знаю 3 вариант (Могу поделиться в комментах)
👎1
DB developers channel
Допустим, Вы получили входящий параметр income_collection типа IS TABLE OF NUMBER. Вы знаете, что там могут быть дубли, которые нужно проигнорировать. Каким бы способом Вы бы это сделали?
ORACLE_SET_TEST.sql
11.1 KB
🔥 Небольшой эксперимент с Oracle коллекциями
Я решил проверить, что реально происходит «под капотом», когда мы убираем дубликаты из коллекции TABLE OF NUMBER.
Сравнил два способа:
1️⃣ SET(collection)
2️⃣ SELECT DISTINCT FROM TABLE(collection)
Для чистоты — прогнал на миллионе элементов, собирал статистику из v$mystat (consistent gets, pga/uga, sorts, cpu и т.д.).
📊 Результаты
1️⃣ SET(collection)
time: +000000000 00:00:00.131000000
2️⃣ SELECT DISTINCT FROM TABLE(collection)
time: +000000000 00:00:00.125000000
💡Результат удивительный. Второй вариант быстрее, несмотря на смену контекста с PL/SQL на SQL, выгрузку BULK COLLECT.
У функции SET явно есть проблемы.
⚠️ Хотите проверить скрипты, но нет базы под рукой - онлайн-песочница
💎 Поддержка канала⁉️
#Cases
Я решил проверить, что реально происходит «под капотом», когда мы убираем дубликаты из коллекции TABLE OF NUMBER.
Сравнил два способа:
1️⃣ SET(collection)
2️⃣ SELECT DISTINCT FROM TABLE(collection)
Для чистоты — прогнал на миллионе элементов, собирал статистику из v$mystat (consistent gets, pga/uga, sorts, cpu и т.д.).
📊 Результаты
1️⃣ SET(collection)
time: +000000000 00:00:00.131000000
2️⃣ SELECT DISTINCT FROM TABLE(collection)
time: +000000000 00:00:00.125000000
💡Результат удивительный. Второй вариант быстрее, несмотря на смену контекста с PL/SQL на SQL, выгрузку BULK COLLECT.
У функции SET явно есть проблемы.
⚠️ Хотите проверить скрипты, но нет базы под рукой - онлайн-песочница
💎 Поддержка канала⁉️
#Cases
🔥7👍2👎1
🎵 «Ваше благородие, госпожа победа,
значит, моя песенка до конца не спета!
Перестаньте, черти,
клясться на крови...
Не везёт мне в смерти,
повезёт в любви.» — Булат Окуджава
Друзья, канал набрал 100 подписчиков меньше чем за месяц 🎉
Для меня это победа — он уже вышел далеко за рамки круга моих знакомых.
Изначально это задумывалось как публичная записная книжка, но постепенно канал стал чем-то большим — отдельным событием, живым и самостоятельным 🚀.
👋 Немного обо мне:
Меня зовут Поликарпов Кирилл Вадимович, я Senior DB Developer.
💾 Опыт — Oracle, PostgreSQL, MS SQL.
Но честно признаюсь — Oracle мне ближе всего ❤️.
🏦 СКБ-Банк — моя первая профессиональная работа как разработчика DB (2017 год).
Воспоминания тёплые: весёлое и живое время, отличная команда, дружеская атмосфера. Ребята, спасибо за старт! 🙌
💍 Кольцо Урала — для меня это особенное место. Для меня это лучшее место на земле. Я именно там состоялся как разработчик и понял что это моё.
Коллеги из Кольца я Вас не просто люблю - я Вас обожаю, преобожаю. Нигде и никогда мне не было так интересно, продуктивно и комфортно, как работать рядом с Вами.
🐹 Банк Хоум Кредит («Хомяк») — большой банк со своими плюсами и минусами. Здесь я встретил много хороших людей и настоящего друга — Ирека Вафина. Ирек, спасибо тебе, ты крутой человек и сильный разработчик 🤝.
🚕 Такси Максим — отличное место, если хочется много работать и при этом оставаться в позитивной атмосфере. Команда «Бобры» 🦫, которой я имел честь руководить, навсегда в моём сердце. И да, связь с аватаркой канала не случайна 😉.
🌍 Сейчас я работаю в международной процессинговой компании.
Здесь крутые ребята. Требования высокие, работать тяжело, но невероятно интересно. Спасибо и вам, коллеги 🙏.
Особое спасибо подписчикам, которых я не знаю лично. Рад видеть вас среди своих читателей 💫.
🎯 Цель: 1000 подписчиков до конца года.
⚙️ Как пишутся посты?
Я пишу «рыбу» ✍️, а затем прошу ИИ помочь с оформлением, эмодзи и упрощением сложных формулировок. Мы с ИИ — сильная команда 🤖✨.
Если хотите помочь каналу:
1️⃣ Главное — предлагайте задачи, темы и фичи. Моего материала хватит ещё на 3–4 месяца, а Ваши идеи сделают канал интереснее.
2️⃣ Если у вас есть знакомые, которым близка тема БД, — поделитесь с ними ссылкой.
Спасибо каждому из вас ❤️
значит, моя песенка до конца не спета!
Перестаньте, черти,
клясться на крови...
Не везёт мне в смерти,
повезёт в любви.» — Булат Окуджава
Друзья, канал набрал 100 подписчиков меньше чем за месяц 🎉
Для меня это победа — он уже вышел далеко за рамки круга моих знакомых.
Изначально это задумывалось как публичная записная книжка, но постепенно канал стал чем-то большим — отдельным событием, живым и самостоятельным 🚀.
👋 Немного обо мне:
Меня зовут Поликарпов Кирилл Вадимович, я Senior DB Developer.
💾 Опыт — Oracle, PostgreSQL, MS SQL.
Но честно признаюсь — Oracle мне ближе всего ❤️.
🏦 СКБ-Банк — моя первая профессиональная работа как разработчика DB (2017 год).
Воспоминания тёплые: весёлое и живое время, отличная команда, дружеская атмосфера. Ребята, спасибо за старт! 🙌
💍 Кольцо Урала — для меня это особенное место. Для меня это лучшее место на земле. Я именно там состоялся как разработчик и понял что это моё.
Коллеги из Кольца я Вас не просто люблю - я Вас обожаю, преобожаю. Нигде и никогда мне не было так интересно, продуктивно и комфортно, как работать рядом с Вами.
🐹 Банк Хоум Кредит («Хомяк») — большой банк со своими плюсами и минусами. Здесь я встретил много хороших людей и настоящего друга — Ирека Вафина. Ирек, спасибо тебе, ты крутой человек и сильный разработчик 🤝.
🚕 Такси Максим — отличное место, если хочется много работать и при этом оставаться в позитивной атмосфере. Команда «Бобры» 🦫, которой я имел честь руководить, навсегда в моём сердце. И да, связь с аватаркой канала не случайна 😉.
🌍 Сейчас я работаю в международной процессинговой компании.
Здесь крутые ребята. Требования высокие, работать тяжело, но невероятно интересно. Спасибо и вам, коллеги 🙏.
Особое спасибо подписчикам, которых я не знаю лично. Рад видеть вас среди своих читателей 💫.
🎯 Цель: 1000 подписчиков до конца года.
⚙️ Как пишутся посты?
Я пишу «рыбу» ✍️, а затем прошу ИИ помочь с оформлением, эмодзи и упрощением сложных формулировок. Мы с ИИ — сильная команда 🤖✨.
Если хотите помочь каналу:
1️⃣ Главное — предлагайте задачи, темы и фичи. Моего материала хватит ещё на 3–4 месяца, а Ваши идеи сделают канал интереснее.
2️⃣ Если у вас есть знакомые, которым близка тема БД, — поделитесь с ними ссылкой.
Спасибо каждому из вас ❤️
👍9🔥5👏2👎1
DB developers channel
📌 Из предыдущего опроса стало ясно, что задачи на алгоритмы Вам интересны. Я прорешал около 💯 задач и понял, что почти все они делятся на 5 категорий:
Продолжим или закончим решать задачи по алгоритмам средствами процедурного языка. Я выбрал 5 задач из 5 тем: работа с массивами, работа со строками, работа с матрицами, структуры данных, динамическое программирование.
Anonymous Poll
12%
Объединение массивов: Объедините два отсортированных массива в один отсортированный массив.
0%
Переворот строки: Переверните слова в строке.
8%
Максимальный квадрат: Найдите самый большой квадрат, состоящий из единиц в двоичной матрице.
8%
Зеркальное отображение дерева: Преобразуйте бинарное дерево в его зеркальное отображение.
0%
Путь робота: Найти число уник. путей для работа из (1,1) в (m,n), если умеет двигаться вправо/вниз?
4%
Переворот строки: Переверните слова в строке.
56%
Все интересны
12%
Русским языком повторяю мне мне это неинтересно.
👍5👎1
✨ «Снежная королева:
— Кай, составь слово «Вечность» — и будешь свободен!
Кай:
— Сколько ни пробую, всё время выходит «ЖОПА»…
Снежная королева:
— Ну, в принципе, то же самое.» - детский анекдот.
🏛 Архитектура кода
Как и обещал подписчику Глебу Буланцеву: набрали 💯 — начинаю серию постов про архитектуру кода.
💡 Каждый разработчик уверен: его код пусть и не идеален, но всё же оптимален в данных обстоятельствах. И это абсолютно нормально — иначе можно утонуть в бесконечных сомнениях.
В этих постах я делюсь своими мыслями и опытом и, естественно, не претендую на вселенскую истину.
📌 Задача
Есть база данных (буду рассматривать Oracle, но подход универсален).
Есть несколько приложений, которые её используют.
Нужно смоделировать архитектуру кода так, чтобы он был:
✅ безопасен
✅ контролируем
✅ гибок
✅ удобен и понятен
Согласитесь, задачка непростая.
🧩 Модель архитектуры
Предлагаю делить код на 3 уровня:
1) 🔹 API-уровень
Это «витрина» для приложения.
Для каждого приложения создаём свой пакет с методами (например, APPLICATION_API или APPLICATION_SRV).
Здесь можно:
проверить входящие параметры,
отдавать курсоры наружу,
вызвать операцию из следующего уровня.
Здесь нельзя:
менять данные в таблицах,
хранить бизнес-логику,
выполнять валидации.
Главная цель: разграничение прав доступа и первичная проверка входа.
2) 🔹 OPER-уровень
Здесь живёт бизнес-логика.
Каждый внешний метод = отдельная операция.
Допустим вызов одной операции из другой, но запрещено обращаться к API-методам отсюда.
Иногда уровень делят ещё на подуровни (например LVL1 и LVL2), если нужно предварительно распарсить входящие JSON/XML.
3) 🔹 Табличный уровень
Самый простой, но ключевой.
Это точка работы с одной строкой таблицы:
вставка,
обновление,
удаление,
чтение,
блокировка.
Здесь же дублируется табличная валидация (те же ограничения, что и на уровне таблицы в БД)
Заполнение и или обновление технических полей.
🚫 Запрещено вызывать другие пакеты. Этот уровень должен быть полностью изолирован.
Чуть позже я опубликую упрошенный вариант кода. Где на примере, мы продолжим разговор уже в обратном направлении от таблиц до API уровня.
⚠️ Хотите проверить скрипты, но нет базы под рукой - онлайн-песочница
💎 Поддержка канала⁉️
💬 Если есть возражение, согласие или негодование — не сдерживайте себя👇
#CodeArchitecture
— Кай, составь слово «Вечность» — и будешь свободен!
Кай:
— Сколько ни пробую, всё время выходит «ЖОПА»…
Снежная королева:
— Ну, в принципе, то же самое.» - детский анекдот.
🏛 Архитектура кода
Как и обещал подписчику Глебу Буланцеву: набрали 💯 — начинаю серию постов про архитектуру кода.
💡 Каждый разработчик уверен: его код пусть и не идеален, но всё же оптимален в данных обстоятельствах. И это абсолютно нормально — иначе можно утонуть в бесконечных сомнениях.
В этих постах я делюсь своими мыслями и опытом и, естественно, не претендую на вселенскую истину.
📌 Задача
Есть база данных (буду рассматривать Oracle, но подход универсален).
Есть несколько приложений, которые её используют.
Нужно смоделировать архитектуру кода так, чтобы он был:
✅ безопасен
✅ контролируем
✅ гибок
✅ удобен и понятен
Согласитесь, задачка непростая.
🧩 Модель архитектуры
Предлагаю делить код на 3 уровня:
1) 🔹 API-уровень
Это «витрина» для приложения.
Для каждого приложения создаём свой пакет с методами (например, APPLICATION_API или APPLICATION_SRV).
Здесь можно:
проверить входящие параметры,
отдавать курсоры наружу,
вызвать операцию из следующего уровня.
Здесь нельзя:
менять данные в таблицах,
хранить бизнес-логику,
выполнять валидации.
Главная цель: разграничение прав доступа и первичная проверка входа.
2) 🔹 OPER-уровень
Здесь живёт бизнес-логика.
Каждый внешний метод = отдельная операция.
Допустим вызов одной операции из другой, но запрещено обращаться к API-методам отсюда.
Иногда уровень делят ещё на подуровни (например LVL1 и LVL2), если нужно предварительно распарсить входящие JSON/XML.
3) 🔹 Табличный уровень
Самый простой, но ключевой.
Это точка работы с одной строкой таблицы:
вставка,
обновление,
удаление,
чтение,
блокировка.
Здесь же дублируется табличная валидация (те же ограничения, что и на уровне таблицы в БД)
Заполнение и или обновление технических полей.
🚫 Запрещено вызывать другие пакеты. Этот уровень должен быть полностью изолирован.
Чуть позже я опубликую упрошенный вариант кода. Где на примере, мы продолжим разговор уже в обратном направлении от таблиц до API уровня.
⚠️ Хотите проверить скрипты, но нет базы под рукой - онлайн-песочница
💎 Поддержка канала⁉️
💬 Если есть возражение, согласие или негодование — не сдерживайте себя👇
#CodeArchitecture
👍1👎1