Допустим, Вы получили входящий параметр 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
"Там, где, сливаяся, шумят,
Обнявшись, будто две сестры,
Струи Арагвы и Куры" — М.Ю. Лермонтов 🌊💫
📌 Разбор задачи про объединение массивов 🛠️
Объединение массивов: Объедините два отсортированных массива в один отсортированный массив.
Даны два отсортированных массива с повторами:
Нужно получить массив: 1 2 3 4 5 6 7 8 9 ✅
🛠️ Алгоритм интуитивно понятен.
Идём по двум массивам одновременно,
в новый массив попадает только меньшее или равное значение.
Счетчики массивов либо по одному, либо по другому увеличиваются +1
Соединим таблицы и добавим хинт USE_MERGE, подсказывающий оптимизатору использовать MERGE JOIN:
Видим, что Oracle отсортировал данные и применил алгоритм, похожий на наш первоначальный 👏
⚠️ Хотите проверить скрипты, но нет базы под рукой - онлайн-песочница
💎 Поддержка канала⁉️
Пишите, если есть что писать. Ставьте эмодзи если вызывает эмоции👇
#sql #Oracle #PLSQL
Обнявшись, будто две сестры,
Струи Арагвы и Куры" — М.Ю. Лермонтов 🌊💫
📌 Разбор задачи про объединение массивов 🛠️
Объединение массивов: Объедините два отсортированных массива в один отсортированный массив.
Даны два отсортированных массива с повторами:
set_1 = (1,2,2,5,7,9)
set_2 = (1,2,3,4,5,5,6,8)Нужно получить массив: 1 2 3 4 5 6 7 8 9 ✅
🛠️ Алгоритм интуитивно понятен.
Идём по двум массивам одновременно,
в новый массив попадает только меньшее или равное значение.
Счетчики массивов либо по одному, либо по другому увеличиваются +1
sql
🔄
DECLARE
TYPE set_tab IS TABLE OF INTEGER;
set_1 set_tab := set_tab (1, 2, 2, 5, 7, 9);
set_2 set_tab := set_tab (1, 2, 3, 4, 5, 5, 6, 8);
index_1# INTEGER := 1;
index_2# INTEGER := 1;
newSet set_tab := set_tab ();
BEGIN
WHILE (index_1# <= set_1.COUNT OR index_2# <= set_2.COUNT) LOOP
IF index_1# > set_1.COUNT THEN
newSet.EXTEND;
newSet(newSet.COUNT) := set_2(index_2#);
index_2# := index_2# + 1;
CONTINUE;
END IF;
IF index_2# > set_2.COUNT THEN
newSet.EXTEND;
newSet(newSet.COUNT) := set_1(index_1#);
index_1# := index_1# + 1;
CONTINUE;
END IF;
IF set_1(index_1#) <= set_2(index_2#) THEN
IF newSet IS EMPTY OR newSet(newSet.COUNT) != set_1(index_1#) THEN
newSet.EXTEND;
newSet(newSet.COUNT) := set_1(index_1#);
END IF;
index_1# := index_1# + 1;
CONTINUE;
END IF;
IF set_1(index_1#) > set_2(index_2#) THEN
IF newSet IS EMPTY OR newSet(newSet.COUNT) != set_2(index_2#) THEN
newSet.EXTEND;
newSet(newSet.COUNT) := set_2(index_2#);
END IF;
index_2# := index_2# + 1;
CONTINUE;
END IF;
END LOOP;
DECLARE
str VARCHAR2(4000);
BEGIN
FOR i IN 1 .. newSet.COUNT LOOP
str := str ' ' TO_CHAR(newSet(i));
END LOOP;
DBMS_OUTPUT.put_line(str);
END;
END;
Сама по себе задача простая, но она перекликается с известным способом соединения таблиц MERGE 🔗
Merge Join работает именно по такому принципу: оба набора данных сначала сортируются, а потом сканируются «с двух концов» одновременно 🔄.
В чём отличие — он сравнивает не сами значения, а по условию равенства вычисляет хэш-функции (STANDARD_HASH('myValue', 'MD5')) 🧩.
Для новичков приведу пример:
SQL
CREATE TABLE table_1
(
id NUMBER
);
CREATE TABLE table_2
(
id NUMBER
);
INSERT INTO table_1 (id)
SELECT LEVEL AS id
FROM DUAL
CONNECT BY LEVEL < 10;
INSERT INTO table_2 (id)
SELECT LEVEL AS id
FROM DUAL
CONNECT BY LEVEL < 100;
SELECT /*+ LEADING (t1 t2) USE_MERGE(t2)*/
t1.id
FROM table_1 t1 INNER JOIN table_2 t2 ON (t1.id = t2.id);
Соединим таблицы и добавим хинт USE_MERGE, подсказывающий оптимизатору использовать MERGE JOIN:
SQL
--------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost | Time |
--------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 9 | 54 | 8 | 00:00:01 |
| 1 | MERGE JOIN | | 9 | 54 | 8 | 00:00:01 |
| 2 | SORT JOIN | | 9 | 27 | 4 | 00:00:01 |
| 3 | TABLE ACCESS FULL | TABLE_1 | 9 | 27 | 3 | 00:00:01 |
| * 4 | SORT JOIN | | 99 | 297 | 4 | 00:00:01 |
| 5 | TABLE ACCESS FULL | TABLE_2 | 99 | 297 | 3 | 00:00:01 |
--------------------------------------------------------------------------Видим, что Oracle отсортировал данные и применил алгоритм, похожий на наш первоначальный 👏
⚠️ Хотите проверить скрипты, но нет базы под рукой - онлайн-песочница
💎 Поддержка канала⁉️
Пишите, если есть что писать. Ставьте эмодзи если вызывает эмоции👇
#sql #Oracle #PLSQL
👍8👎1🤓1
🎵 «Позабыты хлопоты
Остановлен бег
Вкалывают роботы
Счастлив человек!» — из к/ф "Приключения Электроника"
📌 Разбор задачи: Переворот строки
Сегодня у нас на разборе задача: 🔄 перевернуть слова в строке, сохраняя пробелы на своих местах.
⚙️ Важное ограничение: решение процедурными методами.
Исходная строка и нужный результат:
' 123 456 234 789 9 '
' 321 654 432 987 9 '
👉 Алгоритм:
Идём посимвольно по строке.
Если встречаем пробел — просто добавляем его в результат.
Если начинается слово — ищем его длину.
Переписываем слово в обратном порядке.
Двигаем указатель дальше.
📜 Решение на PL/SQL (первый вариант):
🤖 Но машина оказалась умнее. ЧатGPT выдал решение оптимальнее.
Иногда так и хочется быть Джоном Коннором!
Сцену, когда Арни опускается в раскалённый металл, воспринимаю по-другому чем прежде.😉
📜 Оптимизированный вариант:
✨ Отличия от первого варианта:
🚫 Нет вложенного цикла для подсчёта длины слова.
🔄 Переворот делаем "на лету" при сборке.
📖 Код читается проще и выглядит короче.
⚠️ Хотите проверить скрипты, но нет базы под рукой - онлайн-песочница
💎 Поддержка канала⁉️
🤔 А какое чувство к машинам испытываете вы? Поделитесь в комментах 👇
#sql #Oracle #PLSQL
Остановлен бег
Вкалывают роботы
Счастлив человек!» — из к/ф "Приключения Электроника"
📌 Разбор задачи: Переворот строки
Сегодня у нас на разборе задача: 🔄 перевернуть слова в строке, сохраняя пробелы на своих местах.
⚙️ Важное ограничение: решение процедурными методами.
Исходная строка и нужный результат:
' 123 456 234 789 9 '
' 321 654 432 987 9 '
👉 Алгоритм:
Идём посимвольно по строке.
Если встречаем пробел — просто добавляем его в результат.
Если начинается слово — ищем его длину.
Переписываем слово в обратном порядке.
Двигаем указатель дальше.
📜 Решение на PL/SQL (первый вариант):
DECLARE
str VARCHAR2 (4000) := ' 123 456 234 789 9 ';
indexStart INTEGER;
newStr VARCHAR2 (4000);
index# INTEGER := 1;
BEGIN
WHILE index# < LENGTH (str) LOOP
IF SUBSTR (str, index#, 1) = ' ' THEN
newStr := newStr || ' ';
index# := index# + 1;
ELSE
indexStart := 0;
FOR j IN 1 .. LENGTH (str) LOOP
IF SUBSTR (str, index# + j - 1, 1) = ' ' THEN
EXIT;
ELSE
indexStart := indexStart + 1;
END IF;
END LOOP;
FOR q IN 1 .. indexStart LOOP
newStr := newStr || SUBSTR (str, index# + indexStart - q, 1);
END LOOP;
index# := index# + indexStart;
END IF;
END LOOP;
DBMS_OUTPUT.put_line (str);
DBMS_OUTPUT.put_line (newStr);
END;
🤖 Но машина оказалась умнее. ЧатGPT выдал решение оптимальнее.
Иногда так и хочется быть Джоном Коннором!
Сцену, когда Арни опускается в раскалённый металл, воспринимаю по-другому чем прежде.😉
📜 Оптимизированный вариант:
DECLARE
str VARCHAR2(4000) := ' 123 456 234 789 9 ';
word VARCHAR2(4000);
newStr VARCHAR2(4000) := '';
i PLS_INTEGER := 1;
ch CHAR(1);
BEGIN
WHILE i <= LENGTH(str) LOOP
ch := SUBSTR(str, i, 1);
IF ch = ' ' THEN
newStr := newStr || ch;
i := i + 1;
ELSE
word := '';
WHILE i <= LENGTH(str) AND SUBSTR(str, i, 1) <> ' ' LOOP
word := SUBSTR(str, i, 1) || word;
i := i + 1;
END LOOP;
newStr := newStr || word;
END IF;
END LOOP;
DBMS_OUTPUT.put_line(str);
DBMS_OUTPUT.put_line(newStr);
END;
✨ Отличия от первого варианта:
🚫 Нет вложенного цикла для подсчёта длины слова.
🔄 Переворот делаем "на лету" при сборке.
📖 Код читается проще и выглядит короче.
⚠️ Хотите проверить скрипты, но нет базы под рукой - онлайн-песочница
💎 Поддержка канала⁉️
🤔 А какое чувство к машинам испытываете вы? Поделитесь в комментах 👇
#sql #Oracle #PLSQL
👍4🤓2👾2👎1
🎵 «Хочешь сладких апельсинов?
Хочешь вслух рассказов длинных?
Хочешь, я взорву все звёзды
Что мешают спать?» — Земфира
✨ Сегодня суббота — отдыхаем от задач.
Рубрика «Полезные ресурсы»
Есть желание «вскрыть» содержимое wrapped-пакетов?
👉 https://www.codecrete.net/UnwrapIt/
Копируем и вставляем содержимое поля text.
⚠️В ресурс вставляем не сам запрос, а содержимое поля из выполненного в базе запроса:
И наслаждаемся «индусским» кодом 😎
⚡ Работает прямо в браузере, без установки.
⚠️ Хотите проверить скрипты, но нет базы под рукой - онлайн-песочница
💎 Поддержка канала⁉️
💡 Если у вас есть свои полезные ссылки — не жадничайте, делитесь в комментариях!
#tools #Oracle #PLSQL
Хочешь вслух рассказов длинных?
Хочешь, я взорву все звёзды
Что мешают спать?» — Земфира
✨ Сегодня суббота — отдыхаем от задач.
Рубрика «Полезные ресурсы»
Есть желание «вскрыть» содержимое wrapped-пакетов?
👉 https://www.codecrete.net/UnwrapIt/
Копируем и вставляем содержимое поля text.
⚠️В ресурс вставляем не сам запрос, а содержимое поля из выполненного в базе запроса:
SELECT line, text
FROM ALL_SOURCE
WHERE owner = 'SYS'
AND name = 'DBMS_SCHEDULER'
AND type = 'PACKAGE BODY'
ORDER BY line;
И наслаждаемся «индусским» кодом 😎
⚡ Работает прямо в браузере, без установки.
⚠️ Хотите проверить скрипты, но нет базы под рукой - онлайн-песочница
💎 Поддержка канала⁉️
💡 Если у вас есть свои полезные ссылки — не жадничайте, делитесь в комментариях!
#tools #Oracle #PLSQL
🆒4👎1
🎵 «Труд мой
любому
труду
родствен.
Взгляните —
сколько я потерял,
какие
издержки
в моем производстве
и сколько тратится
на материал.»
— В.В. Маяковский
📌 Разбор задачи: Максимальный квадрат (процедурными методами)
🧩 Условие:
Дана двоичная матрица (элементы 0 и 1).
Нужно найти самый большой квадрат, состоящий только из единиц.
🧩 Пример матрицы
0 1 1 0 1 0 1
1 1 1 1 1 0 0
0 1 1 1 1 1 0
0 1 1 1 1 1 0
0 0 1 1 1 0 0
🔵 В этой матрице максимальный квадрат состоит из 3x3 единиц (сверху слева от позиции (2,2)):
0 1 1 0 1 0 1
1 🔵 🔵 🔵 1 0 0
0 🔵 🔵 🔵 1 1 0
0 🔵 🔵 🔵 1 1 0
0 0 1 1 1 0 0
💻 Решение (PL/SQL):
⚡ Итог: выводит координаты i, j и размер стороны найденного квадрата.
👍 Пальцы вверх — продолжаем разбирать задачи методами процедурного языка.
👎 Пальцы вниз — значит, тема надоела.
⚠️ Хотите проверить скрипты, но нет базы под рукой - онлайн-песочница
💎 Поддержка канала⁉️
#️⃣ #sql #Oracle #PLSQL
любому
труду
родствен.
Взгляните —
сколько я потерял,
какие
издержки
в моем производстве
и сколько тратится
на материал.»
— В.В. Маяковский
📌 Разбор задачи: Максимальный квадрат (процедурными методами)
🧩 Условие:
Дана двоичная матрица (элементы 0 и 1).
Нужно найти самый большой квадрат, состоящий только из единиц.
🧩 Пример матрицы
0 1 1 0 1 0 1
1 1 1 1 1 0 0
0 1 1 1 1 1 0
0 1 1 1 1 1 0
0 0 1 1 1 0 0
🔵 В этой матрице максимальный квадрат состоит из 3x3 единиц (сверху слева от позиции (2,2)):
0 1 1 0 1 0 1
1 🔵 🔵 🔵 1 0 0
0 🔵 🔵 🔵 1 1 0
0 🔵 🔵 🔵 1 1 0
0 0 1 1 1 0 0
💻 Решение (PL/SQL):
SQL
DDECLARE
TYPE row_type IS TABLE OF NUMBER;
TYPE matrix_type IS TABLE OF row_type;
matrix matrix_type
:= matrix_type (row_type (0, 1, 1, 0, 1, 0, 1),
row_type (1, 1, 1, 1, 1, 0, 0),
row_type (0, 1, 1, 1, 1, 1, 0),
row_type (0, 1, 1, 1, 1, 1, 0),
row_type (0, 0, 1, 1, 1, 0, 0));
TYPE square IS RECORD
(
i INTEGER,
j INTEGER,
side_amount INTEGER
);
maxSquare square;
currentSquare square;
BEGIN
FOR i IN 1 .. matrix.COUNT LOOP
FOR j IN 1 .. matrix (i).COUNT LOOP
IF matrix (i) (j) = 1 THEN
currentSquare.i := i;
currentSquare.j := j;
--DBMS_OUTPUT.put_line ('--');
--DBMS_OUTPUT.put_line ('(' || TO_CHAR (i) || ', ' || TO_CHAR (j) || ')');
DECLARE
maxSide INTEGER := 1;
skip EXCEPTION;
BEGIN
WHILE maxSide <= LEAST (matrix.COUNT - i, matrix (i).COUNT - j) LOOP
/*
j
i 1 1 1 ..
1 1 0 ..
1 1 1 ..
. . . ..
*/
FOR q IN 0 .. maxSide LOOP
--DBMS_OUTPUT.put_line ('(' || TO_CHAR (i + maxSide) || ', ' || TO_CHAR (j + q) || ')');
--DBMS_OUTPUT.put_line ('(' || TO_CHAR (i + q) || ', ' || TO_CHAR (j + maxSide) || ')');
IF matrix (i + maxSide) (j + q) = 0 OR matrix (i + q) (j + maxSide) = 0 THEN
RAISE skip;
END IF;
END LOOP;
maxSide := maxSide + 1;
END LOOP;
currentSquare.side_amount := GREATEST (NVL (currentSquare.side_amount, 0), maxSide);
EXCEPTION
WHEN skip THEN
currentSquare.side_amount := GREATEST (NVL (currentSquare.side_amount, 0), maxSide);
END;
IF NVL (maxSquare.side_amount, 0) < currentSquare.side_amount THEN
maxSquare := currentSquare;
END IF;
currentSquare := NULL;
END IF;
END LOOP;
END LOOP;
DBMS_OUTPUT.put_line (
'side_amount = ' || TO_CHAR (maxSquare.side_amount) || ', i = ' || TO_CHAR (maxSquare.i) || ', j = ' || TO_CHAR (maxSquare.j));
END;
⚡ Итог: выводит координаты i, j и размер стороны найденного квадрата.
👍 Пальцы вверх — продолжаем разбирать задачи методами процедурного языка.
👎 Пальцы вниз — значит, тема надоела.
⚠️ Хотите проверить скрипты, но нет базы под рукой - онлайн-песочница
💎 Поддержка канала⁉️
#️⃣ #sql #Oracle #PLSQL
👍7🤔2👎1
🎵 «Во поле берёза стояла
Во поле кудрявая стояла
Люли-люли, стояла
Люли-люли, стояла» — народная 🌳✨
📌 Разбор задачи: Зеркальное отображение дерева
🧩 Условие:
Дана бинарная береза 🌲.
Преобразуйте бинарное дерево в его зеркальное отображение — то есть поменять местами все левые и правые поддеревья.
⚙️ Алгоритм (кратко):
Рекурсивно обходим дерево.
Для каждой вершины:
🔄 меняем местами левое и правое поддерево.
Возвращаем новую ссылку на корень.
💻 Решение (PL/SQL):
👍 Пальцы вверх — продолжаем разбирать задачи методами процедурного языка.
👎 Пальцы вниз — значит, тема надоела.
⚠️ Хотите проверить скрипты, но нет базы под рукой - онлайн-песочница
💎 Поддержка канала⁉️
Вчера комменты были интереснее поста, надуюсь что "есть еще порох в пороховницах"👇
#️⃣ #SQL #Oracle #PLSQL
Во поле кудрявая стояла
Люли-люли, стояла
Люли-люли, стояла» — народная 🌳✨
📌 Разбор задачи: Зеркальное отображение дерева
🧩 Условие:
Дана бинарная береза 🌲.
Преобразуйте бинарное дерево в его зеркальное отображение — то есть поменять местами все левые и правые поддеревья.
⚙️ Алгоритм (кратко):
Рекурсивно обходим дерево.
Для каждой вершины:
🔄 меняем местами левое и правое поддерево.
Возвращаем новую ссылку на корень.
💻 Решение (PL/SQL):
CREATE OR REPLACE TYPE node IS OBJECT (
value NUMBER,
left REF node,
right REF node
);
CREATE TABLE nodes OF node;
DECLARE
TYPE ref_tab IS TABLE OF REF node INDEX BY PLS_INTEGER;
refs ref_tab := ref_tab();
root REF node;
mirroredTreeRoot 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);
UPDATE nodes n SET n.left = current.left WHERE REF(n) = insert_node.root;
ELSE
insert_node(root => current.right, new_value => new_value);
UPDATE nodes n SET n.right = current.right WHERE REF(n) = insert_node.root;
END IF;
END IF;
END insert_node;
PROCEDURE print_node (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_node(root => current.left); END IF;
IF current.right IS NOT NULL THEN print_node(root => current.right); END IF;
EXCEPTION WHEN skip THEN NULL;
END print_node;
FUNCTION mirror_tree (root REF node) RETURN REF node IS
newNode REF node;
BEGIN
IF root IS NULL THEN RETURN NULL; END IF;
DECLARE
current node;
leftNext REF node;
rightNext REF node;
BEGIN
SELECT DEREF(root) INTO current FROM DUAL;
leftNext := mirror_tree(root => current.right);
rightNext := mirror_tree(root => current.left);
INSERT INTO nodes n
VALUES (node(VALUE => current.VALUE, left => leftNext, right => rightNext))
RETURNING REF(n) INTO newNode;
RETURN newNode;
END;
END mirror_tree;
BEGIN
FOR i IN 1..10 LOOP
DECLARE newValue NUMBER := TRUNC(DBMS_RANDOM.VALUE(1, 100));
BEGIN insert_node(root => root, new_value => newValue); END;
END LOOP;
DBMS_OUTPUT.put_line('root');
print_node(root => root);
mirroredTreeRoot := mirror_tree(root);
DBMS_OUTPUT.put_line('mirroredTreeRoot');
print_node(root => mirroredTreeRoot);
END;
👍 Пальцы вверх — продолжаем разбирать задачи методами процедурного языка.
👎 Пальцы вниз — значит, тема надоела.
⚠️ Хотите проверить скрипты, но нет базы под рукой - онлайн-песочница
💎 Поддержка канала⁉️
Вчера комменты были интереснее поста, надуюсь что "есть еще порох в пороховницах"👇
#️⃣ #SQL #Oracle #PLSQL
👍13👎4
🎵 «Киборг-убийца рвётся наружу,
Он не опасен, он безоружен.
Киборг-убийца на вечеринке,
Любит Анжелу, любит Маринку.
Киборг-убийца где-то внутри —
Может быть, я, может быть, ты…» — Ленинград 🤖🎤
📌 Разбор задачи: Путь робота в сетке
🧩 Условие:
Робот начинает движение в верхнем левом углу сетки m × n.
Он может двигаться только 👉 вправо или 👇 вниз.
Нужно найти количество уникальных путей до нижнего правого угла.
⚙️ Алгоритм (кратко):
1️⃣ Создаём матрицу n × m.
2️⃣ Заполняем первую строку и первый столбец единицами (робот может двигаться только по одной траектории).
3️⃣ Для каждой ячейки:
📐 matrix[i][j] = matrix[i-1][j] + matrix[i][j-1]
(сумма способов попасть сверху и слева).
4️⃣ В правом нижнем углу будет количество всех уникальных путей.
💻 Решение (PL/SQL):
📊 Для сетки 10 × 10 ответ будет: 48620 уникальных путей.
✨ Можно усложнить задачу: сделать матрицу бинарной (1 и 0), и добавить условие, что робот может двигаться только по клеткам со значением 1.
💡 Желающие могут поэкспериментировать и поделиться своими решениями в комментах.
👍 Пальцы вверх — продолжаем разбирать задачи методами процедурного языка.
👎 Пальцы вниз — значит, тема надоела.
⚠️ Хотите проверить скрипты, но нет базы под рукой - онлайн-песочница
💎 Поддержка канала⁉️
💬 Каждый ваш коммент ценен, не сдерживайте себя — здесь цензуры нет 👇
#️⃣ #SQL #Oracle #PLSQL
Он не опасен, он безоружен.
Киборг-убийца на вечеринке,
Любит Анжелу, любит Маринку.
Киборг-убийца где-то внутри —
Может быть, я, может быть, ты…» — Ленинград 🤖🎤
📌 Разбор задачи: Путь робота в сетке
🧩 Условие:
Робот начинает движение в верхнем левом углу сетки m × n.
Он может двигаться только 👉 вправо или 👇 вниз.
Нужно найти количество уникальных путей до нижнего правого угла.
⚙️ Алгоритм (кратко):
1️⃣ Создаём матрицу n × m.
2️⃣ Заполняем первую строку и первый столбец единицами (робот может двигаться только по одной траектории).
3️⃣ Для каждой ячейки:
📐 matrix[i][j] = matrix[i-1][j] + matrix[i][j-1]
(сумма способов попасть сверху и слева).
4️⃣ В правом нижнем углу будет количество всех уникальных путей.
💻 Решение (PL/SQL):
DECLARE
TYPE row_tab IS TABLE OF NUMBER;
TYPE matrix_tab IS TABLE OF row_tab;
matrix matrix_tab := matrix_tab();
uniqueWayCount INTEGER;
PROCEDURE get_unique_way_count (
n IN INTEGER,
m IN INTEGER,
matrix IN OUT NOCOPY matrix_tab,
unique_way_count OUT INTEGER
) IS
PROCEDURE init_matrix (
n IN INTEGER,
m IN INTEGER,
matrix IN OUT NOCOPY matrix_tab
) IS
"row" row_tab := row_tab();
BEGIN
"row".extend(m);
matrix.extend(n);
FOR i IN 1..n LOOP
matrix(i) := "row";
END LOOP;
"row".delete;
END init_matrix;
BEGIN
init_matrix(n => n, m => m, matrix => matrix);
FOR i IN 1..n LOOP
FOR j IN 1..m LOOP
IF i = 1 OR j = 1 THEN
matrix(i)(j) := 1;
ELSE
matrix(i)(j) := matrix(i - 1)(j) + matrix(i)(j - 1);
END IF;
END LOOP;
END LOOP;
unique_way_count := matrix(n)(m);
END get_unique_way_count;
PROCEDURE print_matrix (matrix IN matrix_tab) IS
BEGIN
FOR i IN 1..matrix.COUNT LOOP
DECLARE
str VARCHAR2(200);
BEGIN
FOR j IN 1..matrix(i).COUNT LOOP
str := str || ' ' || TO_CHAR(matrix(i)(j));
END LOOP;
DBMS_OUTPUT.put_line(str);
END;
END LOOP;
END print_matrix;
BEGIN
get_unique_way_count(n => 10, m => 10, matrix => matrix, unique_way_count => uniqueWayCount);
print_matrix(matrix => matrix);
DBMS_OUTPUT.put_line('uniqueWayCount = ' || TO_CHAR(uniqueWayCount));
END;
📊 Для сетки 10 × 10 ответ будет: 48620 уникальных путей.
✨ Можно усложнить задачу: сделать матрицу бинарной (1 и 0), и добавить условие, что робот может двигаться только по клеткам со значением 1.
💡 Желающие могут поэкспериментировать и поделиться своими решениями в комментах.
👍 Пальцы вверх — продолжаем разбирать задачи методами процедурного языка.
👎 Пальцы вниз — значит, тема надоела.
⚠️ Хотите проверить скрипты, но нет базы под рукой - онлайн-песочница
💎 Поддержка канала⁉️
💬 Каждый ваш коммент ценен, не сдерживайте себя — здесь цензуры нет 👇
#️⃣ #SQL #Oracle #PLSQL
👍6👎5
🚀 Хочется прокачать SQL, но под рукой нет базы данных?
Рекомендую дружественный ресурс от моего коллеги Славы Рожнева - автора курса SQL от Яндекс практикума.
У Славы Рожнева — есть два удобных инструмента:
🔹 sqltest.online — тренажёр с задачами и тестами для практики.
📢 Канал: t.me/sqltestonline
🔹 sqlize.online — онлайн-песочница для SQL-запросов прямо в браузере.
📢 Канал: t.me/sqlize
✨ Отличный способ учиться и поддерживать навыки в любой момент и в любом месте.
Рекомендую дружественный ресурс от моего коллеги Славы Рожнева - автора курса SQL от Яндекс практикума.
У Славы Рожнева — есть два удобных инструмента:
🔹 sqltest.online — тренажёр с задачами и тестами для практики.
📢 Канал: t.me/sqltestonline
🔹 sqlize.online — онлайн-песочница для SQL-запросов прямо в браузере.
📢 Канал: t.me/sqlize
✨ Отличный способ учиться и поддерживать навыки в любой момент и в любом месте.
Telegram
SQLTest.online
Новости проекта SQLTest.online
👍11🤡3👎1🔥1
🎵 «Для меня деньги — бумага
Для тебя — свобода
На американскую мечту сегодня мода
К этой мечте стремишься ты
Работать роботом ради бумажной мечты» — Ленинград 🎸
📌 Задача из собеса в ЦБ (2020 год).
В самом первом посту канала (в прикреплённом файлике) — 3 задачи.
🔹 Первые две уже разобраны.
🔹 Вот третья:
🧩 Условие задачи:
Запрос формирует список действующих на sysdate ОКВЭД для всех организаций.
❗ При выполнении возникает ошибка — нехватка табличного пространства TEMP.
Нужно оптимизировать запрос, чтобы он успешно выполнился.
💡 Примечание:
Структуру таблиц T1, T2, T_okved приводить не нужно — она условная, нужна только для понимания сути.
⚠️ Хотите проверить скрипты, но нет базы под рукой - онлайн-песочница
💎 Поддержка канала⁉️
📝 В комментариях пишите свои мысли и варианты оптимизации ⚡
👇👇
#RealInterviewTasks #SQL #Oracle #PLSQL
Для тебя — свобода
На американскую мечту сегодня мода
К этой мечте стремишься ты
Работать роботом ради бумажной мечты» — Ленинград 🎸
📌 Задача из собеса в ЦБ (2020 год).
В самом первом посту канала (в прикреплённом файлике) — 3 задачи.
🔹 Первые две уже разобраны.
🔹 Вот третья:
🧩 Условие задачи:
Запрос формирует список действующих на sysdate ОКВЭД для всех организаций.
❗ При выполнении возникает ошибка — нехватка табличного пространства TEMP.
Нужно оптимизировать запрос, чтобы он успешно выполнился.
SQL
select
t1.ogrn,
t2.ds,
t2.de,
o.kod,
o.name,
o.ver
from T2
join T1 on t1.id = t2.id
left join T_okved o on o.id = t2.okved_id
where sysdate between t1.ds and t1.de
and sysdate between t2.ds and t2.de;
💡 Примечание:
Структуру таблиц T1, T2, T_okved приводить не нужно — она условная, нужна только для понимания сути.
⚠️ Хотите проверить скрипты, но нет базы под рукой - онлайн-песочница
💎 Поддержка канала⁉️
📝 В комментариях пишите свои мысли и варианты оптимизации ⚡
👇👇
#RealInterviewTasks #SQL #Oracle #PLSQL
👍5💩5❤2👎1
Продолжим или закончим 3 часть "Мерлезонского балета" - решение задач методами процедурного языка. Я выбрал очередные 5 задач из 5 тем: работа с массивами, работа со строками, работа с матрицами, структуры данных, динамическое программирование.
Anonymous Poll
9%
Перемещение нулей: все нули в конец массива, порядок ненулевых элементов сохраняется.
3%
Самая длинная подстрока: Найдите длину самой длинной подстроки без повторяющихся символов.
9%
Транспонирование: Транспонируйте заданную матрицу.
9%
Цикл в списке: Определите, содержит ли связный список цикл.
3%
Вычислите мин. кол-во операций (вставка, удаление, замена) нужных для преоб-ия одной строки в другую
26%
Я разработчик DB. Эти трюки для прикладников.
43%
Интересны все.
🤡6❤1👎1
DB developers channel
🎵 «Для меня деньги — бумага Для тебя — свобода На американскую мечту сегодня мода К этой мечте стремишься ты Работать роботом ради бумажной мечты» — Ленинград 🎸 📌 Задача из собеса в ЦБ (2020 год). В самом первом посту канала (в прикреплённом файлике) — 3…
📌 Разбор задачи из ЦБ (2020 год)
❗ Проблема: при выполнении возникает ошибка — нехватка табличного пространства TEMP.
Нужно оптимизировать запрос, чтобы он успешно выполнился.
💡 Решение
Основная причина переполнения TEMP — использование hash join, который строит большие промежуточные таблицы.
Чтобы этого избежать, можно подсказать оптимизатору использовать nested loop.
🔹 Оптимизированный запрос:
⚡ Идея решения:
USE_NL → переключаем соединение на nested loop, чтобы уменьшить нагрузку на TEMP.
Таким образом, запрос выполнится без переполнения TEMP.
UPDATES: под справедливой критикой коллег, запрос и пост изменил
⚠️ Хотите проверить скрипты, но нет базы под рукой - онлайн-песочница
💎 Поддержка канала⁉️
📝 Как Вы бы решили?👇
#️⃣ #RealInterviewTasks #SQL #Oracle #PLSQL
select
t1.ogrn,
t2.ds,
t2.de,
o.kod,
o.name,
o.ver
from T2
join T1 on t1.id = t2.id
left join T_okved o on o.id = t2.okved_id
where sysdate between t1.ds and t1.de
and sysdate between t2.ds and t2.de;
❗ Проблема: при выполнении возникает ошибка — нехватка табличного пространства TEMP.
Нужно оптимизировать запрос, чтобы он успешно выполнился.
💡 Решение
Основная причина переполнения TEMP — использование hash join, который строит большие промежуточные таблицы.
Чтобы этого избежать, можно подсказать оптимизатору использовать nested loop.
🔹 Оптимизированный запрос:
SELECT --+ LEADING(T1 T2 o) USE_NL(T2 o)
t1.OGRN,
t2.DS,
t2.DE,
o.KOD,
o.NAME,
o.VER
FROM T1
JOIN T2 on (t1.id = t2.id)
left join T_okved o on o.id = t2.okved_id
WHERE sysdate between t1.ds and t1.de
and sysdate between t2.ds and t2.de;
⚡ Идея решения:
USE_NL → переключаем соединение на nested loop, чтобы уменьшить нагрузку на TEMP.
Таким образом, запрос выполнится без переполнения TEMP.
UPDATES: под справедливой критикой коллег, запрос и пост изменил
⚠️ Хотите проверить скрипты, но нет базы под рукой - онлайн-песочница
💎 Поддержка канала⁉️
📝 Как Вы бы решили?👇
#️⃣ #RealInterviewTasks #SQL #Oracle #PLSQL
🤡5👍3👎1
✨ «Мы почитаем всех нулями,
А единицами — себя» - А.С. Пушкин
📌 Разбор задачи: Перемещение нулей
🧩 Условие:
Дан массив чисел. Нужно переместить все нули в его конец, сохраняя относительный порядок ненулевых элементов.
⚙️ Алгоритм (кратко):
1️⃣ Создаём новый массив той же длины.
2️⃣ Ведём два указателя:
🔹 firstNotNullIndex — куда класть ненулевые элементы.
🔹 lastNullIndex — куда класть нули с конца.
3️⃣ Проходим по массиву:
👉 если элемент ненулевой — кладём его в начало.
👉 если элемент равен нулю — отправляем его в конец.
💻 Решение (PL/SQL):
📊 Для массива:
👉 результат будет:
👍 Пальцы вверх — продолжаем разбирать алгоритмы на PL/SQL.
👎 Пальцы вниз — значит, тема надоела.
⚠️ Хотите проверить скрипты, но нет базы под рукой - онлайн-песочница
💎 Поддержка канала⁉️
💬 Есть что сказать!? Не сдерживаете себя 👇
#️⃣ #SQL #Oracle #PLSQL
А единицами — себя» - А.С. Пушкин
📌 Разбор задачи: Перемещение нулей
🧩 Условие:
Дан массив чисел. Нужно переместить все нули в его конец, сохраняя относительный порядок ненулевых элементов.
⚙️ Алгоритм (кратко):
1️⃣ Создаём новый массив той же длины.
2️⃣ Ведём два указателя:
🔹 firstNotNullIndex — куда класть ненулевые элементы.
🔹 lastNullIndex — куда класть нули с конца.
3️⃣ Проходим по массиву:
👉 если элемент ненулевой — кладём его в начало.
👉 если элемент равен нулю — отправляем его в конец.
💻 Решение (PL/SQL):
DECLARE
TYPE set_tab IS TABLE OF NUMBER;
"set" set_tab := set_tab(0,1,0,0,2,3,4,0,0,5,6,7,8,0,9,0);
newSet set_tab := set_tab ();
firstNotNullIndex INTEGER := 1;
lastNullIndex INTEGER := "set".COUNT;
BEGIN
newSet.extend("set".COUNT);
FOR i IN 1.."set".COUNT LOOP
IF "set"(i) = 0 THEN
newSet(lastNullIndex) := 0;
lastNullIndex := lastNullIndex - 1;
ELSE
newSet(firstNotNullIndex) := "set"(i);
firstNotNullIndex := firstNotNullIndex + 1;
END IF;
END LOOP;
<<print_set>>
DECLARE
str VARCHAR2(100);
BEGIN
FOR i IN 1..newSet.COUNT LOOP
str := str || TO_CHAR(newSet(i));
END LOOP;
DBMS_OUTPUT.put_line(str);
END;
END;
📊 Для массива:
0,1,0,0,2,3,4,0,0,5,6,7,8,0,9,0
👉 результат будет:
1,2,3,4,5,6,7,8,9,0,0,0,0,0,0,0
👍 Пальцы вверх — продолжаем разбирать алгоритмы на PL/SQL.
👎 Пальцы вниз — значит, тема надоела.
⚠️ Хотите проверить скрипты, но нет базы под рукой - онлайн-песочница
💎 Поддержка канала⁉️
💬 Есть что сказать!? Не сдерживаете себя 👇
#️⃣ #SQL #Oracle #PLSQL
👍13🤡6👎1
✨ «Сидит Кай, раскладывает льдинки.
Изо всех комбинаций вместо „Вечность“ снова выходит „ЖОПА“.
Герда смотрит и говорит:
— Кай, да у тебя просто талант программиста!» – анекдот 😅
🏛 Продолжаем тему: Архитектура кода
Наконец, я собрался с силами и написал несколько букв «правильного» кода, демонстрирующего подход к архитектуре 🚀
📌 Сразу оговорюсь: код упрощён и создан для демонстрации.
Многие вещи в реальности делаются сложнее и эффективнее, но нельзя объять необъятное в одном посте.
Тут важна не конкретика, как именно манипулировать данными пользователей (сам код для этого не годится), а как универсальный архитектурный принцип 🧩
Я специально оставил несколько «жуков» 🐞 — внимательный глаз их заметит 👀
Для опытного разработчика хватит пары дней на разбор.
Новичку, думаю, и месяца может быть мало ⏳
Это Вам не курсы проходить и книжки читать!!!
Это результат коллективного труда, моя доля в нём не велика,
но я считаю, что такая архитектура оптимальна ⚡
🔹 Краткое описание:
1️⃣ Таблицы:
users — основные поля пользователей
users_live — расчётные поля
2️⃣ Пакеты для хранения констант:
GLOBAL_CONSTANTS — глобальные константы
USERS_CONSTANTS — константы для работы с пользователями
3️⃣ Пакеты для работы с одной строкой:
USERS_LIB — методы уровня таблицы users
USERS_LIVE_LIB — методы уровня таблицы users_live
4️⃣ Пакеты бизнес-уровня:
AUTH_LVL1_PROC — установка контекста
USERS_LVL1_PROC — операции над пользователями
USERS_LVL2_PROC — парсинг входящих данных (XML/JSON)
5️⃣ API-уровень:
APPLICATION_API — методы для вызова пользователем
APPLICATION_SRV — методы для джобов/сервисов без контекста
⚠️ Обратите внимание:
1.В коде нет операторов управления транзакциями. Он пассивен.
COMMIT или ROLLBACK выполняет вызывающая сторона 🔄
2. Такая архитектура может быть выполнена и на PostgreSQL.
Но в пакетном виде ORACLE, она выглядит намного симпатичнее.
✅ Всё! Гештальт закрыт. Теперь можно и донаты «клянчить» без стыда 💸
👍 — если зашло
👎 — если нет
⚠️ Хотите проверить скрипты, но нет базы под рукой - онлайн-песочница
💎 Поддержка канала⁉️
А также пишите в комменты вопросы, радость, гнев и прочие чувства 🙌
#CodeArchitecture
Изо всех комбинаций вместо „Вечность“ снова выходит „ЖОПА“.
Герда смотрит и говорит:
— Кай, да у тебя просто талант программиста!» – анекдот 😅
🏛 Продолжаем тему: Архитектура кода
Наконец, я собрался с силами и написал несколько букв «правильного» кода, демонстрирующего подход к архитектуре 🚀
📌 Сразу оговорюсь: код упрощён и создан для демонстрации.
Многие вещи в реальности делаются сложнее и эффективнее, но нельзя объять необъятное в одном посте.
Тут важна не конкретика, как именно манипулировать данными пользователей (сам код для этого не годится), а как универсальный архитектурный принцип 🧩
Я специально оставил несколько «жуков» 🐞 — внимательный глаз их заметит 👀
Для опытного разработчика хватит пары дней на разбор.
Новичку, думаю, и месяца может быть мало ⏳
Это Вам не курсы проходить и книжки читать!!!
Это результат коллективного труда, моя доля в нём не велика,
но я считаю, что такая архитектура оптимальна ⚡
🔹 Краткое описание:
1️⃣ Таблицы:
users — основные поля пользователей
users_live — расчётные поля
2️⃣ Пакеты для хранения констант:
GLOBAL_CONSTANTS — глобальные константы
USERS_CONSTANTS — константы для работы с пользователями
3️⃣ Пакеты для работы с одной строкой:
USERS_LIB — методы уровня таблицы users
USERS_LIVE_LIB — методы уровня таблицы users_live
4️⃣ Пакеты бизнес-уровня:
AUTH_LVL1_PROC — установка контекста
USERS_LVL1_PROC — операции над пользователями
USERS_LVL2_PROC — парсинг входящих данных (XML/JSON)
5️⃣ API-уровень:
APPLICATION_API — методы для вызова пользователем
APPLICATION_SRV — методы для джобов/сервисов без контекста
⚠️ Обратите внимание:
1.В коде нет операторов управления транзакциями. Он пассивен.
COMMIT или ROLLBACK выполняет вызывающая сторона 🔄
2. Такая архитектура может быть выполнена и на PostgreSQL.
Но в пакетном виде ORACLE, она выглядит намного симпатичнее.
✅ Всё! Гештальт закрыт. Теперь можно и донаты «клянчить» без стыда 💸
👍 — если зашло
👎 — если нет
⚠️ Хотите проверить скрипты, но нет базы под рукой - онлайн-песочница
💎 Поддержка канала⁉️
А также пишите в комменты вопросы, радость, гнев и прочие чувства 🙌
#CodeArchitecture
👍6🤡6👎3🖕1
🤡6👍1👎1