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

问题描述 投票:0回答:8

在 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 view foreign-keys
8个回答
128
投票

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


32
投票

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


19
投票

如果您确实需要 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
陷入

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


8
投票

抱歉,您无法 FK 到 SQL Server 中的视图。


5
投票

还有另一种选择。将

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
投票

对不起, 从严格意义上来说,不可以在视图上设置外键。原因如下:

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

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

谢谢!


0
投票

如果您需要报告工具(如 Power BI 或 MS Access)的外键,那么有一个解决方法。

  1. 将所有视图从 v_xxx 重命名为 z_xxx
  2. 为每个视图创建一个没有数据的表 v_xxx:select * into v_xxx from z_xxx where 1=0
  3. 添加外键,例如:ALTER TABLE v_2000 ADD FOREIGN KEY (crid) REFERENCES v_crid(crid)
  4. 打开 power bi 并加载 v_xxx 表。外键应出现在“模型”>“管理关系”下
  5. 删除所有v_xxx表
  6. 将所有视图从 z_xxx 重命名为 v_xxx
  7. 刷新 power bi,外键应保留在“管理关系”下
© www.soinside.com 2019 - 2024. All rights reserved.