
- •Введение.
- •Соединение с бд 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.
- •Задача. Взятие последней записи о клиенте.
- •Задача. Отчет об изменениях зарплаты.
- •Задача. Пакет функций о вкладах.
- •Задача. Группировка лога выполнения процессов.
- •Задача. Вьюшка с аналитическими функциями по вкладам.
- •Задача. Календарь с аналитикой.
- •Задача. Поиск баланса счета на заданную дату.
- •Задача. Удаление исторических данных о рейтинге.
- •Функции, выдающие более одного значения.
- •Задача. Вызов многозначной функции.
- •"Расклейка" и "склейка" строк.
- •“Расклейка” одной строки.
- •“Расклейка” нескольких строк с группировкой.
- •“Склейка” в одну строку.
- •“Склейка” нескольких строк с группировкой.
- •Задача. Простая расклейка-склейка.
- •Задача. Скрипт создания индексов.
- •Задача. Скрипт создания таблиц.
- •Задача. Отчет о созданных объектах.
- •Задача. Отчет о числе строк в таблицах.
- •Задача. Расклейка списка хобби.
- •Задача. Склейка запроса о максимумах числовых полей.
- •Оптимизация запросов.
Задача. Удаление дубликатов.
Есть таблица KK_STUDENTS с единственным полем NAME - именами студентов.
Требуется убрать дубликаты, т.е. оставить каждое имя по 1 разу.
Создадим таблицу:
CREATE TABLE KK_STUDENTS
(
NAME varchar(50)
);
Заполним ее данными:
insert into KK_STUDENTS(NAME) values('Алексей');
insert into KK_STUDENTS(NAME) values('Сергей');
insert into KK_STUDENTS(NAME) values('Иван');
insert into KK_STUDENTS(NAME) values('Андрей');
insert into KK_STUDENTS(NAME) values('Иван');
insert into KK_STUDENTS(NAME) values('Алексей');
insert into KK_STUDENTS(NAME) values('Пётр');
insert into KK_STUDENTS(NAME) values('Алексей');
В каждой таблице есть системное поле ROWID, представляющее собой физический адрес строки. При апдейтах строк их ROWID не меняются. Поиск строки в большой таблице по заданному значению ROWID Oracle осуществляет очень быстро.
Посмотрим, какие записи вставились в таблицу:
select rowid, name from kk_students;
Вот эти записи мы оставим, а остальные удалим:
select name, min(rowid) from kk_students group by name;
Приведем delete, решающий задачу:
delete from kk_students
where rowid not in (select min(rowid) from kk_students group by name);
Если в таблице есть первичный ключ или другие уникальные ключи, то их можно использовать вместо ROWID для решения задачи удаления дубликатов.
Задача. Удаление по условию not in.
Создать таблицу KK_XX c данными
NAME |
DT |
VAL |
Красный |
07.08.2011 |
123 |
Красный |
17.11.2011 |
513425 |
Красный |
19.02.2012 |
3245 |
Cиний |
07.08.2011 |
879 |
Cиний |
07.08.2011 |
932 |
Зеленый |
07.08.2011 |
89123 |
Зеленый |
05.09.2011 |
89210 |
Зеленый |
05.09.2011 |
6365 |
Написать один оператор DELETE, который оставит для каждого NAME только записи с максимальным DT, а более ранние записи удалит.
Создадим таблицу и заполним ее данными:
create table KK_XX(name varchar2(30), dt date, val number);
insert into KK_XX(name, dt, val) values('Красный', to_date('07.08.2011','dd.mm.yyyy'), 123);
insert into KK_XX(name, dt, val) values('Красный', to_date('17.11.2011','dd.mm.yyyy'), 513425);
insert into KK_XX(name, dt, val) values('Красный', to_date('19.02.2012','dd.mm.yyyy'), 3245);
insert into KK_XX(name, dt, val) values('Cиний', to_date('07.08.2011','dd.mm.yyyy'), 879);
insert into KK_XX(name, dt, val) values('Cиний', to_date('07.08.2011','dd.mm.yyyy'), 932);
insert into KK_XX(name, dt, val) values('Зеленый', to_date('07.08.2011','dd.mm.yyyy'), 89123);
insert into KK_XX(name, dt, val) values('Зеленый', to_date('05.09.2011','dd.mm.yyyy'), 89210);
insert into KK_XX(name, dt, val) values('Зеленый', to_date('05.09.2011','dd.mm.yyyy'), 6365);
Проведем удаление:
DELETE FROM KK_XX
WHERE (NAME, DT) NOT IN (SELECT NAME, MAX(DT) FROM KK_XX GROUP BY NAME);
Проверим результат:
select * from KK_XX;
Замена exists/not exists на left join + rowid.
Создадим таблицу - справочник цветов - и заполним ее данными (поле NAME - уникально):
create table KK_COLORS(name varchar2(30));
insert into KK_COLORS(name) values ('Серый');
insert into KK_COLORS(name) values ('Зеленый');
insert into KK_COLORS(name) values ('Красный');
insert into KK_COLORS(name) values ('Черный');
Тогда запрос с "exists"
select KK_XX.*
from KK_XX
where exists (select 1 from KK_COLORS where KK_XX.NAME = KK_COLORS.NAME);
можно переписать на запрос с "left join" и "rowid is not null"
select KK_XX.*
from KK_XX
left join KK_COLORS
on KK_XX.NAME = KK_COLORS.NAME
where KK_COLORS.rowid is not null;
А запрос с "not exists"
select KK_XX.*
from KK_XX
where not exists (select 1 from KK_COLORS where KK_XX.NAME = KK_COLORS.NAME);
можно переписать на запрос с "left join" и "rowid is null"
select KK_XX.*
from KK_XX
left join KK_COLORS
on KK_XX.NAME = KK_COLORS.NAME
where KK_COLORS.rowid is null;
Способы с "left join" и "rowid" зачастую работают быстрее, поэтому на практике стоит пробовать их использование.