如何将值插入到具有复合主键的表中



这些是我已经拥有的表格:

CREATE TABLE Gyartok 
(
GyID INT IDENTITY(2, 3),
Nev VARCHAR(20),
CONSTRAINT PK_Gyartok PRIMARY KEY (GyID)
)
CREATE TABLE Focicsuka 
(
CsID INT IDENTITY(2, 2),
Meret INT, 
CONSTRAINT PK_Focicsuka PRIMARY KEY (CsID)
)
CREATE TABLE FcsGyartjaGya 
(
GyID INT IDENTITY(3, 2), 
CsID INT,
Ar INT,
CONSTRAINT FK_FcsGyartjaGya1 
FOREIGN KEY (GyID) REFERENCES Gyartok(GyID),
CONSTRAINT FK_FcsGyartjaGya2 
FOREIGN KEY (CsID) REFERENCES Focicsuka(CsID),
CONSTRAINT PK_FcsGyartjaGya 
PRIMARY KEY (GyID, CsID)
)

问题是每次我尝试向表添加新值时(就像这样)

INSERT INTO FcsGyartjaGya (Ar) VALUES (300);

我收到一条错误消息,指出我没有初始化 CsID INT 列:

无法将值 NULL 插入到列 'CsID' 中,表 'Lab3.dbo.FcsGyartjaGya';列不允许空值。插入失败。

我知道我必须用一些东西初始化它,但我不知道如何处理它,因为IDENTITY(x, y)不起作用(它已经被另一列占用)并向代码添加另一个参数(像这样)

INSERT INTO FcsGyartjaGya (Ar, CsID) VALUES (300, 7);

创建另一个错误,其中显示

INSERT 语句与外键约束"FK_FcsGyartjaGya1"冲突。冲突发生在数据库"Lab3a",表"dbo"中。嘉尔托克","GyID"一栏。

重要的是要注意,我已经用数据填充了每一列,所以这不是问题。

正如我在评论中提到的,只要星星正确对齐,您的INSERT就可以正常工作。对于您的表Gyartok,您将GyID作为您的PRIMARY KEY,定义为IDENTITY(2,3);因此,生成的第一个值是2,然后尝试INSERT的每一行 ed 将递增3.

因此,如果我们运行以下命令,我们将获得 ID 2、5、7 和 17。(11 和 14 因INSERT失败而跳过)。

CREATE TABLE Gyartok (
GyID INT IDENTITY(2, 3),
Nev VARCHAR(20),
CONSTRAINT PK_Gyartok PRIMARY KEY (GyID)
);
GO
INSERT INTO dbo.Gyartok (Nev)
VALUES ('asdfjahsbvd'),
('ashjkgdfakd'),
('kldfbhjo');
GO
INSERT INTO dbo.Gyartok (Nev)
VALUES (REPLICATE('A',25)), --Force a truncation error
('ashjkgdfakd');
GO
INSERT INTO dbo.Gyartok (Nev)
VALUES (REPLICATE('A',15));

现在让我们为您的其他表添加一些数据:

CREATE TABLE Focicsuka (
CsID INT IDENTITY(2, 2),
Meret INT, 
CONSTRAINT PK_Focicsuka PRIMARY KEY (CsID)
)
INSERT INTO dbo.Focicsuka (Meret)
VALUES(12),
(25);

现在我们要INSERTFcsGyartjaGya,定义为如下:

CREATE TABLE FcsGyartjaGya (
GyID INT IDENTITY(3, 2), 
CsID INT,
Ar INT,
CONSTRAINT FK_FcsGyartjaGya1 FOREIGN KEY (GyID) REFERENCES Gyartok(GyID),
CONSTRAINT FK_FcsGyartjaGya2 FOREIGN KEY (CsID) REFERENCES Focicsuka(CsID),
CONSTRAINT PK_FcsGyartjaGya PRIMARY KEY (GyID, CsID)
)

这在GyID上有一个IDENTITY,但定义为IDENTITY(3,2),所以第一个值是3然后递增2

由于它有 2 个外键,因此当我们INSERT行时,GyIDCsID时,值必须出现在相应的表中。然而,由于GyID被定义为IDENTITY(3,2),这就是我们需要依靠星星运气来INSERT工作的地方。为什么?好吧,2 + (3*n)3+(2*n)可以给出非常不同的数字。第一个是你在这个答案的开头看到的。对于后者,我们有像357911这样的数字。如您所见,这些数字中只有三分之一与我们原始序列中的数字匹配,因此运气是我们将要依赖的。

因此,让我们尝试一个INSERT

INSERT INTO dbo.FcsGyartjaGya (CsID,Ar)
VALUES(2,1);

INSERT 语句与外键约束"FK_FcsGyartjaGya1"冲突。冲突发生在数据库"沙盒"中,表"dbo。嘉尔托克","GyID"一栏。

好吧,这不起作用,但这是意料之中的。3不是表中的值Gyartok。让我们再试一次!

INSERT INTO dbo.FcsGyartjaGya (CsID,Ar)
VALUES(2,2);

成功了!星运气是我们这边,IDENTITY值是表Gyartok中的值。这次让我们尝试几行!

INSERT INTO dbo.FcsGyartjaGya (CsID,Ar)
VALUES(4,3),
(4,4);

INSERT 语句与外键约束"FK_FcsGyartjaGya1"冲突。冲突发生在数据库"沙盒"中,表"dbo。嘉尔托克","GyID"一栏。

不!!又来了。:(那是因为星星没有对齐;79不在另一个表中。但是等等,11在序列中,所以让我们尝试一下:

INSERT INTO dbo.FcsGyartjaGya (CsID,Ar)
VALUES(4,5);

又是错误?!不,不可能!!:(哦,等等,我忘了,星星以前反对过我们,因为那个INSERT为了11的价值而对Gyartok失败了.我需要等17

--13 fails
INSERT INTO dbo.FcsGyartjaGya (CsID,Ar)
VALUES(4,6);
GO
--15 fails
INSERT INTO dbo.FcsGyartjaGya (CsID,Ar)
VALUES(4,6);
GO
--17 works!
INSERT INTO dbo.FcsGyartjaGya (CsID,Ar)
VALUES(4,6);

现在我们的表中还有另一行。


那么问题出在哪里?您的设计。GyID被定义为IDENTITYFOREIGN KEY;这意味着您处于SQL Server生成有效值的"突发奇想"。这不是你想要的。只是不要将列定义为IDENTITY然后INSERT定义了所有 3 列的数据:

CREATE TABLE FcsGyartjaGya (
GyID int,-- IDENTITY(3, 2), 
CsID INT,
Ar INT,
CONSTRAINT FK_FcsGyartjaGya1 FOREIGN KEY (GyID) REFERENCES Gyartok(GyID),
CONSTRAINT FK_FcsGyartjaGya2 FOREIGN KEY (CsID) REFERENCES Focicsuka(CsID),
CONSTRAINT PK_FcsGyartjaGya PRIMARY KEY (GyID, CsID)
)
GO
INSERT INTO dbo.FcsGyartjaGya (GyID, CsID, Ar)
VALUES(2,2,1),
(2,4,2),
(5,4,3),
(8,2,4),
(8,4,5);

所有这些行都插入得很好。

我认为有点混乱,如果我正确理解您要做什么,那么您有两个表,每个表都有自己的id,该ID基于标识列,因此您可以免费获得新值。 然后,您正在尝试使用额外数据制作关系表。

问题 1:如果 FcsGyartjaGya.GyID 引用 Gyartok.GyID,则不能将其作为标识,因为您需要插入其中而不依赖于自动增量。如果它不是指相同的,它应该有另一个名字,否则我的头可能会爆炸:))

问题 2:填充关系表时,您需要插入所需的对,SQL Server 无法知道它应该如何匹配关系表中的这些标识对

我认为这就是人们在评论中的目标,例如 将行与 Focicsuka.CsID = 1 插入到 Gyartok.GyID 7 之间的关系,并添加 Ar = 300 必须看起来像

INSERT INTO FCSGYARTJAGYA(GYID, CSID, AR)
VALUES(7, 1, 300)

除非您忘记提及要为每个值或基于可以编写脚本的内容放置一些值,否则除非您有逻辑来定义对及其值,否则关系表不能在其外键字段上具有默认值。

最新更新