创建一个触发器,在插入时抛出异常。

3

我在寒假有几个大学作业,其中一个是在表上创建触发器:

PERSON(ID, Name, Surname, Age);

触发器应该在用户插入具有无效ID的行时通知用户。有效性标准是ID长度为11位。

我尝试编写如下解决方案:

CREATE OR REPLACE TRIGGER person_id_trigg
AFTER INSERT
ON person
DECLARE
  idNew VARCHAR(50);
  lengthException EXCEPTION;
BEGIN
  SELECT id INTO idNew FROM INSERTED;
  IF LENGTH(idNew) <> 11 THEN
  RAISE lengthException;
  END IF;
  EXCEPTION
  WHEN lengthException THEN
  dbms_output.put_line('ID for new person is INVALID. It must be 11 digits long!'); 
END;

然后我意识到INSERTED只存在于SQL Server中,而不是Oracle。

我该怎么办才能解决这个问题呢?


1
使用 BEFORE INSERT,而不是 AFTER INSERT。使用 FOR EACH ROW 子句。不要执行任何查询,只需检查 new.id。阅读此链接以获取详细信息,其中有许多示例:http://docs.oracle.com/cd/B28359_01/appdev.111/b28370/triggers.htm#LNPLS020 - krokodilko
谢谢您的输入,显然我需要阅读这份文档才能理解触发器。 - devBem
1个回答

8
你想要引发异常(这将阻止插入成功)吗?还是你想让插入成功,并向 dbms_output 缓冲区写入一个字符串,该缓冲区可能存在也可能不存在,并且可能被正在运行插入的人看到或不看到?在任何一种情况下,你都希望这是一种行级触发器,而不是语句级触发器,因此你需要添加 for each row 子句。
CREATE OR REPLACE TRIGGER person_id_trigg
  AFTER INSERT
  ON person
  FOR EACH ROW

如果你想引发异常

BEGIN
  IF( length( :new.id ) <> 11 )
  THEN
    RAISE_APPLICATION_ERROR( -20001, 
                             'The new ID value must have a length of 11' );
  END IF;
END;

如果你想可能会输出,但又想保证insert成功的话

BEGIN
  IF( length( :new.id ) <> 11 )
  THEN
    dbms_output.put_line( 'The new ID value must have a length of 11' );
  END IF;
END;

当然,在实际应用中,你不会使用触发器来处理这种情况。在现实世界中,你会使用约束来处理。

感谢您的回答,但是当我尝试编译它时,我遇到了这个错误:错误报告 - ORA-04082:不允许在表级触发器中引用NEW或OLD 04082. 00000 - “不允许在表级触发器中引用NEW或OLD” *原因:触发器正在访问表触发器中的“new”或“old”值。 *操作:删除任何新的或旧的引用。 - devBem
@Roff - 我错过了您将触发器声明为语句级触发器而不是行级触发器的事实。我在我的答案中添加了这一点。 - Justin Cave
谢谢帮助,我已经清楚地理解了触发器的使用方式。现在它可以正常工作了。 - devBem

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接