如何在oracle中创建一个触发器,它将根据条件限制在表上插入和更新查询

时间:2012-03-11 11:46:56

标签: sql oracle sqlplus

我有帐户表 -

create table account
(
acct_id int,
cust_id int,
cust_name varchar(20)  
)

insert into account values(1,20,'Mark');
insert into account values(2,23,'Tom');
insert into account values(3,24,'Jim');

我想创建一个触发器,确保在帐户表中不能插入或更新记录,其中acct_id为2,cust_id为23。

我的代码是 -

create trigger tri_account
before insert or update
on account
for each row
begin
    IF (:new.acct_id == 2 and :new.cust_id == 23) THEN 
        DBMS_OUTPUT.PUT_LINE('No insertion with id 2 and 23.');
rollback;
    END IF; 
end;

因此创建了此触发器,但出现编译错误。 现在,当我插入任何acct_id为2且cust_id为23的记录时,它会执行allow。 但我得到一个错误说 ORA-04098:触发'OPS $ 0924769.TRI_ACCOUNT'无效且重新验证失败

我不明白这一点。我还希望显示一条消息,说明无法插入。 请帮忙......

4 个答案:

答案 0 :(得分:19)

  1. Oracle中的等于运算符是=,而不是==
  2. 您无法在触发器中提交或回滚。您可以抛出一个异常,导致触发语句失败并回滚(尽管现有的事务不一定会被回滚)。
  3. 创建此触发器时,似乎未成功编译此触发器。如果您使用的是SQL * Plus,则可以在创建PL / SQL对象后键入show errors以查看编译错误。
  4. 您永远不应该编写依赖于调用者能够看到DBMS_OUTPUT输出的代码。如果你的触发器只是试图写入DBMS_OUTPUT缓冲区,那么大多数应用程序都不会这样,DML操作就会失败。
  5. 将这些项目放在一起,您可以编写类似

    的内容
    create trigger tri_account
    before insert or update
    on account
    for each row
    begin
        IF (:new.acct_id = 2 and :new.cust_id = 23) THEN 
            raise_application_error( -20001, 'No insertion with id 2 and 23.');
        END IF; 
    end;
    

答案 1 :(得分:3)

触发器更灵活,但您也可以通过使用CHECK CONSTRAINT实现此目的:

ALTER TABLE account ADD CONSTRAINT check_account CHECK ( acct_id != 2 OR cust_id != 23 )
ENABLE NONVALIDATE;

NONVALIDATE子句将确保检查约束不会尝试验证现有数据,但它将验证所有未来数据。

希望这有帮助。

答案 2 :(得分:1)

IF (:new.acct_id = 2 and :new.cust_id = 23) THEN 

必须是OR,而不是and

答案 3 :(得分:0)

使用条件检查时,您不需要使用冒号(:)。这总会导致错误。

注意:仅在执行条件检查的情况下排除冒号。