使用外键将值插入表中
Insert values into tables with a foreign key
我想在一个循环中的两个表中插入一些值,但由于外键的原因,我似乎不能这样做。但是,相同的代码在 SQL 服务器中确实有效。
这在 SQL 服务器中完美运行:
declare @i int = 1
while @i<1200
BEGIN
INSERT INTO DOKUMENTY VALUES(null,null);
INSERT INTO POZYCJE VALUES
( null,@i,RAND()*(10000) ) ,
( null,@i,RAND()*(10000) ),
( null,@i,RAND()*(10000) ),
( null,@i,RAND()*(10000) )
SET @i+=1
END
我正尝试在 Firebird 中做同样的事情:
SET TERM #;
execute block
as
declare variable cnt2 integer = 0;
begin
while (cnt2 < 1200) do
begin
insert into DOKUMENTY(DATA_KSIEGOWANIA) values(current_date);
insert INTO POZYCJE(ID_DOKUMENTU, KWOTA)
select (:cnt2), MOD(RAND(),1000) FROM RDB$DATABASE UNION ALL
select (:cnt2), MOD(RAND(),1000) FROM RDB$DATABASE UNION ALL
select (:cnt2), MOD(RAND(),1000) FROM RDB$DATABASE UNION ALL
select (:cnt2), MOD(RAND(),1000) FROM RDB$DATABASE ;
cnt2 = cnt2 + 1;
end
end#
SET TERM;#
但是,我收到此错误:
Error: *** IBPP::SQLException ***
Message: isc_dsql_execute2 failed
SQL Message : -530
can't format message 13:470 -- message file C:\WINDOWS\SYSTEM32\firebird.msg not found
Engine Code : 335544466
Engine Message :
violation of FOREIGN KEY constraint "INTEG_44" on table "POZYCJE"
Foreign key reference target does not exist
Problematic key value is ("ID_DOKUMENTU" = 0)
At block line: 10, col: 9
这是我创建表格的方式:
CREATE TABLE DOKUMENTY(
ID_DOKUMENTU integer generated by default as identity primary key,
DATA_KSIEGOWANIA DATE
);
CREATE TABLE POZYCJE(
ID_POZYCJI integer generated by default as identity primary key,
ID_DOKUMENTU integer,
FOREIGN KEY(ID_DOKUMENTU) references DOKUMENTY(ID_DOKUMENTU),
KWOTA decimal(18,2)
);
我该如何解决这个问题?
您的 Firebird 代码不等同于您的 SQL 服务器代码。您的 SQL 服务器代码从 1
开始,而您的 Firebird 代码从 0
开始。为标识列生成的第一个值是 1
,而不是 0
,因此您的插入未通过外键约束,因为 DOKUMENTY
中没有包含 ID_DOKUMENTU = 0
的记录。因此,直接的解决方案是使用 declare variable cnt2 integer = 1;
而不是 declare variable cnt2 integer = 0;
但是,您的代码当前依赖于标识列,该标识列实际上从特定值 (1
) 开始,并且始终递增 1。这不是一个安全的解决方案,例如,如果您尝试运行 现在进行此更改后,它将失败,因为当您的执行块失败时,带有 ID_DOKUMENTU = 1
的记录的插入被撤消,并且插入的下一条记录将具有更高的 ID。
改为修改您的代码以使用实际生成的 ID:
execute block
as
declare variable cnt2 integer = 1;
declare variable ID_DOKUMENTU type of column DOKUMENTY.ID_DOKUMENTU;
begin
while (cnt2 < 1200) do
begin
insert into DOKUMENTY(DATA_KSIEGOWANIA) values(current_date)
returning ID_DOKUMENTU into ID_DOKUMENTU;
insert INTO POZYCJE(ID_DOKUMENTU, KWOTA)
select (:ID_DOKUMENTU), MOD(RAND(),1000) FROM RDB$DATABASE UNION ALL
select (:ID_DOKUMENTU), MOD(RAND(),1000) FROM RDB$DATABASE UNION ALL
select (:ID_DOKUMENTU), MOD(RAND(),1000) FROM RDB$DATABASE UNION ALL
select (:ID_DOKUMENTU), MOD(RAND(),1000) FROM RDB$DATABASE ;
cnt2 = cnt2 + 1;
end
end
顺便说一句,MOD(RAND(),1000)
与 SQL 服务器代码中的 RAND()*(10000)
不一样。
我想在一个循环中的两个表中插入一些值,但由于外键的原因,我似乎不能这样做。但是,相同的代码在 SQL 服务器中确实有效。
这在 SQL 服务器中完美运行:
declare @i int = 1
while @i<1200
BEGIN
INSERT INTO DOKUMENTY VALUES(null,null);
INSERT INTO POZYCJE VALUES
( null,@i,RAND()*(10000) ) ,
( null,@i,RAND()*(10000) ),
( null,@i,RAND()*(10000) ),
( null,@i,RAND()*(10000) )
SET @i+=1
END
我正尝试在 Firebird 中做同样的事情:
SET TERM #;
execute block
as
declare variable cnt2 integer = 0;
begin
while (cnt2 < 1200) do
begin
insert into DOKUMENTY(DATA_KSIEGOWANIA) values(current_date);
insert INTO POZYCJE(ID_DOKUMENTU, KWOTA)
select (:cnt2), MOD(RAND(),1000) FROM RDB$DATABASE UNION ALL
select (:cnt2), MOD(RAND(),1000) FROM RDB$DATABASE UNION ALL
select (:cnt2), MOD(RAND(),1000) FROM RDB$DATABASE UNION ALL
select (:cnt2), MOD(RAND(),1000) FROM RDB$DATABASE ;
cnt2 = cnt2 + 1;
end
end#
SET TERM;#
但是,我收到此错误:
Error: *** IBPP::SQLException ***
Message: isc_dsql_execute2 failed
SQL Message : -530
can't format message 13:470 -- message file C:\WINDOWS\SYSTEM32\firebird.msg not found
Engine Code : 335544466
Engine Message :
violation of FOREIGN KEY constraint "INTEG_44" on table "POZYCJE"
Foreign key reference target does not exist
Problematic key value is ("ID_DOKUMENTU" = 0)
At block line: 10, col: 9
这是我创建表格的方式:
CREATE TABLE DOKUMENTY(
ID_DOKUMENTU integer generated by default as identity primary key,
DATA_KSIEGOWANIA DATE
);
CREATE TABLE POZYCJE(
ID_POZYCJI integer generated by default as identity primary key,
ID_DOKUMENTU integer,
FOREIGN KEY(ID_DOKUMENTU) references DOKUMENTY(ID_DOKUMENTU),
KWOTA decimal(18,2)
);
我该如何解决这个问题?
您的 Firebird 代码不等同于您的 SQL 服务器代码。您的 SQL 服务器代码从 1
开始,而您的 Firebird 代码从 0
开始。为标识列生成的第一个值是 1
,而不是 0
,因此您的插入未通过外键约束,因为 DOKUMENTY
中没有包含 ID_DOKUMENTU = 0
的记录。因此,直接的解决方案是使用 declare variable cnt2 integer = 1;
而不是 declare variable cnt2 integer = 0;
但是,您的代码当前依赖于标识列,该标识列实际上从特定值 (1
) 开始,并且始终递增 1。这不是一个安全的解决方案,例如,如果您尝试运行 现在进行此更改后,它将失败,因为当您的执行块失败时,带有 ID_DOKUMENTU = 1
的记录的插入被撤消,并且插入的下一条记录将具有更高的 ID。
改为修改您的代码以使用实际生成的 ID:
execute block
as
declare variable cnt2 integer = 1;
declare variable ID_DOKUMENTU type of column DOKUMENTY.ID_DOKUMENTU;
begin
while (cnt2 < 1200) do
begin
insert into DOKUMENTY(DATA_KSIEGOWANIA) values(current_date)
returning ID_DOKUMENTU into ID_DOKUMENTU;
insert INTO POZYCJE(ID_DOKUMENTU, KWOTA)
select (:ID_DOKUMENTU), MOD(RAND(),1000) FROM RDB$DATABASE UNION ALL
select (:ID_DOKUMENTU), MOD(RAND(),1000) FROM RDB$DATABASE UNION ALL
select (:ID_DOKUMENTU), MOD(RAND(),1000) FROM RDB$DATABASE UNION ALL
select (:ID_DOKUMENTU), MOD(RAND(),1000) FROM RDB$DATABASE ;
cnt2 = cnt2 + 1;
end
end
顺便说一句,MOD(RAND(),1000)
与 SQL 服务器代码中的 RAND()*(10000)
不一样。