【问题标题】:SQL Server Conditional Foreign KeySQL Server 条件外键
【发布时间】:2018-08-19 02:25:24
【问题描述】:

我的 SQL Server 数据库中有两个表,Foo 和 Bar。 Table Foo 是这样的:

+-------+
|  Foo  |
+-------+
| Id    |
| Type  |
| Value |
+-------+

该表的值如下:

+----+--------+-----------+
| Id |  Type  |   Value   |
+----+--------+-----------+
|  1 | Status | New       |
|  2 | Status | Old       |
|  3 | Type   | Car       |
|  4 | State  | Inventory |
|  5 | State  | Sold      |
+----+--------+-----------+

表格栏是这样的:

+----------+
|   Bar    |
+----------+
| Id       |
| TypeId   |
| StatusId |
| StateId  |
+----------+

其中TypeIdStatusIdStateId 都是 Foo 表的外键。 但我想对每个外键设置一个条件,它们只能对 Foo 进行键控 与其类型相关的 ID。例如,TypeId 列只能外键到 id 3 在 Foo 表上。或者StatusId 列只能是 ids 1 或 2 的外键。

我知道 SQL Server 中有一个检查功能,但我不确定如何正确使用它。我 试图做这样的事情:

CREATE TABLE TEST.dbo.Bar
(
    Id int PRIMARY KEY NOT NULL IDENTITY,
    TypeId int NOT NULL CHECK (Type='Type'),
    CONSTRAINT FK_Bar_Foo_Type FOREIGN KEY (TypeId) REFERENCES Foo (Id, Type)
)
CREATE UNIQUE INDEX Bar_Id_uindex ON TEST.dbo.Bar (Id)

但这没有用。我做错了什么?

【问题讨论】:

  • CHECK 用于确保列中的值在某些硬编码值范围内。这根本不是你想要的。您需要的是使用函数的约束。这个问题已经被问了几十次了。
  • FWIW“外键”不是动词,而是名词。 :)
  • 我不认为外键能如你所愿。这有点与“多态外键”有关,但又不太一样。
  • 您可以扩展bar,例如'Status' 之类的列(可以计算但必须持久化),然后在引用@ 的数字词对上放置外键约束foo 中的 987654332@ 和 type(可能在 foo 中声明了对主键或唯一后)。否则,您必须在 bar 上创建一个触发器,以按照您想要的方式进行检查。
  • 只是加上我的 2 美分,但这是一个糟糕的设计。创建typestatusstate表;为他们创建一个适当的 FK,让 SQL 完成它的工作,然后收工。当输入无效的组合时,你所做的任何事情都会引发错误,这将是一种黑客攻击。

标签: sql sql-server foreign-keys conditional-statements


【解决方案1】:

您所指的检查约束仅用于限制存储在键或非键列中的信息类型。因此,如果您不希望键列具有负值(假设它是价格列,并且永远不会有负价格),您将使用 Check 约束。

为了更好地理解主键和外键的概念:

主键唯一标识表中的每条记录。 外键是某个表中的一个值,它是另一个表中的唯一标识符(也可以是主键)。这意味着外键可以在它作为外键的表中重复多次,并且它在创建它的表中肯定是唯一的(在赋予它意义的表中)。

现在谈到您的问题,您可能需要使用复合键的概念。复合键基本上是一组两个或多个唯一标识记录的值,因为您不能以您打算做的方式对外键施加限制,因为这违背了键的目的。在应用层而不是数据库层处理存储在密钥中的数据类型的一些问题。

以这种方式看待问题也将从概念上解决您的表格的一些设计缺陷。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-24
    • 2011-02-19
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多