在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:
您无法在外键中引用视图。
如果您确实需要A_or_B_ID
TableZ,则有两个类似的选择:
1)向表z中添加nullableA_ID
和B_ID
column,A_or_B_ID
在这两列上使用ISNULL来创建计算列,并添加CHECK约束,以使A_ID
或之一B_ID
不为null
2)将TableName列添加到表z中,约束为包含A或B。现在创建列A_ID
并B_ID
作为计算列,当它们的适当表被命名时(使用CASE表达式),它们仅是非null的。也让他们坚持
在这两种情况下,您现在都有A_ID
和B_ID
列,这些列可以具有基本表的适当外键。区别在于计算列的方式。另外,如果2个ID列的域不重叠,则在上面的选项2中不需要TableName-只要您的case表达式可以确定哪个域A_or_B_ID
属于
(感谢您对我的格式进行评论)
A_or_B_ID
抱歉,您无法FK到SQL Server中的视图。
还有另一种选择。将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中将其正式化。
添加引用用户定义函数的约束比较容易,fCheckIfValueExists(columnValue)会为您进行检查,如果该值存在,则返回true,否则返回false。
好处是它可以接收多列,使用它们执行计算,接受空值以及接受与主键不完全对应的值或与联接结果进行比较。
缺点是优化器无法使用他的所有外键技巧。
抱歉,严格来说,不能在视图上设置外键。原因如下:
InnoDB是MySQL唯一具有外键的内置存储引擎。任何InnoDB表都将使用engine ='InnoDB'在information_schema.tables中注册。
视图在information_schema.tables中注册时,具有NULL存储引擎。在MySQL中,没有任何机制可以在具有未定义存储引擎的任何表上具有外键。
谢谢!