
- •Введение.
- •Соединение с бд 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.
- •Задача. Взятие последней записи о клиенте.
- •Задача. Отчет об изменениях зарплаты.
- •Задача. Пакет функций о вкладах.
- •Задача. Группировка лога выполнения процессов.
- •Задача. Вьюшка с аналитическими функциями по вкладам.
- •Задача. Календарь с аналитикой.
- •Задача. Поиск баланса счета на заданную дату.
- •Задача. Удаление исторических данных о рейтинге.
- •Функции, выдающие более одного значения.
- •Задача. Вызов многозначной функции.
- •"Расклейка" и "склейка" строк.
- •“Расклейка” одной строки.
- •“Расклейка” нескольких строк с группировкой.
- •“Склейка” в одну строку.
- •“Склейка” нескольких строк с группировкой.
- •Задача. Простая расклейка-склейка.
- •Задача. Скрипт создания индексов.
- •Задача. Скрипт создания таблиц.
- •Задача. Отчет о созданных объектах.
- •Задача. Отчет о числе строк в таблицах.
- •Задача. Расклейка списка хобби.
- •Задача. Склейка запроса о максимумах числовых полей.
- •Оптимизация запросов.
Задача. Проставление роста животных.
Даны таблицы млекопитающих, птиц и значений среднего роста животных в сантиметрах:
create table mammals(mammal_name varchar2(50), height number, weight number);
insert into mammals(mammal_name) values('жираф');
insert into mammals(mammal_name) values('кит');
create table birds(bird_name varchar2(50), height number, weight number);
insert into birds(bird_name) values('страус');
insert into birds(bird_name) values('курица');
create table animal_heights(animal_name varchar2(50), height number);
insert into animal_heights(animal_name, height) values('жираф', '550');
insert into animal_heights(animal_name, height) values('кошка', '30');
insert into animal_heights(animal_name, height) values('страус', '250');
insert into animal_heights(animal_name, height) values('курица', '35');
Следует проставить в поля mammals.height и birds.height соответствующие значения из animal_heights.
Напишем блок кода, решающий задачу. Для реализации left join в oracle существует возможность упрощенной записи с помощью знака '(+)', которую мы продемонстрируем. Update будем делать по rowid ради повышения скорости работы:
begin
for z in (select a.animal_name, a.height, m.rowid m_rowid, b.rowid b_rowid
from animal_heights a, mammals m, birds b
where a.animal_name = m.mammal_name(+)
and a.animal_name = b.bird_name(+)) loop
if z.m_rowid is not null then
update mammals set height = z.height where rowid = z.m_rowid;
end if;
if z.b_rowid is not null then
update birds set height = z.height where rowid = z.b_rowid;
end if;
end loop;
end;
Посмотрим результаты update-ов:
select * from mammals;
select * from birds;
Jobs.
В оракле есть возможность поставить процедуру на регулярное выполнение по расписанию. Это делается с помощью механизма джобов.
С помощью вызова dbms_job.submit создадим джоб, запускающий процедуру load_kk_st_deposit из задачи "Загрузка данных с помощью full join".
Параметр next_date имеет тип данных date, это показатель, в какой момент времени джоб запустится в первый раз.
В данном вызове "next_date => sysdate + 1 / 24 / 60 / 2" означает, что джоб запустится через полминуты после выполнения нижеприведенного вызова.
Параметр interval имеет строковый тип данных, это показатель, с какой частотой будет выполняться джоб.
В данном вызове "interval => 'trunc(sysdate, ''MI'') + 1 / 24 / 60'" означает, что всякий раз по завершении выполнения джоба он будет ставиться на запуск по расписанию в следующий ближайший момент с целым количеством минут и нулем секунд.
Если вызываемая процедура load_kk_st_deposit будет выполняться быстрее минуты, то джоб будет отрабатывать раз в минуту.
Итак, вызываем создание джоба. Посмотрим получившийся номер джоба в dbms_output:
declare
v_job_number integer;
begin
dbms_job.submit(job => v_job_number,
what => 'declare
i integer;
d integer;
u integer;
begin
load_kk_st_deposit(i, d, u);
end;',
next_date => sysdate + 1 / 24 / 60 / 2,
interval => 'trunc(sysdate, ''MI'') + 1 / 24 / 60');
dbms_output.put_line(to_char(v_job_number));
commit;
end;
(При работе с джобами удобно использовать именованную нотацию.)
Заметим, что на сервере может быть установлено ограничение на количество разрешенных джобов, т.е. вышеприведенный запуск не гарантирует того, что джоб реально стартует.
Поищем, присутствует ли джоб с выдавшимся в dbms_output номером в системной вьюшке user_jobs:
select * from user_jobs where job = 466423;
В этом месте читателю предлагается самостоятельно проверить, что джоб действительно регулярно выполняет процедуру load_kk_st_deposit и занимается загрузкой данных из kk_deposit в kk_st_deposit.
Теперь поменяем джоб с помощью команды dbms_job.change. Сделаем так, чтобы гонялся пустой PL/SQL-блок один раз в час:
begin
dbms_job.change(job => 466423,
what => 'begin null; end;',
next_date => sysdate,
interval => 'trunc(sysdate, ''HH24'') + 1 / 24');
commit;
end;
В этом месте читателю предлагается самостоятельно проверить, что джоб более не занимается загрузкой данных, а ничего полезного уже не делает.
Теперь поставим джобу параметр broken, равный true. Это отключит выполнение джоба, оставив его в памяти.
begin
dbms_job.broken(job => 466423, broken => true);
commit;
end;
Снова включим джоб, установив параметр broken, равный false. Если другие параметры не указаны, то джоб сразу запустится.
begin
dbms_job.broken(job => 466423, broken => false);
commit;
end;
Командой dbms_job.remove можно удалить джоб навсегда.
begin
dbms_job.remove(job => 466423);
commit;
end;
Отметим, что команды dbms_job.change, dbms_job.broken, dbms_job.remove разумно выполнять, когда джоб не занимается выполнением поставленной на расписание процедуры, а отдыхает, ожидая следующего запуска.