这不是什么大问题,但我的OCD在我正在创建的数据库中遇到以下问题。我不习惯使用数据库,但数据必须存储在某个地方......
问题
我有两张表A
和B
。
其中一个数据字段对两个表都是通用的 - segment 。存在有限数量的段,我想编写将A
到B
的值通过其段值连接的查询,非常类似于使用以下表结构:
但是,您可以看到表Segments
为空。没有什么我想要放入该表,而不是ID将其他表作为外键。我希望我的表格尽可能简单,因此添加另一个表格似乎错误。
另请注意,其中一个表(A
,例如)实际上是 master ,因为您应该能够将段的任何值放入A
,但是B
在插入之前应首先检查A
。
修改 我尝试了下面的答案之一:
create table A(
id int primary key identity,
segment int not null
)
create table B(
id integer primary key identity,
segment int not null
)
--Andomar's suggestion
alter table B add constraint FK_B_SegmentID
foreign key (segment) references A(segment)
这会产生以下错误。
也许我不清楚segment
在A或B中不是唯一的,并且可以在两个表中多次出现。
Msg 1776,Level 16,State 0,Line 11没有小学或候选人 引用表'A'中与引用列匹配的键 在外键'FK_B_SegmentID'中列出。 Msg 1750,Level 16,State 0, 第11行无法创建约束。查看以前的错误。
答案 0 :(得分:3)
您可以直接从B.SegmentID到A.SegmentID创建外键关系。没有额外的桌子。
更新:如果SegmentID在TableA中不是唯一的,那么执行需要额外的表来存储段ID,并从两个表到此表创建外键关系。但这并不足以强制表B中的所有段ID也出现在TableA中。你可以使用触发器。
答案 1 :(得分:2)
您可以使用外键确保A中存在分段:
alter table B add constraint FK_B_SegmentID
foreign key (SegmentID) references A(SegmentID)
要避免B中没有段的行,请使B.SegmentID
不可为空:
alter table B alter column SegmentID int not null
除非您想要将额外数据与Segments
相关联,否则无需创建SegmentID
表。
答案 2 :(得分:1)
Andomar和Mark Byers写道,您不必创建额外的表格。
您还可以在主服务器上CASCADE
更新或删除。不过要小心ON DELETE CASCADE
!
对于查询,请使用JOIN:
SELECT *
FROM A
JOIN B ON a.SegmentID = b.SegmentID
您必须在“master”表中的segment_id上添加UNIQUE constraint以避免重复,否则无法使用外键。像这样:
ALTER TABLE A ADD CONSTRAINT UNQ_A_SegmentID UNIQUE (SegmentID);
答案 3 :(得分:1)
如果我理解正确,除非已将某个段插入表B
,否则无法将其添加到表A
中。在这种情况下,表A
应引用表Segments
,表B
应引用表A
;表B
最终会引用表Segments
(间接通过表A
),因此不需要显式引用。这可以使用外键完成(例如,不需要触发器)。
由于表A
有自己的密钥,我假设某个segment_ID
可以多次出现在表A
中,因此B
能够引用{ {1}}中的{1}}值,然后需要在segment_ID
和A
的复合上定义超级键。这是一个快速草图:
A_ID