我有一张下表描述了每个行星使用百分比组成的化学元素。
CREATE TABLE elem_in_planet
(
id_planet INTEGER,
element_symbol CHAR(2),
percent_representation NUMBER CONSTRAINT NN_elem_in_planet NOT NULL,
CONSTRAINT PK_elem_in_planet PRIMARY KEY (id_planet, element_symbol),
CONSTRAINT FK_planet_has_elem FOREIGN KEY (id_planet) REFERENCES planet (id_planet),
CONSTRAINT FK_elem_in_planet FOREIGN KEY (element_symbol) REFERENCES chemical_element (element_symbol)
);
我正在尝试创建一个触发器,当用户向行星添加新元素并且该行星中的元素总数超过100%时向用户发出警告。我想到了这个。
CREATE OR REPLACE TRIGGER elem_in_planet_check
AFTER INSERT OR UPDATE ON elem_in_planet
FOR EACH ROW
DECLARE
sum_var NUMBER;
PRAGMA autonomous_transaction;
BEGIN
SELECT SUM(percent_representation)
INTO sum_var
FROM elem_in_planet
WHERE id_planet = :NEW.id_planet
GROUP BY id_planet;
EXCEPTION
WHEN NO_DATA_FOUND THEN
sum_var := 0;
IF sum_var > 100 THEN
DBMS_OUTPUT.put_line('WARNING: Blah blah.');
END IF;
END;
/
此代码似乎每次都抛出NO_DATA_FOUND异常,即使我插入了测试数据,并且当我单独运行SQL查询时,它也按预期运行。
我是新来的,不明白我在做什么错。
谢谢您的任何建议。
删除PRAGMA autonomous_transaction
,否则您将看不到表中插入的数据(您只会在:NEW
记录中看到它。See also this question。
也请注意,您的IF
语句位于EXCEPTION .. WHEN no_data_found THEN
块中。它不会执行,除非有这样的异常(在sum_var
始终为零的情况下。这是触发器的更正确的版本:
CREATE OR REPLACE TRIGGER elem_in_planet_check
AFTER INSERT OR UPDATE ON elem_in_planet
FOR EACH ROW
DECLARE
sum_var NUMBER;
BEGIN
SELECT SUM(percent_representation)
INTO sum_var
FROM elem_in_planet
WHERE id_planet = :NEW.id_planet;
IF sum_var > 100 THEN
DBMS_OUTPUT.put_line('WARNING: Blah blah.');
END IF;
-- This is probably no longer necessary unless some other trigger prevents the insertion
EXCEPTION
WHEN NO_DATA_FOUND THEN
NULL;
END;
/