Как применить бизнес-логику в базе данных для предотвращения конфликтующих периодов дат, указанных в отдельной таблице (oracle db) - PullRequest
0 голосов
/ 06 декабря 2018

У меня есть 2 таблицы базы данных (K_TILBUD & WEB_PRODUKT_TILBUD):

<b>K_TILBUD</b>
TILBUD_ID - *NUMBER(10,0)*
TILBUD - *VARCHAR2(2000 CHAR)*
AKTIV_STATUS - *VARCHAR2(1 CHAR)*
DATO_FRA - *DATE*
DATO_TIL - *DATE*
<b>WEB_PRODUKT_TILBUD</b>
ID - *NUMBER*
TILBUD_ID - *NUMBER(10,0)*
PRODUKT_ID - *NUMBER(10,0)*
BUTIKK_ID - *VARCHAR2(2 CHAR)*

При создании / обновлении (INSERT & UPDATE) строки WEB_PRODUKT_TILBUD желательно избегать данного «PRODUKT_ID»Комбинация BUTIKK_ID "получает период K_TILBUD (DATO_FRA - DATO_TIL), который находится в конфликте с существующим периодом TILBUD_ID комбинации« PRODUKT_ID & BUTIKK_ID ».

Другими словами: 2 строки в WEB_PRODUKT_TILBUT не могут совпадать с PRODUKT_TILBUD с одинаковымиссылка на K_TILBUD (через TILBUD_ID) с конфликтующими / перекрывающимися периодами дат (DATO_FRA - DATO_TIL).

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

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

Пока что ближайший подход является недействительным триггером:

CREATE OR REPLACE TRIGGER TI_WEB_PRODUKT_TILBUD 
BEFORE INSERT OR UPDATE ON WEB_PRODUKT_TILBUD 
FOR EACH ROW
DECLARE
V_FRADATO DATE;
V_TILDATO DATE;
V_COUNT NUMBER; 
BEGIN
SELECT K_TILBUD.DATO_FRA, K_TILBUD.DATO_TIL 
INTO V_FRADATO, V_TILDATO
FROM K_TILBUD
WHERE K_TILBUD.TILBUD_ID = :NEW.TILBUD_ID;
SELECT COUNT(*) INTO V_COUNT 
FROM WEB_PRODUKT_TILBUD, K_TILBUD 
WHERE WEB_PRODUKT_TILBUD.PRODUKT_ID=:NEW.PRODUKT_ID 
AND WEB_PRODUKT_TILBUD.BUTIKK_ID=:NEW.BUTIKK_ID 
AND WEB_PRODUKT_TILBUD.TILBUD_ID = K_TILBUD.TILBUD_ID 
AND K_TILBUD.DATO_FRA <= V_TILDATO AND K_TILBUD.DATO_TIL >= V_FRADATO;
IF V_COUNT > 0 THEN
    RAISE_APPLICATION_ERROR(-20100, 'Et produkt tilbud kan ikke forekomme flere ganger i samme K_TILBUD periode');
END IF;
EXCEPTION WHEN NO_DATA_FOUND THEN NULL;
END;

Это, конечно, недопустимый триггер базы данных оракула, так как он ссылается на «старую таблицу», что запрещено в триггере- и поэтому выдает следующую ошибку:

Одна ошибка при сохранении изменений в таблице "WEB_PRODUKT_TILBUD": строка 49: ORA-04091: таблица WEB_PRODUKT_TILBUD мутирует, триггер / функция может ее не видеть ORA-06512:в "TI_WEB_PRODUKT_TILBUD", строка 10 ORA-04088: ошибка во время выполнения триггера 'TI_WEB_PRODUKT_TILBUD'

Но попытка триггера иллюстрирует то, что пытается быть достигнуто - как описано в начале.

Можно ли вообще этого достичь?Каким-то другим способом?

Поможет ли это создать хранимую процедуру (аналогично триггеру выше) и вызвать ее из триггера - возможно, сделав ее действительной? *

Любые другие идеи подсказывают, какприменять эту логику на уровне БД?

...