- •Введение.
- •Соединение с бд 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.
- •Задача. Взятие последней записи о клиенте.
- •Задача. Отчет об изменениях зарплаты.
- •Задача. Пакет функций о вкладах.
- •Задача. Группировка лога выполнения процессов.
- •Задача. Вьюшка с аналитическими функциями по вкладам.
- •Задача. Календарь с аналитикой.
- •Задача. Поиск баланса счета на заданную дату.
- •Задача. Удаление исторических данных о рейтинге.
- •Функции, выдающие более одного значения.
- •Задача. Вызов многозначной функции.
- •"Расклейка" и "склейка" строк.
- •“Расклейка” одной строки.
- •“Расклейка” нескольких строк с группировкой.
- •“Склейка” в одну строку.
- •“Склейка” нескольких строк с группировкой.
- •Задача. Простая расклейка-склейка.
- •Задача. Скрипт создания индексов.
- •Задача. Скрипт создания таблиц.
- •Задача. Отчет о созданных объектах.
- •Задача. Отчет о числе строк в таблицах.
- •Задача. Расклейка списка хобби.
- •Задача. Склейка запроса о максимумах числовых полей.
- •Оптимизация запросов.
Задача. Загрузка данных с помощью full join.
Создать таблицу вкладчиков KK_DEPOSIT(DEPOSIT_ID INTEGER, CLIENT_NAME VARCHAR2(40), DT DATE, AMOUNT NUMBER).
Создать таблицу KK_ST_DEPOSIT, по структуре как KK_DEPOSIT, но с дополнительным полем ACTIVE, принимающим значения 'Y' или 'N'.
Первичным ключом в KK_DEPOSIT и KK_ST_DEPOSIT является поле DEPOSIT_ID.
Сделать индексы на поле DEPOSIT_ID в таблицах KK_DEPOSIT и KK_ST_DEPOSIT.
Написать процедуру по загрузке данных из KK_DEPOSIT в KK_ST_DEPOSIT по следующим правилам:
- Если запись есть в KK_DEPOSIT, но нет в KK_ST_DEPOSIT, то вставить ее в KK_ST_DEPOSIT с признаком ACTIVE = 'Y'
- Если запись отсутствует в KK_DEPOSIT, но есть в KK_ST_DEPOSIT, то проставить для нее в KK_ST_DEPOSIT признак ACTIVE = 'N'
- Если запись есть в KK_DEPOSIT и есть в KK_ST_DEPOSIT, то проапдейтить все поля в KK_ST_DEPOSIT значениями из KK_DEPOSIT.
У процедуры должно быть три OUT параметра - число совершенных inserts, deletes(disactivates), updates.
Создадим таблицы и заполним их данными:
CREATE TABLE KK_DEPOSIT(DEPOSIT_ID INTEGER, CLIENT_NAME VARCHAR2(40), DT DATE, AMOUNT NUMBER);
insert into kk_deposit(deposit_id,client_name,dt,amount) values(1,'Карапетян',to_date('30.01.2011','dd.mm.yyyy'),123.89);
insert into kk_deposit(deposit_id,client_name,dt,amount) values(2,'Карапетян',to_date('31.01.2011','dd.mm.yyyy'),129.8);
insert into kk_deposit(deposit_id,client_name,dt,amount) values(3,'Саахов',to_date('24.09.2011','dd.mm.yyyy'),123123.91);
insert into kk_deposit(deposit_id,client_name,dt,amount) values(5,'Саахов',to_date('13.05.2010','dd.mm.yyyy'),8000000);
insert into kk_deposit(deposit_id,client_name,dt,amount) values(6,'Растрелли',to_date('10.01.2012','dd.mm.yyyy'),1100000);
CREATE TABLE KK_ST_DEPOSIT(DEPOSIT_ID INTEGER, CLIENT_NAME VARCHAR2(40), DT DATE, AMOUNT NUMBER, ACTIVE CHAR(1));
insert into kk_st_deposit(deposit_id,client_name,dt,amount,active) values(1,'Карапетян',to_date('30.01.2011','dd.mm.yyyy'),123.89,'Y');
insert into kk_st_deposit(deposit_id,client_name,dt,amount,active) values(2,'Карапетян',to_date('12.06.2012','dd.mm.yyyy'),700000,'N');
insert into kk_st_deposit(deposit_id,client_name,dt,amount,active) values(3,'Саахов',to_date('24.09.2011','dd.mm.yyyy'),123123.91,'Y');
insert into kk_st_deposit(deposit_id,client_name,dt,amount,active) values(4,'Саахов',to_date('27.11.2011','dd.mm.yyyy'),90.98,'Y');
insert into kk_st_deposit(deposit_id,client_name,dt,amount,active) values(5,'Саахов',to_date('13.05.2010','dd.mm.yyyy'),100,'Y');
Расскажем немного об индексах.
Индексы служат для быстрого поиска в таблице по условию. Например, если требуется быстрый поиск в таблице по полям – серии и номеру паспорта, то имеет смысл создать составной индекс на эти два поля.
Индексы бывают неуникальными и уникальными. Уникальные индексы запрещают вставлять в проиндексированные наборы поле дублирующиеся значения (кроме NULL).
Кроме того индексы бывают различных типов (по организации) NORMAL, BITMAP, FUNCTION-BASED и т.п. Но в нашей задаче мы не будем детально расписывать эти опции в получаемом скрипте создания индексов.
Создадим требуемые индексы на наши таблицы, призванные облегчить поиск и update информации по ключу deposit_id:
create unique index ix_kk_deposit on kk_deposit (deposit_id);
create unique index ix_kk_st_deposit on kk_st_deposit (deposit_id);
Напишем требуемую процедуру:
create or replace procedure load_kk_st_deposit(inserts_count out integer,
deletes_count out integer,
updates_count out integer) is
begin
inserts_count := 0;
deletes_count := 0;
updates_count := 0;
for z in (select n.deposit_id new_deposit_id,
n.client_name new_client_name,
n.dt new_dt,
n.amount new_amount,
o.deposit_id old_deposit_id
from kk_deposit n
full outer join kk_st_deposit o
on n.deposit_id = o.deposit_id) loop
if z.old_deposit_id is null then
-- Если запись есть в KK_DEPOSIT, но нет в KK_ST_DEPOSIT, то вставить ее в KK_ST_DEPOSIT с признаком ACTIVE = 'Y'
insert into kk_st_deposit
(deposit_id, client_name, dt, amount, active)
values
(z.new_deposit_id, z.new_client_name, z.new_dt, z.new_amount, 'Y');
inserts_count := inserts_count + 1;
elsif z.new_deposit_id is null then
-- Если запись отсутствует в KK_DEPOSIT, но есть в KK_ST_DEPOSIT, то проставить для нее в KK_ST_DEPOSIT признак ACTIVE = 'N'
update kk_st_deposit
set active = 'N'
where deposit_id = z.old_deposit_id;
deletes_count := deletes_count + 1;
elsif z.new_deposit_id = z.old_deposit_id then
-- Если запись есть в KK_DEPOSIT и есть в KK_ST_DEPOSIT, то проапдейтить все поля в KK_ST_DEPOSIT значениями из KK_DEPOSIT.
update kk_st_deposit
set client_name = z.new_client_name,
dt = z.new_dt,
amount = z.new_amount,
active = 'Y'
where deposit_id = z.old_deposit_id;
updates_count := updates_count + 1;
end if;
end loop;
commit;
end load_kk_st_deposit;
Вызовем ее и посмотрим dbms_output:
declare
i integer;
d integer;
u integer;
begin
load_kk_st_deposit(i, d, u);
dbms_output.put_line('Вставлено новых активных записей ' || i);
dbms_output.put_line('Дезактивировано старых записей ' || d);
dbms_output.put_line('Изменено имеющихся записей ' || u);
end;
Посмотрим, что загрузилось в kk_st_deposit:
select * from kk_st_deposit;
