- •Введение.
- •Соединение с бд 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 or replace package pck_global_values as
v_osuser varchar2(100);
v_sid number;
end;
Создадим таблицу клиентов, в которой при вставке данных оператором запоминается, кто и из какой сессии вставил данные:
create table clients_ext(client_name varchar2(100), osuser varchar2(100), sid number);
Выполним в двух различных сессиях один и тот же код:
-- инициализируем глобальные переменные для многократного использования в рамках сессии:
begin
pck_global_values.v_osuser := SYS_CONTEXT('USERENV', 'OS_USER');
pck_global_values.v_sid := SYS_CONTEXT('USERENV', 'SID');
dbms_output.put_line('v_osuser = ' || pck_global_values.v_osuser);
dbms_output.put_line('v_sid = ' || pck_global_values.v_sid);
end;
-- вставим немного случайных клиентов и сделаем commit:
begin
for i in 1 .. 3 loop
insert into clients_ext
(client_name, osuser, sid)
values
(translate(to_char(trunc(1000000 * dbms_random.value)),
'1234567890',
'ABCDEFGHIJ'),
pck_global_values.v_osuser,
pck_global_values.v_sid);
end loop;
commit;
end;
-- посмотрим, что вставилось:
select * from clients_ext;
Регулярные выражения.
О регулярных выражениях можно почитать по ссылке:
http://apps-oracle.ru/regular_expression-2
Подробнее мы их разберем в задачах ниже.
Задача. Правка некачественных данных регулярными выражениями.
Оператор неаккуратно вводит в поле ввода такие строки:
комиссия по договору ФД-315/11 за просрочку
проценты по вкладу ФП 8712 /10
НДС по договору лизинга №ФК 2983/09 по условиям договора
просрочка по кредиту ФР №812/ 07
С помощью функций работы с регулярными выражениями (regexp) написать запрос, выдающий результат:
ФД 315/11
ФП 8712/10
ФК 2983/09
ФР 812/07
При решении задачи используем именованный подзапрос (с помощью оператора WITH) с данными входной виртуальной таблицы.
Приведем одно из возможных решений этой плохо формализованной, но жизненной задачи:
with a as
(select 'комиссия по договору ФД-315/11 за просрочку' str
from dual
union all
select 'проценты по вкладу ФП 8712 /10' str
from dual
union all
select 'НДС по договору лизинга №ФК 2983/09 по условиям договора' str
from dual
union all
select 'просрочка по кредиту ФР №812/ 07' str
from dual)
select a.str,
regexp_substr(a.str, '([Ф]{1}.{1})') || ' ' ||
regexp_substr(a.str, '([[:digit:]]+)') ||
replace(regexp_substr(a.str, '([/]{1}[ ]*[[:digit:]]+)'), ' ')
from a;
Задача. Парсинг строк с помощью регулярных выражений.
Операторы ввели в текстовые поля много данных (см. данные ниже в решении). Вычленить из строк все номера счетов и все даты. Если несколько счетов или дат, то собрать их через запятую. Что-то можно и пропустить, т.к. данные вводились без каких-либо шаблонов.
В курсоре z заведены исходные данные. Вывод результата осуществляется в dbms_output. Используются символы табуляции для копирования и просмотра результата в Excel:
declare
v_account_numbers_list varchar2(4000);
v_dates_list varchar2(4000);
v_parced_string varchar2(4000);
v_matched_substring varchar2(4000);
begin
for z in (select 'Сч. №#SYS300419629 от 22.01.09 страх. Каско а/м Солен с 27.01.09 по 26.01.10' str
from dual
union all
select 'Сч. №260 от 29.01.09 вода, Луков пер.' str
from dual
union all
select 'Сч. №28 от 12.01.09 аренда за январь, Таганск.' str
from dual
union all
select 'Сч. №30035 от 26.01.09 изготовл. печатей и штампов, Тверь' str
from dual
union all
select 'Сч. №30035 от 26.01.09 изготовл. печатей и штампов, отд. орг-ции раб. Моск.сети' str
from dual
union all
select 'Под отчет (Гусев) проезд. билеты, сл. режима' str
from dual
union all
select 'Сч. №30034 от 26.01.08 изготовл. печатей и штампов, отд. координ. и контроля за деят-тью филиалов' str
from dual
union all
select 'Сч. №6/9209 от 18.02.09 пластилин, Серпухов' str
from dual
union all
select 'Сч. №1 от 31.01.09 комм.услуги (мусор ноябрь-январь, водоснабж. ноябрь-декабрь, газ октябрь-декабрь, землепользование ноябрь-декабрь), Наро-Фоминск' str
from dual
union all
select 'Сч. №845 от 28.02.09 услуги охраны за февраль, Липецкое' str
from dual
union all
select 'Оплата по дог. №Т-46/08 от 05.03.09 за аренду с 12.12 по 31.12.08, ПТ 1645920' str
from dual
union all
select 'Оплата по дог. купли-продажи 7/02 а/м от 05.03.09 Диса' str
from dual
union all
select 'Реализация а/м Диса инв.6441 по дог. 7/02 от 05.03.09' str
from dual
union all
select 'Сч. №22 от 11.03.09 семинар (Шеронова, Кузнецова), отд. фин.отч-ти' str
from dual
union all
select 'Сч. №Н001290/В09 от 20.02.09 доплата за ремонт принтера, Краснопресн.' str
from dual
union all
select 'Сл.зап. от 03.03.09 №02-04-22/СЗ госпошлина по иск. заявл. о взыск. с ООО "Санрайз Раша", ООО "Санрайз Риэл Эстейт", ООО "Санрайз Недвижимость", ООО "Санрайз.ру" Бобылева С.А. задолж. по КД №4036/08 от 13.03.08' str
from dual)
-- цикл по введенным строкам, которые парсятся
loop
-- цикл по поиску номеров счетов
v_account_numbers_list := '';
v_parced_string := z.str;
loop
-- крутим цикл, пока номера счетов удается найти по шаблону в переменную v_matched_substring
v_matched_substring := regexp_substr(v_parced_string, '[№].[^ ]*');
-- накапливаем счета в список v_account_numbers_list
v_account_numbers_list := v_account_numbers_list ||
v_matched_substring || ', ';
-- и убираем их из строки v_parced_string
v_parced_string := replace(v_parced_string, v_matched_substring);
-- когда найти номер счета более не удалось, выходим
exit when v_matched_substring is null;
end loop;
-- цикл по поиску дат
v_dates_list := '';
v_parced_string := z.str;
loop
-- крутим цикл, пока даты удается найти по шаблону в переменную v_matched_substring
v_matched_substring := regexp_substr(v_parced_string,
'(([[:digit:]]{2}[.][[:digit:]]{2}[.][[:digit:]]{2}))|([[:digit:]]{2}[.][[:digit:]]{2})');
-- накапливаем даты в список v_dates_list
v_dates_list := v_dates_list || v_matched_substring || ', ';
-- и убираем их из строки v_parced_string
v_parced_string := replace(v_parced_string, v_matched_substring);
-- когда найти дату более не удалось, выходим
exit when v_matched_substring is null;
end loop;
-- вывод результата через символы табуляции chr(9) для копирования и просмотра в Excel
dbms_output.put_line(z.str || chr(9) ||
rtrim(v_account_numbers_list, ', ') || chr(9) ||
rtrim(v_dates_list, ', '));
end loop;
end;
