使用触发器时如何避免突变 table 错误?
How to avoid mutating table error while using a trigger?
我需要在 Table_A
中插入行,其中值来自 Table_B
Table_B
的 UPDATE。
table_A (
station int,
state varchar(20),
CONSTRAINT pk_table_a PRIMARY KEY(station, state),
CONSTRAINT fk_table_A FOREIGN KEY (station, state)
REFERENCES table_B (station, state)
)
table_B (
station int,
state varchar(20),
player int,
date_sent Date DEFAULT NULL
CONSTRAINT pk_table_b PRIMARY KEY(station, state, player)
)
现在,当这些 (station, state)
的所有日期都变成 table_B
中的 NOT NULL
时,我的触发器需要向 table_A (station, state)
添加一行。
这是我的实际原因 mutating table error
:
CREATE OR REPLACE TRIGGER add_stations_sent
AFTER INSERT OR UPDATE ON "TABLE_B"
FOR EACH ROW
WHEN (NEW.DATE_SENT IS NOT NULL)
DECLARE
nb_stations_null number;
BEGIN
SELECT COUNT(1)
INTO nbr_stations_null
FROM "TABLE_B"
WHERE "TABLE_B".STATE = :NEW.STATE AND
"TABLE_B".STATION <> :NEW.STATION AND
"TABLE_B".DATE_SENT IS NULL;
IF (nb_stations_null = 0) THEN
INSERT INTO "TABLE_A" VALUES (:NEW.STATION, :NEW.STATE);
END IF;
END;
这样的事情会将处理推迟到 AFTER STATEMENT 级别,从而允许您 运行 查询
create or replace
trigger avoid_mutate
for insert or update on table_b
compound trigger
l_station sys.odcivarchar2list := sys.odcivarchar2list();
l_state sys.odcivarchar2list := sys.odcivarchar2list();
before each row is
begin
l_station.extend;
l_state.extend;
l_station(l_station.count) := :new.station;
l_state(l_state.count) := :new.state;
end before each row;
after statement is
declare
nb_stations_null number;
begin
for i in 1 .. l_station.count loop
SELECT COUNT(1)
INTO nbr_stations_null
FROM "TABLE_B"
WHERE "TABLE_B".STATE = l_state(i) AND
"TABLE_B".STATION <> l_station(i) AND
"TABLE_B".DATE_SENT IS NULL;
IF (nb_stations_null = 0) THEN
INSERT INTO "TABLE_A" VALUES (l_station(i), l_state(i));
END IF;
end after statement;
end;
/
我需要在 Table_A
中插入行,其中值来自 Table_B
Table_B
的 UPDATE。
table_A (
station int,
state varchar(20),
CONSTRAINT pk_table_a PRIMARY KEY(station, state),
CONSTRAINT fk_table_A FOREIGN KEY (station, state)
REFERENCES table_B (station, state)
)
table_B (
station int,
state varchar(20),
player int,
date_sent Date DEFAULT NULL
CONSTRAINT pk_table_b PRIMARY KEY(station, state, player)
)
现在,当这些 (station, state)
的所有日期都变成 table_B
中的 NOT NULL
时,我的触发器需要向 table_A (station, state)
添加一行。
这是我的实际原因 mutating table error
:
CREATE OR REPLACE TRIGGER add_stations_sent
AFTER INSERT OR UPDATE ON "TABLE_B"
FOR EACH ROW
WHEN (NEW.DATE_SENT IS NOT NULL)
DECLARE
nb_stations_null number;
BEGIN
SELECT COUNT(1)
INTO nbr_stations_null
FROM "TABLE_B"
WHERE "TABLE_B".STATE = :NEW.STATE AND
"TABLE_B".STATION <> :NEW.STATION AND
"TABLE_B".DATE_SENT IS NULL;
IF (nb_stations_null = 0) THEN
INSERT INTO "TABLE_A" VALUES (:NEW.STATION, :NEW.STATE);
END IF;
END;
这样的事情会将处理推迟到 AFTER STATEMENT 级别,从而允许您 运行 查询
create or replace
trigger avoid_mutate
for insert or update on table_b
compound trigger
l_station sys.odcivarchar2list := sys.odcivarchar2list();
l_state sys.odcivarchar2list := sys.odcivarchar2list();
before each row is
begin
l_station.extend;
l_state.extend;
l_station(l_station.count) := :new.station;
l_state(l_state.count) := :new.state;
end before each row;
after statement is
declare
nb_stations_null number;
begin
for i in 1 .. l_station.count loop
SELECT COUNT(1)
INTO nbr_stations_null
FROM "TABLE_B"
WHERE "TABLE_B".STATE = l_state(i) AND
"TABLE_B".STATION <> l_station(i) AND
"TABLE_B".DATE_SENT IS NULL;
IF (nb_stations_null = 0) THEN
INSERT INTO "TABLE_A" VALUES (l_station(i), l_state(i));
END IF;
end after statement;
end;
/