【问题标题】:SQL Logical KeySQL 逻辑键
【发布时间】:2017-12-18 19:33:12
【问题描述】:

我有三个表,比如说 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

tableC:

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 上的逻辑键。我已经阅读了一些关于逻辑键的在线资料,但无法理解。

谁能解释一下什么是逻辑键以及如何在我的示例中使用它。

【问题讨论】:

  • 感谢 Aaron,在发布上述问题之前,我已经查看了该链接。你能详细说明一下逻辑键吗?

标签: sql sql-server tsql constraints


【解决方案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)

【讨论】:

    【解决方案2】:

    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)

    【讨论】:

    • 是的,我在网上看到解释说要么将 id 设置为 tableB 中的唯一 PK,要么列出 tableB 中表示为 PK 的所有列作为 talbleC FK 中的引用。所以我决定在 tableB 中将 id 更改为 PK,但我不确定如何将 tableB 中的其他列(appNbr、appCode、tableAid、beginDt、endDt)作为我的唯一逻辑键
    • SQL Server 也支持UNIQUE CONSTRAINT。看看:docs.microsoft.com/en-us/sql/relational-databases/tables/…
    • 那么逻辑键在 SQL 中的确切含义是什么?
    猜你喜欢
    • 2016-05-08
    • 2021-11-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-12-12
    • 2020-08-07
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多