我有一张看起来像这样的表:
CREATE TABLE A (
A_UNIQUE_ID int NOT NULL PRIMARY KEY,
A_OTHER_ID int NOT NULL,
A_CURRENT_FL bit NOT NULL )
并且它具有与此类似的值
INSERT INTO TABLE A VALUES (1, 1, 0);
INSERT INTO TABLE A VALUES (2, 1, 0);
INSERT INTO TABLE A VALUES (3, 1, 1);
我想创建另一个像这样的表B
CREATE TABLE B (
B_UNIQUE_ID int NOT NULL PRIMARY KEY,
A_OTHER_ID int NOT NULL)
其中B.A_OTHER_ID
被约束为A中的唯一行。所以B.A_OTHER_ID = A.A_OTHER_ID AND A.CURRENT_FL = 1
。是否可以使用某种类型的检查约束设置?非常感谢例子。
答案 0 :(得分:0)
好的开始你需要一个约束表A,使它如上所述独特。使用此answer,您可以创建一个函数并在新的检查约束中调用它。 例如:
CREATE FUNCTION Check_A_CURRENT_FL_Count(@Id INT) RETURNS INT AS
BEGIN
DECLARE @ret INT;
SELECT @ret = COUNT(*) FROM A WHERE A_OTHER_ID = @Id AND A_CURRENT_FL = 1;
RETURN @ret;
END
GO
alter table A add constraint [CK_A] CHECK (NOT (dbo.Check_A_CURRENT_FL_Count(A_OTHER_ID) > 1 AND A_CURRENT_FL = 1))
GO
然后,如果我正确理解你想要的东西 - 你可以在表B的检查约束中使用相同的功能。不完全确定这个目的是什么,尽管显然你使用的是一个人为的例子。如果您想要表A中的唯一ID列表 - 您可以使用A_OTHER_ID作为表B中的主键,并摆脱B_UNIQUE_ID?
答案 1 :(得分:0)
您可以使用一些计算列来完成它,但它看起来不是很漂亮:
CREATE TABLE A (
A_UNIQUE_ID int NOT NULL PRIMARY KEY,
A_OTHER_ID int NOT NULL,
A_CURRENT_FL bit NOT NULL,
OTHER_XREF as CASE WHEN A_CURRENT_FL = 1 THEN A_OTHER_ID END persisted,
UNIQ as CASE WHEN A_CURRENT_FL = 0 THEN A_UNIQUE_ID ELSE 0 END persisted
constraint UQ_OTHER_XREF UNIQUE (OTHER_XREF,UNIQ)
)
INSERT INTO A VALUES (1, 1, 0);
INSERT INTO A VALUES (2, 1, 0);
INSERT INTO A VALUES (3, 1, 1);
CREATE TABLE B (
B_UNIQUE_ID int NOT NULL PRIMARY KEY,
A_OTHER_ID int NOT NULL,
XREF as 0 persisted,
constraint FK_B_A FOREIGN KEY (A_OTHER_ID,XREF) references A (OTHER_XREF,UNIQ))
这有效:
insert into B VALUES (2,1)
这打破了FK约束:
insert into B VALUES (3,2)
表A中的两个计算列确保A_CURRENT_FL
= 1
的任何行都将其作为OTHER_XREF
中的不同值。其他行在该列中将包含NULL
。但是,要应用UNIQUE
约束(外键的目标),我们需要对于具有NULL
的每一行都有明显不同的内容,同时对于具有A_CURRENT_FL
的行是一个众所周知的值。 1
= 0
。在这种情况下,我创造了众所周知的价值0
。
最后,外键约束需要匹配这些列的两个,因此我们在表B中添加一个具有众所周知的值A_CURRENT_FL
的新计算列。
列名不是特别好,但我相信你能想出一些。
另请注意,通过上述内容,我们还实现了另一个您未提及的约束,但这也可能很重要 - 表A中现在不能有两行{{1设置为1,表示相同的A_OTHER_ID
值。这也会产生错误:
INSERT INTO A VALUES (4,1,1);