- •Введение.
- •Соединение с бд 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.
- •Задача. Взятие последней записи о клиенте.
- •Задача. Отчет об изменениях зарплаты.
- •Задача. Пакет функций о вкладах.
- •Задача. Группировка лога выполнения процессов.
- •Задача. Вьюшка с аналитическими функциями по вкладам.
- •Задача. Календарь с аналитикой.
- •Задача. Поиск баланса счета на заданную дату.
- •Задача. Удаление исторических данных о рейтинге.
- •Функции, выдающие более одного значения.
- •Задача. Вызов многозначной функции.
- •"Расклейка" и "склейка" строк.
- •“Расклейка” одной строки.
- •“Расклейка” нескольких строк с группировкой.
- •“Склейка” в одну строку.
- •“Склейка” нескольких строк с группировкой.
- •Задача. Простая расклейка-склейка.
- •Задача. Скрипт создания индексов.
- •Задача. Скрипт создания таблиц.
- •Задача. Отчет о созданных объектах.
- •Задача. Отчет о числе строк в таблицах.
- •Задача. Расклейка списка хобби.
- •Задача. Склейка запроса о максимумах числовых полей.
- •Оптимизация запросов.
Оператор merge.
Оператор MERGE работает так: есть порция вливаемых данных (SRC) и таблица-приемник, в которую мы их вливаем (DEST).
Если ключ в таблице-приемнике найден, то update-им другие поля в таблице-приемнике указанным образом.
Если же ключ в таблице-приемнике не найден, то insert-им в таблицу-приемник указанным образом.
MERGE еще иногда называют “update else insert” или “upsert”.
Подробнее мы разберем его в задаче ниже.
Задача. Merge данных о студентах.
Создать пустую таблицу KK_STUDENTS_ALL_YEARS. С помощью оператора MERGE внести в нее сначала данные из таблицы KK_STUDENTS_2010, а потом из таблицы KK_STUDENTS_2012 (см. задачу “Сравнение множеств”).
Создадим пустую таблицу KK_STUDENTS_ALL_YEARS:
CREATE TABLE KK_STUDENTS_ALL_YEARS AS SELECT * FROM KK_STUD_2010 WHERE 0=1;
"Вмёржим" в KK_STUDENTS_ALL_YEARS данные за 2010 год. Будут только insert-ы:
MERGE INTO KK_STUDENTS_ALL_YEARS DEST
USING (SELECT ID, NAME FROM KK_STUD_2010) SRC
ON (DEST.ID = SRC.ID)
WHEN MATCHED THEN
UPDATE SET DEST.NAME = SRC.NAME
WHEN NOT MATCHED THEN
INSERT (DEST.ID, DEST.NAME) VALUES (SRC.ID, SRC.NAME);
Проверим результат:
SELECT * FROM KK_STUDENTS_ALL_YEARS;
Сменим фамилию одному из студентов (в 2012 году сменил фамилию), сохранив первичный ключ ID:
UPDATE KK_STUD_2012 SET NAME = 'ТРУНОВА' WHERE ID = 2;
"Вмёржим" в KK_STUDENTS_ALL_YEARS данные за 2012 год. Будут insert-ы и update-ы:
MERGE INTO KK_STUDENTS_ALL_YEARS DEST
USING (SELECT ID, NAME FROM KK_STUD_2012) SRC
ON (DEST.ID = SRC.ID)
WHEN MATCHED THEN
UPDATE SET DEST.NAME = SRC.NAME
WHEN NOT MATCHED THEN
INSERT (DEST.ID, DEST.NAME) VALUES (SRC.ID, SRC.NAME);
Проверим результат:
SELECT * FROM KK_STUDENTS_ALL_YEARS;
MERGE является одним из эффективных способов вливания дельты (порции изменившихся данных) в таблицу-приемник.
Задача. Merge данных о клиентах.
Дана таблица kk_clients со списком клиентов:
create table kk_clients (id integer, name varchar2(60), passport char(11));
Дана таблица kk_clients_delta, в которой собрана порция изменившихся за сутки данных о клиентах - новых и старых, причем имя и фамилия поступают в отдельных полях.
create table kk_clients_delta (id integer, firstname varchar2(30), lastname varchar2(30), passport char(11));
Поле id – первичный ключ в обеих таблицах.
Написать оператор merge, который вливает данные из kk_clients_delta в kk_clients.
Заполним таблицы данными:
insert into kk_clients values (1,'Козлов Сергей','6605 700822');
insert into kk_clients values (2,'Стервятников Евгений','1390 193734');
insert into kk_clients values (3,'Баранов Илья','8808 848908');
insert into kk_clients values (4,'Шакалов Григорий','7209 888614');
insert into kk_clients values (5,'Крысин Роман','8976 616964');
insert into kk_clients values (6,'Змеев Игорь','5332 659236');
insert into kk_clients values (7,'Свиньин Абрам','1015 305818');
insert into kk_clients values (8,'Пиявкин Ираклий','7015 389388');
insert into kk_clients values (9,'Червяков Иосиф','3249 300256');
insert into kk_clients values (10,'Трутнев Абдулла','6950 327070');
insert into kk_clients_delta values (7,'Свиньин','Абрам','5587 324786');
insert into kk_clients_delta values (10,'Трутнев','Владимир','6950 327070');
insert into kk_clients_delta values (11,'Рыропротьев','Станислав','2901 849017');
merge into kk_clients dest
using (select * from kk_clients_delta) src
on (dest.id = src.id)
when matched then
update
set dest.name = src.firstname || ' ' || src.lastname,
dest.passport = src.passport
when not matched then
insert
values
(src.id, src.firstname || ' ' || src.lastname, src.passport);
Посмотрим результат:
select * from kk_clients;
