1

我有两张桌子(简化) - 卡车和拖车

卡车

TruckID  int identity
Trailer1 int null
Trailer2 int null

拖车

TrailerID int identity

由于拖车外键可以为空,因此卡车可以根本没有拖车、有一个拖车或有两个拖车。

如何在 Trucks 表上建立索引以确保相同的 TrailerID 永远不会被使用两次?

对于一个预告片,我可以创建一个计算域

IsNull(TrailerID, -1 * TruckID)

并为此创建一个唯一索引。但是我如何为两个预告片管理这个?

4

4 回答 4

2

您需要创建一个索引视图,该视图可以有效地合并预告片。

为此,您必须创建一个小型支持表:

CREATE TABLE place (id INT NOT NULL PRIMARY KEY)

INSERT
INTO    place
VALUES  (1),
        (2)

GO

CREATE VIEW
        v_truck_trailers
WITH SCHEMABINDING
AS
        SELECT  t.id AS truckId,
                p.id AS placeId,
                CASE p.id WHEN 1 THEN trailer1 WHEN 2 THEN trailer2 END AS trailerId
        FROM    dbo.truck t
        JOIN    dbo.place p
        ON      CASE p.id WHEN 1 THEN trailer1 WHEN 2 THEN trailer2 END IS NOT NULL
GO

CREATE UNIQUE CLUSTERED INDEX
        ux_v_truck_trailers_truck_place
ON      v_truck_trailers (truckId, placeId)
GO

CREATE UNIQUE INDEX
        ux_v_truck_trailers_trailer
ON      v_truck_trailers (trailerId)
GO

现在让我们尝试一下:

INSERT
INTO    truck
VALUES  (1, 1, NULL) -- succeeds

INSERT
INTO    truck
VALUES  (2, 2, 3) -- also succeeds

INSERT
INTO    truck
VALUES  (3, NULL, 2) -- fails as trailer 2 is already used on truck 2, even if on another place.

请参阅SQLFiddle

于 2013-04-25T08:57:26.250 回答
1

如果您可以更改表结构,我会推荐第三张表 TrailersTrucks

TrailersTrucks

TrailersTrucksID int identity
TruckID  int not null
TrailerID int not null
[TrailerNo int] - optional

更改卡车声明

Trucks

TruckID  int identity
TrailersTrucksID int null

然后您可以在 TrailerID 上使用唯一索引。您可能还想引入 TrailerNo 并将其限制为 1 和 2 个值(或使用枚举)并在 TruckID 和 TrailerNo 上添加唯一索引...这样就不可能向卡车添加 3 个或更多拖车...您如果需要,可以随时扩展约束(例如火车)。

这是解决问题的建议方法,然后您将获得规范化的数据库。

但是我知道这并不总是可能的,原因有很多:)

于 2013-04-25T09:02:25.107 回答
1

我不认为你可以单独使用索引来做到这一点。您需要拥有自己的身份。我认为如果发生违规行为,您将不得不在更新时触发一个触发器以将其回滚,这将确保预告片 ID 在任何一个中都不存在

Select Trailer1 FROM Trucks
UNION
Select Trailer2 FROM Trucks

http://msdn.microsoft.com/en-gb/library/ms189799%28v=sql.105%29.aspx用于触发器

Trailer1 和 Trailer2 上仍然应该有索引,以便优化器可以查找 TrailerID 是否存在于任一列中。

于 2013-04-25T08:03:15.130 回答
0

您可以分别对 Traileid1 和 TrailerId2 进行 UNIQUE 约束。

CREATE TABLE Trailers
(
TrailerID int identity PRIMARY KEY NOT NULL,
t_type varchar(10) null
)


CREATE TABLE Trucks
(
TruckID  int identity PRIMARY KEY NOT NULL,
Trailer1 int UNIQUE null,
Trailer2 int UNIQUE null
FOREIGN KEY ( Trailer1 ) REFERENCES Trailers(TrailerID),
FOREIGN KEY ( Trailer2 ) REFERENCES Trailers(TrailerID),
)
于 2013-04-25T08:38:22.100 回答