如何在表中插入带有外键的行?

时间:2011-05-22 19:41:48

标签: sql sql-server tsql sql-server-2008

table有自己的外键。列 parentid 是外键,不能为NULL。

如果我INSERT INTO mytable(name) VALUES('name'),则表示无法向 parentid 插入NULL。但是,如果还没有插入行,我可以设置什么值?!

如何编写将向该表添加行的脚本?

谢谢

7 个答案:

答案 0 :(得分:5)

技巧:有一个带虚拟键的虚拟行,比如说99999.将其作为FK插入,然后将FK更改为其实际值。并在交易中完成。

答案 1 :(得分:5)

删除NOT NULL约束,因为它是一个不合适的约束。如果您没有ParentId,则值为NULL并且应该被允许。创建一个虚拟行只是为了产生一个虚拟的parentid会产生不必要的依赖。

答案 2 :(得分:2)

如何使idparentid等于-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       |

如果您要将其他表中的许多数据传输到此表中,可以将IDENTITY_INSERT变量设置为ON,插入数据然后再将其设置为OFF。

但正如其他人所说,最好从NOT NULL字段中删除parentid约束。

答案 3 :(得分:2)

禁用FK负责人。 然后插入 然后使用新的(生成的?)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]

答案 4 :(得分:1)

您可以将列更改为允许null,然后将fk设置为新标识,并再次启用not null。

这应该有用,但也许有更好的方法

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

答案 5 :(得分:1)

根据我的理解,您在插入之前已经拥有了id,并且您无法插入它,因为身份字段不允许您这样做。

就像你在评论中提到的那样:

  

在1个表格中我有第34行'name1'   34,35'name2'34(id,name,parentid)   我想把它们复制到其他表

第一张表

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)

第二张表:

create table Table2
(
    id int identity(1, 1) primary key,
    name varchar(20) not null,
    parentId int not null foreign key references Table2(id)
)

将数据从第一个表复制到第二个表:

set identity_insert Table2 on

insert Table2(id, name, parentId)
select *
from  Table1

set identity_insert Table2 on

<强> [更新]

如果第二个表已经有值:

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

答案 6 :(得分:0)

不要将IDENTITY列引用为自引用外键。请改用表格的替代键。我猜您使用IDENTITY作为代理键,但每个表都应该有一个自然键,因此IDENTITY列不应该是表的唯一键。