- •Введение.
- •Соединение с бд Oracle.
- •Типы данных Oracle, создание и модификация таблиц и вьюшек.
- •Задача. Удаление дубликатов.
- •Задача. Удаление по условию not in.
- •Функции по работе со строками.
- •Функции по работе с числами.
- •Троичная логика, конструкция with, функции nvl, coalesce, case, decode.
- •Основы pl/sql.
- •Задача. Факториал.
- •Задача. Подсчет числа вхождений символа в строку.
- •Задача. Подсчет числа вхождений подстроки в строку.
- •Задача. Копирование таблицы фиксированной структуры.
- •Задача. Простановка count в цикле.
- •Задача. Распределение данных по условию.
- •Задача. Использование сиквенсов и dbms_random.
- •Задача. Процедура с out параметрами. Нотации.
- •Задача. Простой пакет.
- •Задача. Разные виды Count.
- •Задача. Получение скрипта заполнения таблицы имеющимися данными.
- •Раздача прав (grants).
- •Операции над множествами, joins.
- •Задача. Сравнение множеств.
- •Задача. Загрузка данных с помощью full join.
- •Задача. Проставление роста животных.
- •Оператор merge.
- •Задача. Merge данных о студентах.
- •Задача. Merge данных о клиентах.
- •Функции по работе с датами.
- •Словарь данных.
- •Задача. Last_ddl_time.
- •Задача. Отчет об объектах текущей схемы.
- •Задача. Dbms_output из явного курсора по словарю данных.
- •Задача. Компиляция схемы.
- •Задача. Поиск текста во вьюшках.
- •Динамический sql.
- •Задача. Удаление конкретной таблицы, если она существует.
- •Задача. Удаление любой таблицы с проверкой на существование.
- •Задача. Конструкция '%rowcount'.
- •1) С помощью динамического вызова команды truncate очистить таблицу kk_objects_list от данных.
- •3) Вставить в таблицу kk_objects_list перечень имен всех объектов текущей схемы. С помощью конструкции sql%rowcount выдать в dbms_output количество вставившихся строк.
- •Задача. Удаление всех таблиц и вьюшек.
- •Часть 1. Написать pl/sql блок, который дропает все таблицы текущей схемы, начинающиеся на 'kk_'.
- •Часть 2. Написать pl/sql блок, который выдает в dbms_output скрипт удаления всех вьюшек текущей схемы, начинающихся с 'vw_kk%'.
- •Задача. Отчет о максимальных id.
- •Задача. Переименование столбцов.
- •Задача. Создание вьюшек.
- •Триггеры.
- •Задача. Автоинкрементное поле.
- •Задача. Триггер конвертации сумм в валюте.
- •Задача. Триггер логирования dml-операций.
- •Задача. Триггер зеркалирования.
- •Задача. Триггер по поиску в справочнике.
- •Задача. Триггер контроля.
- •Global temporary tables и переменные в заголовке пакета.
- •Переменные в заголовке пакета.
- •Регулярные выражения.
- •Задача. Правка некачественных данных регулярными выражениями.
- •Задача. Парсинг строк с помощью регулярных выражений.
- •Автономные транзакции.
- •Задача. Автономное логирование этапов загрузки.
- •Иерархические запросы.
- •Задача. Вывод иерархии с отступами.
- •Задача. Соединение иерархической таблицы с обычной.
- •Задача. Сумма зарплат подчиненных.
- •Задача. Простой календарь.
- •Задача. Детальный календарь.
- •Задача. Календарь с индикаторами выходных дней.
- •Аналитические функции.
- •Отступление о Rownum.
- •Негрупповые аналитические функции.
- •Групповая функция keep dense_rank.
- •Задача. Взятие последней записи о клиенте.
- •Задача. Отчет об изменениях зарплаты.
- •Задача. Пакет функций о вкладах.
- •Задача. Группировка лога выполнения процессов.
- •Задача. Вьюшка с аналитическими функциями по вкладам.
- •Задача. Календарь с аналитикой.
- •Задача. Поиск баланса счета на заданную дату.
- •Задача. Удаление исторических данных о рейтинге.
- •Функции, выдающие более одного значения.
- •Задача. Вызов многозначной функции.
- •"Расклейка" и "склейка" строк.
- •“Расклейка” одной строки.
- •“Расклейка” нескольких строк с группировкой.
- •“Склейка” в одну строку.
- •“Склейка” нескольких строк с группировкой.
- •Задача. Простая расклейка-склейка.
- •Задача. Скрипт создания индексов.
- •Задача. Скрипт создания таблиц.
- •Задача. Отчет о созданных объектах.
- •Задача. Отчет о числе строк в таблицах.
- •Задача. Расклейка списка хобби.
- •Задача. Склейка запроса о максимумах числовых полей.
- •Оптимизация запросов.
"Расклейка" и "склейка" строк.
В этом разделе рассмотрим часто возникающие задачи по склейке и расклейке строк. Здесь применяются регулярные выражения и иерархические запросы. Не обязательно глубоко вникать в эти примеры, главное научиться писать такие же запросы на других структурах данных.
“Расклейка” одной строки.
Часто возникают задачи, когда в запросе из строки вида 'A2,8F8,J5,I77' необходимо сделать 4 строки:
A2
8F8
J5
I77
Применяя иерархический запрос и регулярные выражения, напишем запрос, который "расклеивает" строку, делая из нее несколько строк:
select regexp_substr(s, '[^,]+', 1, level) piece
from (select 'A2,8F8,J5,I77' s from dual)
connect by regexp_substr(s, '[^,]+', 1, level) is not null;
“Расклейка” нескольких строк с группировкой.
Теперь приведу волшебный запрос, который делает “расклейку” не по одной строке, а по всей таблице с группировкой:
with sample_table as
(select 'id1' col1, 'aaa,bb,cccc' col2
from dual
union all
select 'id2', 'ddd'
from dual
union all
select 'id3', 'fff,ggg' from dual)
select col1, regexp_substr(col2, '[^,]+', 1, column_value) col2
from sample_table,
table(cast(multiset
(select level
from dual
connect by regexp_instr(col2, '[^,]+', 1, level) > 0) as
sys.odcinumberlist))
order by col1, column_value;
“Склейка” в одну строку.
Также часто возникают задачи когда, наоборот, в запросе из 4 различных строк вида
A2
8F8
J5
I77
необходимо сделать склеенную строку ' 8F8,A2,I77,J5' (упорядочив по значениям, за это отвечает “over(order by id)”):
Применяя функцию sys_connect_by_path, пошагово склеиваем строку:
select ids
from (select ltrim(sys_connect_by_path(id, ','), ',') as ids, level
from (select id, lag(id) over(order by id) as prev_id
from (select 'A2' id
from dual
union all
select '8F8' id
from dual
union all
select 'J5' id
from dual
union all
select 'I77' id from dual))
start with prev_id is null
connect by prev_id = prior id
order by level desc)
where rownum = 1;
“Склейка” нескольких строк с группировкой.
Еще одним способом склеить строку является использование агрегирующей функции WM_CONCAT (она склеивает только через запятую):
select pk, wm_concat(id)
from (select 1 pk, 'A2' id
from dual
union all
select 1 pk, '8F8' id
from dual
union all
select 1 pk, 'J5' id
from dual
union all
select 1 pk, 'I77' id
from dual
union all
select 2 pk, 'GGG' id
from dual
union all
select 2 pk, 'HH69' id from dual)
group by pk;
Далее приведу запрос, который склеивает данные с группировкой и сортировкой склеиваемых данных в указанном порядке. Рассмотрим таблицу людей и их хобби с датой начала увлечения. Склеим набор хобби каждого человека в порядке начала увлечения:
with a as
(select /*+ materialize*/
'Прохоров' name,
'играть в политику' hobby,
to_date('20.05.2011', 'dd.mm.yyyy') hobby_start_date
from dual
union all
select 'Абрамович' name,
'кататься на яхте' hobby,
to_date('17.11.2005', 'dd.mm.yyyy') hobby_start_date
from dual
union all
select 'Прохоров' name,
'отдыхать в Куршавеле' hobby,
to_date('31.01.2007', 'dd.mm.yyyy') hobby_start_date
from dual
union all
select 'Вексельберг' name,
'покупать яйца Фаберже' hobby,
to_date('20.02.2004', 'dd.mm.yyyy') hobby_start_date
from dual
union all
select 'Абрамович' name,
'покупать футболистов' hobby,
to_date('11.06.2003', 'dd.mm.yyyy') hobby_start_date
from dual
union all
select 'Прохоров' name,
'изобретать Ё-мобили' hobby,
to_date('29.09.2009', 'dd.mm.yyyy') hobby_start_date
from dual)
select name, max(hobby_list) keep(dense_rank last order by lvl)
from (select name,
ltrim(sys_connect_by_path(hobby, ','), ',') as hobby_list,
level lvl
from (select name,
hobby,
lag(hobby) over(partition by name order by hobby_start_date) as prev_hobby
from a)
start with prev_hobby is null
connect by name = prior name
and prev_hobby = prior hobby)
group by name
order by name;
