Создание триггера для разрешения INSERT, если существующие данные не равны NULL - PullRequest
0 голосов
/ 17 марта 2020

У меня есть следующая таблица, и я хочу создать триггер, который позволяет вставлять значения, если значение ActualLeaveDate не равно нулю:

CREATE TABLE Bed
( 
    PatBedNum NUMBER GENERATED BY DEFAULT AS IDENTITY START WITH 1 INCREMENT BY 1,
    WardNum NUMBER(4),
    BedNum NUMBER(2),
    PatNum VARCHAR2(6) CHECK (PatNum LIKE '%P%'),
    DateOnWaitlist DATE,
    ExpectedStayDuration VARCHAR2(8) CHECK (ExpectedStayDuration LIKE '% days%'),
    DatePlacedInWard DATE,
    ExpectedLeaveDate DATE,
    ActualLeaveDate DATE,
    CONSTRAINT BedPK PRIMARY KEY (PatBedNum),
    CONSTRAINT PatBedNum FOREIGN KEY (PatNum)
         REFERENCES Patient (PatNum) ON DELETE CASCADE,
    CONSTRAINT PatWardNum FOREIGN KEY (WardNum)
         REFERENCES Ward (WardNum) ON DELETE CASCADE
);

Я пытался создать триггер, используя следующую script:

CREATE TRIGGER BedCheck2
BEFORE INSERT ON BED
FOR EACH ROW
BEGIN
    IF (:Old.ActualLeaveDate IS NOT NULL)
    THEN
        INSERT INTO Bed (PatBedNum, WardNum, BedNum, PatNum, DateOnWaitlist,  ExpectedStayDuration, DatePlacedInWard, ExpectedLeaveDate, ActualLeaveDate)
        VALUES (:New.PatBedNum, :New.WardNum, :New.BedNum, :New.PatNum, :New.DateOnWaitlist, :New.ExpectedStayDuration, :New.DatePlacedInWard, :New.ExpectedLeaveDate, :New.ActualLeaveDate);        
    ELSE
        RAISE_APPLICATION_ERROR (-20002, 'Bed ' || :Old.BedNum || 'is not empty!');    
    END IF;
END;
/

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

INSERT INTO BED VALUES (5, 11, 84, 'P10787', '12/1/20', '5 days', '17/1/20', '22/1/20', NULL);

Кроме того, она направляется прямо к RAISE_APPLICATION_ERROR, даже если данные в «ActualLeaveDate» в базе данных не равны NULL.

Я что-то здесь упускаю или делаю что-то не так?

Ответы [ 2 ]

2 голосов
/ 17 марта 2020

Почему бы просто не добавить ограничение NOT NULL к этому столбцу?

CREATE TABLE Bed (
    ...,
    ActualLeaveDate DATE NOT NULL,
    ...
)

Если вы хотите, чтобы значения ActualLeaveDate и BedNum были null (или * 1009) *), вы можете использовать проверочное ограничение:

CREATE TABLE Bed (
    ...,
    BedNum NUMBER(2),
    ActualLeaveDate DATE,
    ...
    CHECK (
        (BedNum IS NOT NULL AND ActualLeaveDate IS NULL)
        OR (BedNum IS NULL AND ActualLeaveDate IS NOT NULL)
    )
)
0 голосов
/ 17 марта 2020

Триггер не может изменить ту же таблицу, которая его отключает, поэтому оператор вставки никогда не будет работать. Фактически это избыточно, поскольку у вас уже есть вставка, которая запускает триггер. См. Эти ссылки в качестве ссылки:

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

CREATE TRIGGER BedCheck2
BEFORE INSERT ON BED
FOR EACH ROW
BEGIN
    IF (:Old.ActualLeaveDate IS NOT NULL and :Old.BedNum IS NOT NULL)
    THEN
        RAISE_APPLICATION_ERROR (-20002, 'Bed ' || :Old.BedNum || 'is not empty!');    
    END IF;
END;
/

Вы можете использовать только необходимые бизнес-логики c в своем приложении перед отправкой оператора вставки, использовать традиционное ограничение, описанное @GMB, или использовать ограничение на основе функций как описано здесь: http://www.dba-oracle.com/t_sql_patterns_constraints.htm.

...