为什么我会因为触发器创建中的分号而收到 "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"的版本有关。但是我工作电脑的管理策略不允许我更新它,所以我没能尝试。
我正在尝试使用 '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"的版本有关。但是我工作电脑的管理策略不允许我更新它,所以我没能尝试。