4

我有以下表定义:

CREATE TABLE [Car] 
(
   CarID int NOT NULL PRIMARY KEY IDENTITY(1,1),
   FirstColorID int FOREIGN KEY REFERENCES Colors(ColorID),
   SecondColorID int FOREIGN KEY REFERENCES Colors(ColorID),

   UNIQUE(FirstColorID, SecondColorID)
)

我希望这两个颜色列是唯一的,无论它们出现在什么组合中。

例如尝试:

INSERT INTO Car (FirstColorID, SecondColorID) VALUES (1, 2); --should succeed

但是在第一个记录存在并且颜色反转后尝试相同应该失败:

INSERT INTO Car (FirstColorID, SecondColorID) VALUES (2, 1); --should violate constraint/check

我已经使用高级代码解决了这个问题,但我宁愿直接在数据库中强制执行约束,最好不涉及触发器之类的东西。

谢谢。

4

4 回答 4

2

通过设置约束来完全避免该问题SecondColorID >= FirstColorID。它对可以进入数据库的内容产生了限制,这超出了您正在寻找的内容。但是,如果您想查询某种颜色模式,那么这个额外的要求将很有用,因为您只需查找SecondColorID = 1 AND FirstColorID = 2而不是编写额外的逻辑来解释具有不可预测顺序的两个颜色 ID。

CREATE TABLE [Car] 
(
   CarID int NOT NULL PRIMARY KEY IDENTITY(1,1),
   FirstColorID int FOREIGN KEY REFERENCES Colors(ColorID),
   SecondColorID int FOREIGN KEY REFERENCES Colors(ColorID),

   UNIQUE(FirstColorID, SecondColorID)
)

ALTER TABLE [Car] WITH CHECK
    ADD CHECK (SecondColorID >= FirstColorID);
于 2012-07-10T14:35:08.453 回答
2

您也许可以创建计算列,例如:

CREATE TABLE [Car] 
(
   CarID int NOT NULL PRIMARY KEY IDENTITY(1,1),
   FirstColorID int, --FOREIGN KEY REFERENCES Colors(ColorID),
   SecondColorID int, --FOREIGN KEY REFERENCES Colors(ColorID),
   xColor As Cast(Case When FirstColorID > SecondColorID Then FirstColorID Else SecondColorID End as varChar) + ',' + 
        Cast(Case When FirstColorID <= SecondColorID Then SecondColorID Else FirstColorID End as varChar),
   UNIQUE(xColor)
)

更新(你应该先测试一下,我只是做了非常快速的测试)

理念

整数是 4 个字节。如果我将 2 个整数放在一起 - 我得到 8 个字节。如果我订购它们 - 我会得到唯一的 BigInt 值(8 个字节)。

所以我做什么:

  1. 我确保它们的顺序正确
  2. 我将 32 位的字节向左移动(所以只需乘以 4294967296 我就得到了我想要的)
  3. 我进行逻辑 OR- 所以我得到 8 字节 BigInt 值,它应该始终是唯一的!

所以:

CREATE TABLE [Car] 
(
   CarID int NOT NULL PRIMARY KEY IDENTITY(1,1),
   FirstColorID int, --FOREIGN KEY REFERENCES Colors(ColorID),
   SecondColorID int, --FOREIGN KEY REFERENCES Colors(ColorID),
   xColor As 
       Case When FirstColorID > SecondColorID Then 
            Cast(FirstColorID as BigInt) * Cast(4294967296 as BigInt) | Cast(SecondColorID as BigInt)
        Else 
            Cast(SecondColorID as BigInt) * Cast(4294967296 as BigInt) |  Cast(FirstColorID as BigInt)
        End
  UNIQUE(xColor)
)
于 2012-07-10T14:38:25.967 回答
1

创建计算列,使ComputedFirstColorID 是FirstColorID 和SecondColorID 的较低者,ComputedSecondColorID 是FirstColorID 和SecondColorID 的较高者。现在指数

CREATE UNIQUE NONCLUSTERED INDEX index_name ON Car (ComputedFirstColorID, ComputedSecondColorID)

应该没事。

于 2012-07-10T14:38:25.987 回答
0
CREATE UNIQUE NONCLUSTERED INDEX index_name ON Car (FirstColorID, SecondColorID)

http://msdn.microsoft.com/en-us/library/ms188783.aspx

于 2012-07-10T14:23:23.987 回答