SQL逻辑密钥

时间:2017-12-18 19:33:13

标签: sql sql-server tsql constraints

我有三张桌子,比如tableA,tableB,tableC。 这些表的关系是:

  • tableA到tableB分别为一对多
  • tableB到tableC分别为一对多

tableA:

CREATE TABLE tableA (
id int Not Null,
name varchar(50) Not Null,
Area varchar(20) Not Null,
CONSTRAINT PK_tableA PRIMARY KEY NONCLUSTERED(id Asc) WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON, FILLFACTOR = 90)
)

tableB的:

CREATE TABLE tableB (
id int Not Null,
appNbr int NOT NULL,
appCode char(8) NOT NULL,
tableAId int Not Null,
beginDt datetime Not Null,
EndDt datetime Not Null,
updatedDt datetime Not Null,
CONSTRAINT PK_tableB PRIMARY KEY NONCLUSTERED(
id Asc,
appNbr ASC,
appCode ASC,
tableAid ASC,
beginDt ASC,
endDt ASC
) WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON, FILLFACTOR = 90)
) 
GO

ALTER TABLE tableB  WITH CHECK ADD  CONSTRAINT FK_tableB_tableAId FOREIGN KEY(tableAId)
REFERENCES tableA (Id)
GO

ALTER TABLE tableB CHECK CONSTRAINT FK_tableB_tableAId
GO

表C:

CREATE TABLE tableC (
id int Not Null,
tableBId int Not Null,
beginDt datetime Not Null,
endDt datetime Not Null,
indicator char(1) Not Null,
contactId int Not Null
UpdateDt datetime Not Null,
CONSTRAINT PK_tableC PRIMARY KEY NONCLUSTERED(
id ASC,
tableBId Asc,
beginDt ASC,
endDt ASC
) WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON, FILLFACTOR = 90)
)

ALTER TABLE tableC  WITH CHECK ADD  CONSTRAINT FK_tableC_tableBId FOREIGN KEY(tableBId)
REFERENCES tableB (Id)
GO

ALTER TABLE tableC CHECK CONSTRAINT FK_tableC_tableBId
GO

这里的问题是当我运行脚本来创建表C时,它显示错误如下

There are no primary or candidate keys in the referenced table
   'dbo.tableB' that match the referencing column list in the
   foreign key 'FK_tableC_tableBId'.  
Msg 1750, Level 16, State 0, Line 2
Could not create constraint. See previous errors.

在谷歌研究后,我发现不允许从复合主键创建一个外键。所以,我决定将id作为我的主键和剩余字段(appNbr,appCode,tableAid,beginDt和endDt)放到表B上的逻辑键中。我已经阅读了一些关于逻辑键的在线资料,但是不能理解。

任何人都可以向我解释一下逻辑键是什么,我如何在我的例子中使用它。

2 个答案:

答案 0 :(得分:1)

不保证TableB.id是唯一的,这是外键引用的要求之一。因此,要么使用id作为TableB的主键CONSTRAINT PK_tableB PRIMARY KEY NONCLUSTERED(id),要么引用所有PK_tableB候选列CONSTRAINT FK_tableC_tableBId FOREIGN KEY(tableBId/*... and a column for each referenced column*/) REFERENCES tableB (id, appNbr, appCode, tableAid, beginDt, endDt)

答案 1 :(得分:1)

一般来说,逻辑键是定义数据和表之间关系的任何东西。主键和外键是最常见的示例,尽管唯一和复合索引属于同一个保护伞。您必须拥有与您定义的任何FK完全匹配的PK或唯一索引。

听起来你理解这个问题以及如何解决它,但这有两种方法:

  • tableB (id)上添加唯一索引:

    CREATE UNIQUE INDEX UI_bID ON dbo.tableB (id)

  • tableB上的PK更改为仅涵盖(id)

例如:

CREATE TABLE tableB (
id int Not Null,
appNbr int NOT NULL,
appCode char(8) NOT NULL,
tableAId int Not Null,
beginDt datetime Not Null,
EndDt datetime Not Null,
updatedDt datetime Not Null,
CONSTRAINT PK_tableB PRIMARY KEY NONCLUSTERED(
id Asc
) WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON, FILLFACTOR = 90)
) 

然后在唯一索引中包含其他列:

CREATE UNIQUE INDEX UI_tableB ON dbo.tableB (
appNbr ASC,
appCode ASC,
tableAid ASC,
beginDt ASC,
endDt ASC)