在 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
中找到的值?这可以通过针对视图的外键来完成吗?
您无法在外键中引用视图。
在旧版 SQL Server 版本中,外键只能通过触发器实现。您可以通过创建插入触发器来模拟自定义外键,该触发器检查插入的值是否也出现在相关表之一中。
如果您确实需要 TableZ 中的
A_or_B_ID
,您有两个类似的选项:
1) 将可空的
A_ID
和 B_ID
列添加到表 z,在这两列上使用 ISNULL 使 A_or_B_ID
成为计算列,并添加 CHECK 约束,以便仅 A_ID
或 B_ID
之一不存在空
2) 将 TableName 列添加到表 z,限制为包含 A 或 B。现在创建
A_ID
和 B_ID
作为计算列,只有在命名相应的表(使用 CASE 表达式)时,它们才为非空。让他们也坚持下去
在这两种情况下,您现在都有
A_ID
和 B_ID
列,它们可以具有适当的外国
基表的键。区别在于计算哪些列。还有,你
如果 2 个 ID 列的域不需要,则不需要上面选项 2 中的 TableName
重叠 - 只要你的 case 表达式可以确定哪个域 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 表都将在 information_schema.tables 中注册,其中 engine = 'InnoDB'。
视图在 information_schema.tables 中注册时,具有 NULL 存储引擎。 MySQL 中没有任何机制可以在任何具有未定义存储引擎的表上拥有外键。
谢谢!
如果您需要报告工具(如 Power BI 或 MS Access)的外键,那么有一个解决方法。