PLSQL: BEFORE INSERT TRIGGER(在允许插入之前检查其他表中的列中的值)

Posted

技术标签:

【中文标题】PLSQL: BEFORE INSERT TRIGGER(在允许插入之前检查其他表中的列中的值)【英文标题】:PLSQL: BEFORE INSERT TRIGGER (check value in column from other table before allowing insert) 【发布时间】:2014-03-10 02:04:29 【问题描述】:

我制作了一个简单的 DVD 商店数据库。 DVD 表有一个“状态”列,可以是“FOR_RENT”、“FOR_SALE”、“RENTED”或“SOLD”。如果 DVD 表中的状态列未设置为“FOR_RENT”,我想编写一个触发器来阻止任何插入到我的 RENTALS 表中。

我看过的大部分文档通常都没有显示使用来自两个不同表的值的示例,所以我有点不知所措。

这是我认为迄今为止我最好的尝试:

CREATE OR REPLACE TRIGGER RENTAL_UNAVAILABLE
BEFORE INSERT ON RENTAL;
FOR EACH ROW
WHEN (DVD.STATUS != 'FOR_RENT')
DECLARE
dvd_rented EXCEPTION;
PRAGMA EXCEPTION_INIT( dvd_rented, -20001 );
BEGIN
RAISE dvd_rented;
EXCEPTION
WHEN dvd_rented THEN
RAISE_APPLICATION_ERROR(-20001,'DVD has been rented');
END;
/

我收到此错误:

 ORA-00911: invalid character

【问题讨论】:

删除ON RENTAL之后的半列 现在,我收到 ORA-04076:无效的新旧规范。至少它比上一个错误提供更多信息。 【参考方案1】:

试试这个 - 我没有编译代码,但应该很好。如果您看到任何编译问题,请告诉我并在 sqlfiddle.com 上发布架构

CREATE OR REPLACE TRIGGER rental_unavailable
   BEFORE INSERT
   ON rental
   FOR EACH ROW
DECLARE
   dvd_rented   EXCEPTION;
   PRAGMA EXCEPTION_INIT (dvd_rented, -20001);
   n_count      NUMBER (1);
BEGIN
   SELECT COUNT (*)
     INTO n_count
     FROM dvd
    WHERE dvd_id = :NEW.dvd_id AND dvd.status = 'FOR_RENT' AND ROWNUM < 2;

   IF n_count > 0
   THEN
      RAISE dvd_rented;
   END IF;
EXCEPTION
   WHEN dvd_rented
   THEN
      raise_application_error (-20001, 'DVD has been rented');
END;

【讨论】:

也许你可以向 OP 解释一下为什么这行得通?也根本不需要异常处理程序;关键是引发异常。 OP 正在尝试 WHEN (DVD.STATUS != 'FOR_RENT') 这不是正确的方式,因为触发器无法以这种方式引用其他表。为了达到这个条件,我插入了 COUNT 检查。对于 EXCEPTION 块,我知道没有必要,但也许他想处理来自 EXCEPTION 块的所有错误消息,例如“DVD 已租用”

以上是关于PLSQL: BEFORE INSERT TRIGGER(在允许插入之前检查其他表中的列中的值)的主要内容,如果未能解决你的问题,请参考以下文章

Triggers:代替/For Insert,哪个会先触发?

模型事件注意点,before_deleteafter_deletebefore_writeafter_writebefore_updateafter_updatebefore_insert

php insert_into_array_before

Oracle 使用PLSQL 导出 一个表的insert 语句

mybatis insert 返回主键 的before 和after的区别

oracle_触发器