PLSQL - 创建触发器抛出错误

时间:2018-05-23 16:44:05

标签: plsql triggers

我有一个表,我需要生成一个触发器。以下是我的代码:

CREATE OR REPLACE EDITIONABLE TRIGGER "MYUSER"."REGISTRATION_TRG" BEFORE
  INSERT ON REGISTRATIONS FOR EACH ROW BEGIN <<COLUMN_SEQUENCES>> BEGIN IF INSERTING
  AND :NEW.REGISTRATIONID                              IS NULL THEN
  SELECT REGISTRATIONS_SEQ.NEXTVAL
  INTO :NEW.REGISTRATIONID
  FROM SYS.DUAL;
END IF;
END COLUMN_SEQUENCES;
END;

当我运行此操作时,我收到以下错误:

Error starting at line 0 in command:
CREATE OR REPLACE EDITIONABLE TRIGGER "MYUSER"."REGISTRATIONS_TRG" BEFORE
  INSERT ON REGISTRATIONS FOR EACH ROW BEGIN <<COLUMN_SEQUENCES>> BEGIN IF INSERTING
  AND :NEW.REGISTRATIONID                              IS NULL THEN
  SELECT REGISTRATIONS_SEQ.NEXTVAL
  INTO :NEW.REGISTRATIONID
  FROM SYS.DUAL
Error report:
SQL Command: CREATE OR REPLACE EDITIONABLE
Failed: Warning: execution completed with warning

Error starting at line 7 in command:
END IF
Error report:
Unknown Command

Error starting at line 8 in command:
END COLUMN_SEQUENCES
Error report:
Unknown Command

Error starting at line 9 in command:
END
Error report:
Unknown Command

我做错了什么?

谢谢!

1 个答案:

答案 0 :(得分:0)

首先,它适用于SQL * Plus和PL / SQL Developer:

create table registrations(registrationid integer);

create sequence registrations_seq;

CREATE OR REPLACE EDITIONABLE TRIGGER "REGISTRATION_TRG" BEFORE
  INSERT ON REGISTRATIONS FOR EACH ROW BEGIN <<COLUMN_SEQUENCES>> BEGIN IF INSERTING
  AND :NEW.REGISTRATIONID                              IS NULL THEN
  SELECT REGISTRATIONS_SEQ.NEXTVAL
  INTO :NEW.REGISTRATIONID
  FROM SYS.DUAL;
END IF;
END COLUMN_SEQUENCES;
END;
/

(我删除了"MYUSER",因为我没有具有该名称的用户帐户。)

但是,你可以简化这一点。首先,值得用任何语言整齐地编写代码,所以第一步是:

create or replace editionable trigger registration_trg
    before insert on registrations
    for each row
begin
    <<column_sequences>>
    begin
        if inserting and :new.registrationid is null then
            select registrations_seq.nextval into :new.registrationid
            from sys.dual;
        end if;
    end column_sequences;
end;

然后,

  1. 如果它是唯一的块,则不需要命名块。
  2. 这是一个插入触发器,因此您无需测试if inserting
  3. 允许同一列中生成的和用户输入的值都是灾难的处方,但如果必须,则可以在触发器规范中将其定义为when条件。
  4. PL / SQL语言有一个赋值运算符:=,因此您不需要查询来为变量赋值。
  5. 为什么不简单地说:

    create or replace trigger registration_trg
        before insert on registrations
        for each row
        when (new.registrationid is null)
    begin
        :new.registrationid := registrations_seq.nextval;
    end;
    

    更简单地说,从Oracle 12.1开始,您甚至不需要触发器:

    drop table registrations;
    
    create table registrations (id integer generated always as identity);
    
    insert into registrations values (default);
    
    select * from registrations;
    
            ID
    ----------
             1