PL/SQL 编译错误,不知道哪里出了问题
PL/SQL compilation error, can't figure out whats broken
所以我的 SQL 程序如下:
create or replace procedure generate_sample_dd_contracts(cnt in pls_integer)
is
begin
for cur in (select * from (select * from tc_client cli where not exists (select 1 from tc_direct_debit dd where dd.cli_id=cli.id) order by dbms_random.value) where rownum < dbms_random.value(2,100))
-- select query works fine and gets clients as needed
loop
for i in 0..cnt
loop
insert into tc_direct_debit (cli_id, ref_number) values (cur.id, tc_ref_num_seq.nextval);
-- this insert also works separately from procedure, I have autoinc trigger
end loop;
end loop;
commit;
end;
/
begin
generate_sample_dd_contracts(3);
end;
先for循环select查询结果
此外,当我 运行 程序 tc_direct_debit ID 得到更新(进入子句)但 table 中没有数据出现。
以及错误报告:
PROCEDURE GENERATE_SAMPLE_DD_CONTRACTS compiled
Error starting at line 19 in command:
begin
generate_sample_dd_contracts(3);
end;
Error report:
ORA-00001: unique constraint (T.U_DIRECT_DEBIT_CLI_ID) violated
ORA-06512: at "T.GENERATE_SAMPLE_DD_CONTRACTS", line 9
ORA-06512: at line 2
00001. 00000 - "unique constraint (%s.%s) violated"
*Cause: An UPDATE or INSERT statement attempted to insert a duplicate key.
For Trusted Oracle configured in DBMS MAC mode, you may see
this message if a duplicate entry exists at a different level.
*Action: Either remove the unique restriction or do not insert the key.
据我所知,insert 会尝试添加一个已经存在但 tc_direct_debit 为空的 cli_id(已多次 运行 确定)。
tc_direct_debit table
`CREATE TABLE TC_DIRECT_DEBIT
(ID NUMBER NOT NULL
, CLI_ID NUMBER NOT NULL
, REF_NUMBER VARCHAR2(20) NOT NULL
, CONSTRAINT TC_DIRECT_DEBIT_PK PRIMARY KEY (ID)
, CONSTRAINT U_DIRECT_DEBIT_CLI_ID UNIQUE (CLI_ID)
, CONSTRAINT TC_DIRECT_DEBIT_CLI_FK FOREIGN KEY (CLI_ID) REFERENCES TC_CLIENT (ID)
);`
似乎 CLI_ID
被提到为 unique key
这意味着将不接受任何费用的重复。程序中的 wherears line 9
已循环插入
for i in 0..cnt
loop
insert into tc_direct_debit (cli_id, ref_number) values (cur.id, tc_ref_num_seq.nextval);
-- this insert also works separately from procedure, I have autoinc trigger
end loop;
删除唯一约束 U_DIRECT_DEBIT_CLI_ID
将解决您的问题
对于光标中的每一行,您将其插入四次(从 0 到 3)。
执行我认为您想要执行的操作的代码是:
create or replace procedure generate_sample_dd_contracts(cnt in pls_integer)
is
declare
i number;
begin
i:=0;
for cur in (select * from (select * from tc_client cli where not exists (select 1 from tc_direct_debit dd where dd.cli_id=cli.id) order by dbms_random.value) where rownum < dbms_random.value(2,100))
loop
i:=i+1;
exit when i > cnt;
insert into tc_direct_debit (cli_id, ref_number) values (cur.id, tc_ref_num_seq.nextval);
end loop;
commit;
end;
/
或者更好,只需更改光标代码:
create or replace procedure generate_sample_dd_contracts(cnt in pls_integer)
is
begin
for cur in (select * from (select * from tc_client cli where not exists (select 1 from tc_direct_debit dd where dd.cli_id=cli.id) order by dbms_random.value) where rownum <= cnt)
loop
insert into tc_direct_debit (cli_id, ref_number) values (cur.id, tc_ref_num_seq.nextval);
end loop;
commit;
end;
/
所以我的 SQL 程序如下:
create or replace procedure generate_sample_dd_contracts(cnt in pls_integer)
is
begin
for cur in (select * from (select * from tc_client cli where not exists (select 1 from tc_direct_debit dd where dd.cli_id=cli.id) order by dbms_random.value) where rownum < dbms_random.value(2,100))
-- select query works fine and gets clients as needed
loop
for i in 0..cnt
loop
insert into tc_direct_debit (cli_id, ref_number) values (cur.id, tc_ref_num_seq.nextval);
-- this insert also works separately from procedure, I have autoinc trigger
end loop;
end loop;
commit;
end;
/
begin
generate_sample_dd_contracts(3);
end;
先for循环select查询结果
此外,当我 运行 程序 tc_direct_debit ID 得到更新(进入子句)但 table 中没有数据出现。
以及错误报告:
PROCEDURE GENERATE_SAMPLE_DD_CONTRACTS compiled
Error starting at line 19 in command:
begin
generate_sample_dd_contracts(3);
end;
Error report:
ORA-00001: unique constraint (T.U_DIRECT_DEBIT_CLI_ID) violated
ORA-06512: at "T.GENERATE_SAMPLE_DD_CONTRACTS", line 9
ORA-06512: at line 2
00001. 00000 - "unique constraint (%s.%s) violated"
*Cause: An UPDATE or INSERT statement attempted to insert a duplicate key.
For Trusted Oracle configured in DBMS MAC mode, you may see
this message if a duplicate entry exists at a different level.
*Action: Either remove the unique restriction or do not insert the key.
据我所知,insert 会尝试添加一个已经存在但 tc_direct_debit 为空的 cli_id(已多次 运行 确定)。
tc_direct_debit table
`CREATE TABLE TC_DIRECT_DEBIT
(ID NUMBER NOT NULL
, CLI_ID NUMBER NOT NULL
, REF_NUMBER VARCHAR2(20) NOT NULL
, CONSTRAINT TC_DIRECT_DEBIT_PK PRIMARY KEY (ID)
, CONSTRAINT U_DIRECT_DEBIT_CLI_ID UNIQUE (CLI_ID)
, CONSTRAINT TC_DIRECT_DEBIT_CLI_FK FOREIGN KEY (CLI_ID) REFERENCES TC_CLIENT (ID)
);`
似乎 CLI_ID
被提到为 unique key
这意味着将不接受任何费用的重复。程序中的 wherears line 9
已循环插入
for i in 0..cnt
loop
insert into tc_direct_debit (cli_id, ref_number) values (cur.id, tc_ref_num_seq.nextval);
-- this insert also works separately from procedure, I have autoinc trigger
end loop;
删除唯一约束 U_DIRECT_DEBIT_CLI_ID
将解决您的问题
对于光标中的每一行,您将其插入四次(从 0 到 3)。
执行我认为您想要执行的操作的代码是:
create or replace procedure generate_sample_dd_contracts(cnt in pls_integer)
is
declare
i number;
begin
i:=0;
for cur in (select * from (select * from tc_client cli where not exists (select 1 from tc_direct_debit dd where dd.cli_id=cli.id) order by dbms_random.value) where rownum < dbms_random.value(2,100))
loop
i:=i+1;
exit when i > cnt;
insert into tc_direct_debit (cli_id, ref_number) values (cur.id, tc_ref_num_seq.nextval);
end loop;
commit;
end;
/
或者更好,只需更改光标代码:
create or replace procedure generate_sample_dd_contracts(cnt in pls_integer)
is
begin
for cur in (select * from (select * from tc_client cli where not exists (select 1 from tc_direct_debit dd where dd.cli_id=cli.id) order by dbms_random.value) where rownum <= cnt)
loop
insert into tc_direct_debit (cli_id, ref_number) values (cur.id, tc_ref_num_seq.nextval);
end loop;
commit;
end;
/