89

在 SQL Server 2008 中并给出

TableA(A_ID, A_Data)
TableB(B_ID, B_Data)
ViewC(A_or_B_ID, A_or_B_Data)

是否可以定义TableZ(A_or_B_ID, Z_Data)这样的Z.A_or_B_ID列被限制在中找到的值ViewC?这可以通过针对视图的外键来完成吗?

4

7 回答 7

118

您不能在外键中引用视图。

于 2009-01-15T15:25:06.597 回答
31

在较旧的 SQL Server 版本中,外键只能通过触发器来实现。您可以通过创建一个插入触发器来模拟自定义外键,该触发器检查插入的值是否也出现在相关表之一中。

于 2013-03-10T08:59:26.590 回答
19

如果你真的需要A_or_B_ID在 TableZ 中,你有两个类似的选择:

1)向表 z添加可空列A_ID和列,在这两个列上使用 ISNULL 创建一个计算列,并添加一个 CHECK 约束,使得只有一个or不为空B_IDA_or_B_IDA_IDB_ID

2) 向表 z 添加一个 TableName 列,限制为包含 A 或 B。现在创建A_IDB_ID作为计算列,这些列仅在其适当的表被命名时才为非空(使用 CASE 表达式)。让他们也坚持

在这两种情况下,您现在都拥有A_IDB_ID列,这些列可以具有基表的适当外键。不同之处在于计算哪些列。此外,如果 2 个 ID 列的域不重叠,则不需要上面选项 2 中的 TableName - 只要您的案例表达式可以确定哪个域A_or_B_ID 属于

(感谢评论修复我的格式)

于 2009-01-15T15:36:45.530 回答
8

抱歉,您不能 FK 到 SQL Server 中的视图。

于 2009-01-15T15:25:17.003 回答
5

还有另一种选择。TableA将和视为TableB名为 的新表的子类TablePrime。调整TableB的 ID 值,使其与 的 ID 值不一致TableA。在 PK 中制作 IDTablePrime并将所有TableA' 和TableB' 的(调整后的)ID 插入TablePrime. 在他们的 PK 上TableA与.TableBTablePrime

您现在拥有超类型/子类型模式,并且可以对TablePrime(当您需要-A-or-B时)或单个表之一(当您只需要 AB时)进行约束。

如果您需要更多详细信息,请询问。有一些变化可以让你确保 A 和 B 是互斥的,或者你正在使用的东西可以同时是两者。如果可能,最好在 FK 中将其正式化。

于 2012-07-27T20:34:36.503 回答
2

添加引用用户定义函数的约束更容易,该函数为您进行检查, fCheckIfValueExists(columnValue) 如果值存在则返回 true,否则返回 false。

好处是它可以接收多个列,使用它们执行计算,接受空值并接受与主键不精确对应的值或与连接结果进行比较。

缺点是优化器不能使用他所有的外键技巧。

于 2015-12-29T17:56:50.237 回答
1

抱歉,严格来说,不,您不能在视图上设置外键。原因如下:

InnoDB 是 MySQL 唯一具有外键的内置存储引擎。任何 InnoDB 表都将在 information_schema.tables 中注册,其中 engine = 'InnoDB'。

视图虽然注册在 information_schema.tables 中,但有一个 NULL 存储引擎。MySQL 中没有任何机制可以在具有未定义存储引擎的任何表上具有外键。

谢谢!

于 2018-08-13T02:15:18.983 回答