Oracle DB, Oracle APEX, Linux etc.

понедельник, 15 марта 2010 г.

ORA-38104: Бомба с часовым механизмом

Так сказать, моя небольшая история об неудачном дизайне.

Была задача, которую в двух словах можно описать так: хранить некоторые меняющиеся во времени значения. Одно значение должно сменять другое, без разрывов в периодах.

Нет проблем, подумал я. Всё это реализуется декларативно, через ограничения целостности. Где-то так:


create table test_params
( param_id number -- параметр
, prev_end_date date -- дата окончания прошлой записи
, start_date date -- дата начала текущей записи
, end_date date -- дата конца текущей записи
, value varchar2(10)
, primary key (param_id, start_date)
, unique (param_id, end_date)
, check(start_date - 1 = prev_end_date)
, check(end_date >= start_date)
, check(start_date = trunc(start_date))
, check(end_date = trunc(end_date))
, check(prev_end_date = trunc(prev_end_date)) );

alter table test_params
add constraint test_params_fk_chain
foreign key (param_id, prev_end_date)
references test_params(param_id, end_date)
deferrable
initially immediate;


В реальной системе всё немного сложнее (param_id ссылается на таблицу с определениями параметров), но это хорошо отражает суть.

Всё было отлично, вокруг таблицы создавался PL/SQL-код... А затем мне понадобилось написать в пакете процедуру для обновления start_date и end_date у заданной записи. Очевидно, что при их изменении нужно соответствующим образом изменить предыдущую и следующую запись в цепочке значений параметра. "Если ты можешь сделать это через SQL - сделай это так," - говорит дядя Том. И я решил сделать это через MERGE. И вот тут-то стремление к минимализму при проектировании меня подвело: изменять поле, которое используется в on_clause, MERGE отказался наотрез. ORA-38104, господа и дамы. А пересоздание ограничений откладываемыми привнесёт ещё больше проблем.

Вывод: сэкономив на поле для суррогатного первичного ключа, я потерял время, которое теперь необходимо для того, чтобы его добавить. Дизайн нужно продумывать с учётом ограничений способов, которыми будет вестись работа. :)

Комментариев нет:

Отправить комментарий