- •Введение.
- •Соединение с бд 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.
- •Задача. Взятие последней записи о клиенте.
- •Задача. Отчет об изменениях зарплаты.
- •Задача. Пакет функций о вкладах.
- •Задача. Группировка лога выполнения процессов.
- •Задача. Вьюшка с аналитическими функциями по вкладам.
- •Задача. Календарь с аналитикой.
- •Задача. Поиск баланса счета на заданную дату.
- •Задача. Удаление исторических данных о рейтинге.
- •Функции, выдающие более одного значения.
- •Задача. Вызов многозначной функции.
- •"Расклейка" и "склейка" строк.
- •“Расклейка” одной строки.
- •“Расклейка” нескольких строк с группировкой.
- •“Склейка” в одну строку.
- •“Склейка” нескольких строк с группировкой.
- •Задача. Простая расклейка-склейка.
- •Задача. Скрипт создания индексов.
- •Задача. Скрипт создания таблиц.
- •Задача. Отчет о созданных объектах.
- •Задача. Отчет о числе строк в таблицах.
- •Задача. Расклейка списка хобби.
- •Задача. Склейка запроса о максимумах числовых полей.
- •Оптимизация запросов.
Триггеры.
Триггеры чаще всего "вешаются" на таблицы. В триггерах пишут, какие действия нужно совершить перед изменением данных в таблице или после изменения данных в таблице. По этому признаку триггеры бывают BEFORE и AFTER. Триггеры можно "вешать" на события INSERT, UPDATE, DELETE. В триггерах можно проверять, какое именно из действий совершается (IF inserting THEN ..., IF updating THEN ..., IF deleting THEN ..., ), а также обращаться к предыдущим и новым значениям полей (например, v_old_id := :old.ID; :new.ID := v_new_id).
Подробности мы разберем в задачах ниже.
Задача. Автоинкрементное поле.
Создать таблицу KK_14 с полями ID и VAL, создать сиквенс SQ_KK_14.
Написать BEFORE INSERT триггер, который делает следующее: если при вставке в KK_14 не указано ID, то значение ID берется из сиквенса SQ_KK_14. Это реализация автоинкрементного поля.
Создадим таблицу и сиквенс:
CREATE TABLE KK_14(ID NUMBER, VAL VARCHAR2(20));
CREATE SEQUENCE SQ_KK_14;
Создадим триггер:
CREATE OR REPLACE TRIGGER KK_TRIG_BI_KK_14
BEFORE INSERT ON KK_14
FOR EACH ROW
BEGIN
IF :NEW.ID IS NULL THEN
SELECT SQ_KK_14.NEXTVAL INTO :NEW.ID FROM DUAL;
END IF;
END KK_TRIG_BI_KK_14;
Вставляем строки, не указав значения поля ID:
INSERT INTO KK_14(VAL) VALUES ('FJI');
INSERT INTO KK_14(VAL) VALUES ('SDA');
Проверяем, что ID заполнились из сиквенса:
SELECT * FROM KK_14;
Задача. Триггер конвертации сумм в валюте.
Дана таблица курсов KK_RATE (RATE_DATE - дата курса, CURRENCY_CODE - код валюты, RATE - сам курс).
Дана таблица платежей KK_PAYMENT (PAYMENT_DATE - дата платежа, CURRENCY_CODE - код валюты, PAYMENT_SUM_IN_CURRENCY – сумма платежа в валюте CURRENCY_CODE, PAYMENT_SUM_IN_RUB - сумма платежа, пересчитанная в рублях).
Требуется создать BEFORE INSERT OR UPDATE триггер, который по заданным полям PAYMENT_DATE, CURRENCY_CODE, PAYMENT_SUM_IN_CURRENCY автоматически рассчитывает поле PAYMENT_SUM_IN_RUB согласно таблице курсов KK_RATE.
Если курс не найден, выдавать об этом сообщение в dbms_output, но оставлять в PAYMENT_SUM_IN_RUB null.
Создадим таблицы:
create table KK_RATE
(
rate_date DATE,
currency_code INTEGER,
rate NUMBER(6,2)
);
insert into KK_RATE(RATE_DATE, CURRENCY_CODE, RATE) values(to_date('22.03.2012','dd.mm.yyyy'), 840, 29.43);
insert into KK_RATE(RATE_DATE, CURRENCY_CODE, RATE) values(to_date('23.03.2012','dd.mm.yyyy'), 840, 29.35);
insert into KK_RATE(RATE_DATE, CURRENCY_CODE, RATE) values(to_date('22.03.2012','dd.mm.yyyy'), 978, 38.42);
insert into KK_RATE(RATE_DATE, CURRENCY_CODE, RATE) values(to_date('23.03.2012','dd.mm.yyyy'), 978, 38.45);
create table KK_PAYMENT
(
payment_date DATE,
currency_code INTEGER,
payment_sum_in_currency NUMBER(6,2),
payment_sum_in_rub NUMBER(6,2)
);
Создадим решающий задачу триггер:
CREATE OR REPLACE TRIGGER KK_TRIG_BIU_KK_PAYMENT
BEFORE INSERT OR UPDATE ON KK_PAYMENT
FOR EACH ROW
DECLARE
V_RATE KK_RATE.RATE%TYPE;
BEGIN
BEGIN
SELECT RATE
INTO V_RATE
FROM KK_RATE
WHERE KK_RATE.CURRENCY_CODE = :NEW.CURRENCY_CODE
AND KK_RATE.RATE_DATE = :NEW.PAYMENT_DATE;
EXCEPTION
WHEN NO_DATA_FOUND THEN
DBMS_OUTPUT.PUT_LINE('RATE NOT FOUND');
END;
:NEW.PAYMENT_SUM_IN_RUB := V_RATE * :NEW.PAYMENT_SUM_IN_CURRENCY;
END KK_TRIG_BIU_KK_PAYMENT;
Осуществим проверочные вставки, указываем 3 поля, 4ое рассчитывается триггером:
INSERT INTO KK_PAYMENT(PAYMENT_DATE, CURRENCY_CODE, PAYMENT_SUM_IN_CURRENCY) VALUES(TO_DATE('22.03.2012', 'DD.MM.YYYY'), 840, 100);
INSERT INTO KK_PAYMENT(PAYMENT_DATE, CURRENCY_CODE, PAYMENT_SUM_IN_CURRENCY) VALUES(TO_DATE('23.03.2012', 'DD.MM.YYYY'), 978, 100);
INSERT INTO KK_PAYMENT(PAYMENT_DATE, CURRENCY_CODE, PAYMENT_SUM_IN_CURRENCY) VALUES(TO_DATE('30.10.1980', 'DD.MM.YYYY'), 840, 2);
Смотрим результат (в т. ч. DBMS_OUTPUT после каждой вставки):
SELECT * FROM KK_PAYMENT;
Сделаем update:
UPDATE KK_PAYMENT
SET PAYMENT_SUM_IN_CURRENCY = 200
WHERE PAYMENT_DATE = TO_DATE('23.03.2012', 'DD.MM.YYYY')
AND CURRENCY_CODE = 978
AND PAYMENT_SUM_IN_CURRENCY = 100;
Смотрим результат:
SELECT * FROM KK_PAYMENT;
