引用列的SQL Server约束

时间:2012-08-30 22:33:55

标签: sql-server

我有一张看起来像这样的表:

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。是否可以使用某种类型的检查约束设置?非常感谢例子。

2 个答案:

答案 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);