Ви б не писали заявку з функціями довжиною 200 рядків. Ви розкладете ці довгі функції на більш дрібні функції, кожна з яких має чітко визначену відповідальність.
Навіщо писати свій SQL так?
Розкладіть свої запити так само, як ви розкладаєте свої функції. Це робить їх коротшими, простішими, легшими для розуміння, легшими для тестування , легшими для рефакторації. І це дозволяє вам додавати "прокладки" між ними та "обгортки" навколо них, як ви це робите в процесуальному кодексі.
Як це зробити? Здійснюючи кожну важливу річ, запит перетворюється на представлення. Тоді ви складаєте більш складні запити з цих простих поглядів, так само, як ви складаєте більш складні функції з більш примітивних функцій.
І чудова річ, що для більшості композицій переглядів ви отримаєте точно таку ж продуктивність від своїх RDBMS. (Для деяких ви цього не зробите; то що? Передчасна оптимізація - це корінь усього зла. Спочатку правильно вкажіть, а потім оптимізуйте, якщо вам потрібно.)
Ось приклад використання декількох поглядів для розкладання складного запиту.
У прикладі, оскільки кожен вид додає лише одну трансформацію, кожен може бути незалежно перевірений, щоб знайти помилки, а тести - прості.
Ось базова таблиця в прикладі:
create table month_value(
eid int not null, month int, year int, value int );
Ця таблиця є помилковою, оскільки вона використовує два стовпці, місяць та рік, щоб представити одну дату, абсолютний місяць. Ось наша специфікація для нового, обчисленого стовпця:
Ми зробимо це як лінійне перетворення, таке, що воно сортує так само, як (рік, місяць), і таке, що для будь-якого (року, місяця) кортежу є одне і єдине значення, і всі значення є послідовними:
create view cm_absolute_month as
select *, year * 12 + month as absolute_month from month_value;
Тепер те, що ми маємо перевірити, притаманне нашій специфікації, а саме те, що для будь-якого кортежу (рік, місяць) існує один і лише один (абсолютний_місяць), і що (абсолютний_місяць) є послідовними. Давайте напишемо кілька тестів.
Наш тест представлятиме собою SQL- select
запит із такою структурою: тестове ім'я та випадок справи, які проходять катетоване разом. Назва тесту - це лише довільна рядок. Опис справи є лише case when
тестовими твердженнями then 'passed' else 'failed' end
.
Тестові висловлювання будуть просто виборами SQL (підзапити), які повинні бути правдивими для проходження тесту.
Ось наш перший тест:
--a select statement that catenates the test name and the case statement
select concat(
-- the test name
'For every (year, month) there is one and only one (absolute_month): ',
-- the case statement
case when
-- one or more subqueries
-- in this case, an expected value and an actual value
-- that must be equal for the test to pass
( select count(distinct year, month) from month_value)
--expected value,
= ( select count(distinct absolute_month) from cm_absolute_month)
-- actual value
-- the then and else branches of the case statement
then 'passed' else 'failed' end
-- close the concat function and terminate the query
);
-- test result.
Запуск цього запиту дає такий результат: For every (year, month) there is one and only one (absolute_month): passed
Поки є достатньо даних тесту в value_value, цей тест працює.
Ми також можемо додати тест для достатньої кількості тестових даних:
select concat( 'Sufficient and sufficiently varied month_value test data: ',
case when
( select count(distinct year, month) from month_value) > 10
and ( select count(distinct year) from month_value) > 3
and ... more tests
then 'passed' else 'failed' end );
Тепер перевіримо, чи це послідовно:
select concat( '(absolute_month)s are consecutive: ',
case when ( select count(*) from cm_absolute_month a join cm_absolute_month b
on ( (a.month + 1 = b.month and a.year = b.year)
or (a.month = 12 and b.month = 1 and a.year + 1 = b.year) )
where a.absolute_month + 1 <> b.absolute_month ) = 0
then 'passed' else 'failed' end );
Тепер давайте помістимо наші тести, які є лише запитами, у файл та запустіть цей скрипт проти бази даних. Дійсно, якщо ми зберігаємо визначення нашого виду у скрипті (або скриптах, я рекомендую один файл на пов’язані перегляди), щоб запускатись до бази даних, ми можемо додати наші тести для кожного перегляду до того ж сценарію, щоб дія (повторно) -) створення нашого виду також запускає тести подання. Таким чином, ми обидва отримуємо регресійні тести, коли ми створюємо перегляди, і, коли створення представлення буде суперечити виробництву, погляд також буде перевірений у виробництві.