我刚刚开始学习触发器,所以请耐心等待。如果插入的行的礼物与表格中已有的礼物相同,请打印一条消息,说明礼物已经从捐赠者那里赠送给接收者。
create or replace TRIGGER Same_Gift_Given
BEFORE INSERT ON GIVING
FOR EACH ROW
DECLARE
giftgiven varchar(255);
BEGIN
SELECT giftname INTO giftgiven from GIVING;
IF :new.giftname = giftgiven then
dbms_output.put_line(giftgiven || ' has already been gifted to ' || giving.receiver || ' by ' || giving.donor);
end if;
END;
答案 0 :(得分:4)
这是一个非常糟糕的作业问题。在真实系统中,你永远不会让我们触发这样的事情。它将打破大多数INSERT
操作,如果有多个用户,它将失败。实际上,您将使用约束。实际上,如果由于某种原因你被迫用枪指使用触发器,你需要一系列三个触发器,一个包和一个集合才能正确地完成它。
教授可能正在寻找什么
但是,要强调的是,你永远不会考虑在真实系统中这样做
create or replace trigger same_gift_given
before insert on giving
for each row
declare
l_existing_row giving%rowtype;
begin
select *
into l_existing_row
from giving
where giftname = :new.giftname
and rownum = 1;
dbms_output.put_line( :new.giftname ||
' has already been gifted to ' ||
l_existing_row.receiver ||
' from ' ||
l_existing_row.donor );
exception
when no_data_found
then
null;
end;
这不会阻止您插入重复的行。如果您尝试在INSERT ... VALUES
表上执行除giving
之外的任何操作,它将引发变异触发错误。效率低下。它不处理多个会话。简而言之,它绝对是一个绝不应该在任何真实系统中使用的恶意代码。
你会在现实中做些什么
实际上,你会创建一个约束
ALTER TABLE giving
ADD CONSTRAINT unique_gift UNIQUE( giftname );
这将在多用户环境中起作用。它不会抛出变异触发器异常。效率更高。它的代码要少得多。它实际上可以防止插入重复的行。
答案 1 :(得分:0)
让我们尝试一些不同的东西:
CREATE OR REPLACE TRIGGER GIVING_COMPOUND_INSERT
FOR INSERT ON GIVING
COMPOUND TRIGGER
TYPE STRING_COL IS TABLE OF VARCHAR2(255) INDEX BY VARCHAR2(255);
colGiftnames STRING_COL;
aGiftname VARCHAR2(255);
nCount NUMBER;
-- Note that the way the associative array is used here is a bit of a cheat.
-- In the BEFORE EACH ROW block I'm putting the string of interest into the
-- collection as both the value *and* the index. Then, when iterating the
-- collection only the index is used - the value is never retrieved (but
-- since it's the same as the index, who cares?). I do this because I'd
-- rather not write code to call a constructor and maintain the collections
-- size - so I just use an associative array and let Oracle do the work for
-- me.
BEFORE EACH ROW IS
BEGIN
colGiftnames(:NEW.GIFTNAME) := :NEW.GIFTNAME;
END BEFORE EACH ROW;
AFTER STATEMENT IS
BEGIN
aGiftname := colGiftnames.FIRST;
WHILE aGiftname IS NOT NULL LOOP
SELECT COUNT(*)
INTO nCount
FROM GIVING
WHERE GIFTNAME = aGiftname;
IF nCount > 1 THEN
DBMS_OUTPUT.PUT_LINE('Found ' || nCount || ' instances of gift ''' ||
aGiftname || '''');
RAISE_APPLICATION_ERROR(-20001, 'Found ' || nCount ||
' instances of gift ''' ||
aGiftname || '''');
END IF;
aGiftname := colGiftnames.NEXT(aGiftname);
END LOOP;
END AFTER STATEMENT;
END GIVING_COMPOUND_INSERT;
同样,这是一种尝试保证唯一性的LOUSY方式。实际上,执行此操作的“正确方法”是使用约束(UNIQUE或PRIMARY KEY)。仅仅因为可以做某事并不意味着应该。
分享并享受。