为什么我会因为触发器创建中的分号而收到 "A sql/plsql compilation error occured." 错误?

Why am I getting "A sql/plsql compilation error occured." error because of semicolons in trigger creation?

我正在尝试使用 'Oracle 11G' 中的 'Oracle SQL Developer' 创建触发器。但每次尝试时,我都会收到 'ORA-24344: success with compilation error' 消息,并且我的触发器部分创建时出现错误。

My Oracle SQL 开发人员版本为“3.0.04”,服务器版本为 'Oracle Database 11G Release 11.2.0.4.0 (64-bit)'。每次我尝试创建触发器时,我都会收到相同的消息,并且我意识到它会在第一个分号处停止执行。我尝试了 here 中写的所有看起来有同样问题的东西,但其中 none 帮助了。

例如,我正在尝试创建如下触发器:

create or replace
TRIGGER TEST_TRG 
BEFORE INSERT ON TEST_TABLE2 
REFERENCING NEW AS NEW FOR EACH ROW
DECLARE testvar number;
BEGIN 
testvar := test_sequence.nextval;
INSERT INTO TEST_TABLE(id,data) VALUES(testvar,:NEW.id);
END TEST_TRG;
/

我得到:

Error starting at line 0 in command:
CREATE OR REPLACE TRIGGER TEST_TRG 
BEFORE INSERT ON TEST_TABLE2 
REFERENCING NEW AS NEW FOR EACH ROW
DECLARE testvar number
Error report:
SQL Command: trıgger TEST_TRG
Failed: ORA-24344: success with compilation error
24344. 00000 -  "success with compilation error"
*Cause:    A sql/plsql compilation error occurred.
*Action:   Return OCI_SUCCESS_WITH_INFO along with the error code
Bind Variable "NEW" is NOT DECLARED
anonymous block completed

如您所见,它认为语句在第一次出现分号时结束。为了证明我的怀疑,我又进行了一项测试,删除了不必要的 DECLARE 语句:

CREATE OR REPLACE TRIGGER TEST_TRG 
BEFORE INSERT ON TEST_TABLE2 
REFERENCING NEW AS NEW FOR EACH ROW
BEGIN 
INSERT INTO TEST_TABLE(id,data) VALUES(test_sequence.nextval,:NEW.id);
END TEST_TRG;
/

这导致相同的错误但在不同的位置(再次在第一个分号处):

Error starting at line 0 in command:
CREATE OR REPLACE TRIGGER TEST_TRG 
BEFORE INSERT ON TEST_TABLE2 
REFERENCING NEW AS NEW FOR EACH ROW
BEGIN 
INSERT INTO TEST_TABLE(id,data) VALUES(test_sequence.nextval,:NEW.id)
Error report:
SQL Command: trıgger TEST_TRG
Failed: ORA-24344: success with compilation error
24344. 00000 -  "success with compilation error"
*Cause:    A sql/plsql compilation error occurred.
*Action:   Return OCI_SUCCESS_WITH_INFO along with the error code

Error starting at line 6 in command:
END TEST_TRG
Error report:
Unknown Command

所以问题很明显了。为什么我不能创建这些触发器,我应该如何创建它们?

查看此示例 (11.2.0.4):

表格和序列:

SQL> create table test_table2 (id number, data varchar2(20));

Table created.

SQL> create table test_table  (id number, data varchar2(20));

Table created.

SQL> create sequence test_sequence;

Sequence created.

触发器:

SQL> create or replace trigger test_trg
  2     before insert
  3     on test_table2
  4     for each row
  5  begin
  6     insert into test_table (id, data)
  7          values (test_sequence.nextval, :new.id);
  8  end test_trg;
  9  /

Trigger created.

测试:

SQL> insert into test_table2 (id, data) values (100, 'A');

1 row created.

SQL> select * from test_table;

        ID DATA
---------- --------------------
         1 100

SQL> select * from test_table2;

        ID DATA
---------- --------------------
       100 A

SQL>

顺便说一句,您发布的代码在我的数据库中运行正常的第一个触发器:

SQL> create or replace
  2  TRIGGER TEST_TRG
  3  BEFORE INSERT ON TEST_TABLE2
  4  REFERENCING NEW AS NEW FOR EACH ROW
  5  DECLARE testvar number;
  6  BEGIN
  7  testvar := test_sequence.nextval;
  8  INSERT INTO TEST_TABLE(id,data) VALUES(testvar,:NEW.id);
  9  END TEST_TRG;
 10  /

Trigger created.

SQL>

第二个:

SQL> CREATE OR REPLACE TRIGGER TEST_TRG
  2  BEFORE INSERT ON TEST_TABLE2
  3  REFERENCING NEW AS NEW FOR EACH ROW
  4  BEGIN
  5  INSERT INTO TEST_TABLE(id,data) VALUES(test_sequence.nextval,:NEW.id);
  6  END TEST_TRG;
  7  /

Trigger created.

SQL>

所以,这可能与您的 SQL 开发人员版本太旧有关。我建议你升级到最新版本(可在 Oracle 技术网上免费下载)。

感谢,虽然这不是我问题的根本原因,但他帮助我看到了问题。我尝试了我们的两个查询,发现如果我使用小写字母而不是大写字母,触发器会起作用。

然后我意识到错误消息有这样一行:

SQL Command: trıgger TEST_TRG

所以我已经看到,如果我使用大写字母,我的 'Oracle SQL Developer' 版本会将其转换为小写字母。但是正如您所看到的,它没有使用 ASCII 字符集,而是使用我的本地字符集(土耳其字符集)并将 'I' 转换为 'ı' 并将 'İ' 转换为 'i'。因此,在我的 OS Oracle 客户端中,无法将 'TRIGGER' 识别为有效关键字。我应该使用 'trigger' 或 'TRİGGER'.

另一个解决方案是将 Windows OS 的 "Regional format" 设置从 "Turkish (Turkey)" 更改为 "English (United states)"。我检查了所有其他 regional/localization 设置,但只有更改 "Regional format" 设置有效。所以我想 Oracle Developer 检查该设置来决定客户端字符集。

也可能与"Oracle SQL developer"的版本有关。但是我工作电脑的管理策略不允许我更新它,所以我没能尝试。