如何用一个来自另一个表的列的值约束一个列?

时间:2011-10-02 16:05:33

标签: sql sql-server

这不是什么大问题,但我的OCD在我正在创建的数据库中遇到以下问题。我不习惯使用数据库,但数据必须存储在某个地方......

问题

我有两张表AB

My Two Tables

其中一个数据字段对两个表都是通用的 - segment 。存在有限数量的段,我想编写将AB的值通过其段值连接的查询,非常类似于使用以下表结构:

Should be three?

但是,您可以看到表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行无法创建约束。查看以前的错误。

4 个答案:

答案 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_IDA的复合上定义超级键。这是一个快速草图:

A_ID