Создайте триггер, который обновляет столбец в одной таблице, когда обновляется столбец в другой таблице
У меня есть две таблицы
Заказ (id, дата, примечание)
и
Доставка (Id, Note, Date)
Я хочу создать триггер, который обновляет дату в Delivery, когда дата обновляется в Order.
Я думал сделать что-то вроде
CREATE OR REPLACE TRIGGER your_trigger_name
BEFORE UPDATE
ON Order
DECLARE
BEGIN
UPDATE Delivery set date = ??? where id = ???
END;
Как получить идентификатор даты и строки?
спасибо
Ответы
Ответ 1
Как получить идентификатор даты и строки?
Предположим, что это столбцы на вашей таблице ORDER, называемые DELIVERY_DATE, и идентификатор вашего триггера должен выглядеть примерно так:
CREATE OR REPLACE TRIGGER your_trigger_name
BEFORE UPDATE ON Order
FOR EACH ROW
BEGIN
if :new.delivery_date != :old.delivery_date
then
UPDATE Delivery d
set d.delivery_date = :new.delivery_date
where d.order_id = :new.id;
end if;
END;
Обратите внимание на предложение FOR EACH ROW: это необходимо для ссылки на значения из отдельных строк. Я использовал конструкцию IF для проверки выполнения UPDATE при поставке. Если у вас нет другой логики в вашем триггере, вы можете написать ее так:
CREATE OR REPLACE TRIGGER your_trigger_name
BEFORE UPDATE OF delivery_date ON Order
FOR EACH ROW
BEGIN
UPDATE Delivery d
set d.delivery_date = :new.delivery_date
where d.order_id = :new.id;
END;
Я ответил на заданный вами вопрос, но, как и в сторону, я укажу, что ваша модель данных неоптимальна. Правильно нормализованный дизайн будет содержать DELIVERY_DATE только в одной таблице: DELIVERY кажется логичным местом для него.
Ответ 2
В триггере есть неявная новая и старая ссылка в виде:
ССЫЛКА НА СТАРОСТИ С НОВЫМ НОВЫМ
Вы можете записать в значение: NEW, но не в значение: OLD.
UPDATE Delivery set date = :new.delivery_date where id = :new.id;
CREATE OR REPLACE TRIGGER "BUR_TABLENAME" BEFORE
UPDATE ON "TABLE" FOR EACH ROW
BEGIN
If :new.active_date is not null Then
:new.active_date := TRUNC(:new.active_date);
End If;
END;
Шаблон:
CREATE OR REPLACE TRIGGER TRIGGER_NAME
BEFORE
UPDATE
ON TABLE_NAME
REFERENCING OLD AS OLD NEW AS NEW
FOR EACH ROW
DECLARE
V_VARIABLE NUMBER (1);
BEGIN
//Do Stuff;
null;
end;
Ответ 3
Используйте переменные связывания OLD и NEW. OLD ссылается на обновляемую строку или столбец до внесения изменений; NEW ссылается на него после изменения.
CREATE OR REPLACE TRIGGER trig1
BEFORE UPDATE
ON order REFERENCING NEW AS new
FOR EACH ROW
BEGIN
UPDATE delivery
SET ddate = :new.ddate
WHERE id = :new.id;
END;
Вы можете изменить предложение REFERENCING
, чтобы дать вашим переменным связывания разные имена. Вы можете включить OLD as <name>
тоже. Пример:
CREATE OR REPLACE TRIGGER trig1
BEFORE UPDATE
ON order REFERENCING OLD AS old_values NEW AS new_values
...
Если вы не хотите изменять имена по умолчанию "старый" и "новый", вы можете полностью исключить предложение REFERENCING
.
Ответ 4
Всякий раз, когда есть необходимость в этом типе триггера, посмотрите на свой дизайн. Есть ли необходимость в отдельной записи о доставке? У заказа действительно есть более одной доставки?
Триггеры кажутся приятными, но они, как правило, довольно быстро меняют вещи.