[英]How to insert row in table with foreign key to itself?
I have table that has foreign key for itself. 我有自己的外键表 。 Column parentid is foreign key and it cannot be NULL. 列parentid是外键, 不能为NULL。
if I do INSERT INTO mytable(name) VALUES('name')
, so it says that can't insert NULL to parentid . 如果我执行INSERT INTO mytable(name) VALUES('name')
,那么它表示无法向parentid插入NULL。 BUT, what value I can set to it if no row was inserted yet?! 但是,如果没有插入行,我可以设置什么值?!
How I can write script that will add row to this table? 我如何编写将向该表添加行的脚本?
Thank you 谢谢
A trick: Have a dummy row with a dummy key, say 99999. Insert with this as the FK, and then change the FK to its real value. 一个技巧:有一个带虚拟键的虚拟行,比如99999.用此作为FK插入,然后将FK更改为其实际值。 And do it in a transaction. 并在交易中完成。
Remove the NOT NULL constraint, as it is an inappropriate constraint. 删除NOT NULL约束,因为它是一个不合适的约束。 If you do not have a ParentId then the value is NULL and should be allowed. 如果您没有ParentId,则值为NULL并且应该被允许。 Creating a dummy row just to have a dummy parentid creates unnecessary dependencies. 创建虚拟行只是为了产生虚拟parentid会产生不必要的依赖关系。
Disable the FK in charge. 禁用FK负责。 Then do the insert Then do an update with the new (generated?) PK-ID into the Self-FK-Field Then Enable the FK back. 然后执行插入然后使用新的(生成的?)PK-ID更新到Self-FK-Field然后启用FK。
LIke so: 喜欢这样:
ALTER TABLE [Client] NOCHECK CONSTRAINT [FK_Client_MainClient]
INSERT INTO Client VALUES ...
@ClientID = SCOPE_IDENTITY()
IF @IsMainClient=1
BEGIN
UPDATE [Client]
SET MainClientID = @ClientID
WHERE ClientID = @ClientID
END
ALTER TABLE [Relatie] WITH CHECK CHECK CONSTRAINT [FK_Relatie_Relatie]
How to make a dummy row with both id
and parentid
equal to -1
: 如何使id
和parentid
等于-1
的虚拟行:
CREATE TABLE mytable(
id int NOT NULL IDENTITY,
parentid int NOT NULL,
PRIMARY KEY (id),
FOREIGN KEY (parentid) REFERENCES mytable(id)
) ;
SET IDENTITY_INSERT mytable ON ; <-- this allows you to insert the
INSERT INTO mytable(id, parentid) <-- auto incremented identity field
VALUES (-1, -1);
SET IDENTITY_INSERT mytable OFF ;
SELECT * FROM mytable ;
| id | parentid |
| -1 | -1 |
If you have many data from other tables that you want to transfer into this table, you can set the IDENTITY_INSERT variable to ON, insert the data and then set it to OFF again. 如果要将其他表中的许多数据传输到此表中,可以将IDENTITY_INSERT变量设置为ON,插入数据,然后再将其设置为OFF。
But as others said, it might be better to just remove the NOT NULL
constraint from the parentid
field. 但正如其他人所说,从parentid
字段中删除NOT NULL
约束可能更好。
You can alter the column to allow null then set the fk to the new identity and enable not null again. 您可以将列更改为允许null,然后将fk设置为新标识并再次启用not null。
This should work, though maybe there is a better way 这应该有用,但也许有更好的方法
CREATE TABLE mytable
(
id int IDENTITY(1,1) primary key,
name varchar(50) not null,
parentid int not null
)
go
alter table mytable
add constraint FK_mytable_parentid FOREIGN KEY ( parentid ) references mytable(id)
ALTER TABLE mytable alter column parentid int null;
insert into mytable(name)
select 'test'
update mytable
set parentid = SCOPE_IDENTITY()
where id = SCOPE_IDENTITY()
ALTER TABLE mytable alter column parentid int not null;
select * from mytable
drop table mytable
From what I understood you already have id before inserting and you can't insert it because identity field isn't letting you to. 根据我的理解,你在插入前已经有了id,你不能插入它,因为身份字段不允许你。
Like you mentioned in your comment: 就像你在评论中提到的:
in 1 table I have the rows 34 'name1' 34, 35 'name2' 34 (id,name,parentid) and I want to copy them to other table 在1表中,我有行34'name1'34,35'name2'34(id,name,parentid),我想将它们复制到其他表
First table 第一张桌子
create table Table1
(
id int not null primary key,
name varchar(20) not null,
parentId int not null
)
insert Table1
values
(34, 'name1', 34),
(35, 'name2', 34)
Second table: 第二表:
create table Table2
(
id int identity(1, 1) primary key,
name varchar(20) not null,
parentId int not null foreign key references Table2(id)
)
Copying data from the first table to the second one: 将数据从第一个表复制到第二个表:
set identity_insert Table2 on
insert Table2(id, name, parentId)
select *
from Table1
set identity_insert Table2 on
[Update] [更新]
If the second table already has values then: 如果第二个表已经有值,那么:
alter table Table2
add oldId int null
alter table Table2
alter column parentId int null
go
insert Table2(name, oldId)
select name, id
from Table1
update tt3
set parentId = tt2.id
from Table2 tt3
join Table1 tt1 on
tt1.id = tt3.oldId
join Table2 tt2 on
tt1.parentId = tt2.oldId
alter table Table2
drop column oldId
alter table Table2
alter column parentId int not null
Don't reference an IDENTITY column as a self-referencing foreign key. 不要将IDENTITY列引用为自引用外键。 Use an alternative key of the table instead. 请改用表格的替代键。 I guess you are using IDENTITY as a surrogate key but every table ought to have a natural key as well, so the IDENTITY column shouldn't be the only key of your table. 我猜你使用IDENTITY作为代理键,但每个表都应该有一个自然键,所以IDENTITY列不应该是你表的唯一键。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.