我可以使用外键引用SQL Server视图中的列吗?


84

在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?可以使用针对视图的外键来完成此操作吗?

Answers:


108

您无法在外键中引用视图。


36
这是SQL Server的限制,还是想要的不合理的事情?
亚伦·奥诺德

1
@Brian我也很想知道这是对SQL Server的限制还是想要的不合理的事情,因为在这一点上,我将使用触发器来模拟视图以获取FK支持(尽管我正在使用MySql )。
雪橇2012年

4
这是一个很好的解决这些后续问题- stackoverflow.com/questions/3833150/...
克里斯合乐

我不确定这是对这些问题的一个好答案...这是关于另一种DBMS的,并且说视图是为隐藏架构细节和用户方便而设计的。首先,好吧……但这不是在初始设计之外找到可靠用例的第一件事。其次,我不确定为什么FK不会这样做。视图可以是甚至不必从表中绘制出来的任何查询,也可以是将一堆常量联合在一起的视图……在这种情况下,外键似乎非常明智。如果有原因,我不希望有更深层次的内容。
George Mauer

27

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


3
欢迎使用StackOverflow。由于提供了一种解决方法,因此我在您的答案中发现了价值,但正确的答案是被接受的答案,而且这个问题已经有4年了,所以我只是不投票,也不想留下这个评论。
jachguate

16

如果您确实需要A_or_B_IDTableZ,则有两个类似的选择:

1)向表z中添加nullableA_IDB_IDcolumn,A_or_B_ID在这两列上使用ISNULL来创建计算列,并添加CHECK约束,以使A_ID或之一B_ID不为null

2)将TableName列添加到表z中,约束为包含A或B。现在创建列A_IDB_ID作为计算列,当它们的适当表被命名时(使用CASE表达式),它们仅是非null的。也让他们坚持

在这两种情况下,您现在都有A_IDB_ID列,这些列可以具有基本表的适当外键。区别在于计算列的方式。另外,如果2个I​​D列的域不重叠,则在上面的选项2中不需要TableName-只要您的case表达式可以确定哪个域A_or_B_ID 属于

(感谢您对我的格式进行评论)


在下划线中加上下划线: A_or_B_ID
比尔·卡文

我正在为旧系统添加一些功能,这是将旧的和新的修补在一起的好方法。谢谢!
David Gunderson


4

还有另一种选择。将TableA和TableB视为新表TablePrime的子类。调整TableB的ID值,使其与TableA的ID值不一致。将TablePrime中的ID设置为PK,然后将TableA和TableB的所有(调整后的)ID插入TablePrime中。使TableA和TableB的PK与TablePrime中的相同ID具有FK关系。

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

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


2

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

好处是它可以接收多列,使用它们执行计算,接受空值以及接受与主键不完全对应的值或与联接结果进行比较。

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


1
缺点是优化器无法使用他的所有外键技巧... ...并且该函数将在您插入/更新的每一行上运行(因此对于集合来说不太好)。
jimbobmcgee'5

0

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

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

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

谢谢!


这个问题是关于sql server的
George Mauer
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.