如何使用单列创建复合主键的外键?

Ehr*_*ryk 7 foreign-key sql-server sql-server-2012

我正在使用一个已经存在的“查找”样式表,它在 Microsoft SQL Server 2012 中有一个复合主键(不是我的设计)。我想在另一个表中向它添加一个外键,但只有一个单列,我正在寻找一种解决方法,无论多么不合理(基于 CLR 的自定义库或 dll 劫持,甚至),只是为了看看需要做多少。

下面是一个例子:

CREATE TABLE dbo.Lookup (
    FieldName VARCHAR(100) NOT NULL,
    Value VARCHAR(100) NOT NULL,
    PRIMARY KEY (FieldName, Value)
)

INSERT INTO Lookup (FieldName, Value)
SELECT 'This', 'A' UNION ALL
SELECT 'This', 'B' UNION ALL
SELECT 'That', 'A'

CREATE TABLE dbo.OtherTable (
    ID INT PRIMARY KEY IDENTITY(1,1),
    Blah VARCHAR(100)
)

ALTER TABLE dbo.OtherTable WITH CHECK ADD CONSTRAINT [FK__OtherTable__Blah] 
FOREIGN KEY(Blah) REFERENCES Lookup (Value)

--Cannot create this: 
--"There are no primary or candidate keys in the referenced table 'Lookup' 
--that match the referencing column list in the foreign key 'FK__OtherTable__Blah'."
Run Code Online (Sandbox Code Playgroud)

这有点在意料之中。我非常清楚,用于处理此问题的 SQL 标准是我需要在dbo.OtherTable该存储中包含另一列FieldName以创建外键。

但是,如果我提前知道dbo.OtherTable只使用FieldName“This”呢?为什么我不能添加一个使用“This”的外键来FieldName进行检查?

我知道我可以添加另一列,将它们的所有值设置为“This”,然后继续。我对走这条路没有兴趣。我想知道的是,有多大可能把这个争论到提交。甚至有可能编写我自己的类似外键的完整性检查,如果不能做其他任何事情吗?或者劫持内置的外键实现?

基本上,我正在寻找的是这样的:

ALTER TABLE dbo.OtherTable WITH CHECK ADD CONSTRAINT [FK__OtherTable__Blah] 
FOREIGN KEY('This', Blah) REFERENCES Lookup (FieldName, Value)
Run Code Online (Sandbox Code Playgroud)

此功能在其他 SQL 实现(MySQL、Postgres、Oracle 等)中是否可用?

ype*_*eᵀᴹ 9

是的,您可以使用COMPUTEDcolumn执行此操作,这确实是一种解决方法,因为该列PERSISTED必须用于外键约束,因此它会占用存储空间:

CREATE TABLE dbo.OtherTable (
    ID INT PRIMARY KEY IDENTITY(1,1),
    Blah VARCHAR(100),
    FieldName AS CAST('This' AS VARCHAR(100)) PERSISTED NOT NULL
) ;

ALTER TABLE dbo.OtherTable WITH CHECK 
  ADD CONSTRAINT [FK__OtherTable__Blah] 
    FOREIGN KEY (FieldName, Blah) 
    REFERENCES Lookup (FieldName, Value) ;
Run Code Online (Sandbox Code Playgroud)

SQL-Fiddle测试。

然后可以使用该表,就好像该表FieldName不存在一样。您甚至可以定义一个不包含此列的视图并使您的应用程序使用该视图:SQL-Fiddle-2


您希望的语法虽然看起来很漂亮,但在我所知道的任何 DBMS 中都没有实现:

ALTER TABLE dbo.OtherTable WITH CHECK 
  ADD CONSTRAINT [FK__OtherTable__Blah] 
    FOREIGN KEY('This', Blah) 
    REFERENCES Lookup (FieldName, Value) ;
Run Code Online (Sandbox Code Playgroud)

但是请注意,如果将来只有 SQL-Server 删除了仅使用持久列的限制,则计算列的解决方法将 100% 等效于此语法。您可以根据您的请求添加一个 Connect 项目。

对于是否有任何其他 DBMS 允许这样做的问题,不,没有。还检查一个相关的问题:

是否有 DBMS 允许引用视图(而不仅仅是基表)的外键?


如果您真的不想使用此方法(由于额外的存储要求,替代路径是通过过程或触发器强制执行约束(请注意,您必须为所涉及的两个表编写过程或触发器。)