首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >SQL唯一索引

SQL唯一索引
EN

Stack Overflow用户
提问于 2013-04-25 07:40:50
回答 4查看 199关注 0票数 1

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

卡车

代码语言:javascript
运行
复制
TruckID  int identity
Trailer1 int null
Trailer2 int null

拖车

代码语言:javascript
运行
复制
TrailerID int identity

由于拖车外键是空的,卡车可以没有拖车,也可以有一辆拖车,或者有两辆拖车。

我如何在卡车表上建立一个索引,以确保同一个TrailerID永远不会被使用两次?

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

代码语言:javascript
运行
复制
IsNull(TrailerID, -1 * TruckID)

并在此基础上创建唯一的索引。但我该怎么处理两辆拖车呢?

EN

回答 4

Stack Overflow用户

发布于 2013-04-25 08:57:26

您将需要创建一个索引视图,这将有效地结合拖车。

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

代码语言:javascript
运行
复制
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

现在让我们试试看:

代码语言:javascript
运行
复制
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

票数 2
EN

Stack Overflow用户

发布于 2013-04-25 08:03:15

我认为单靠索引是无法做到这一点的。你需要有你自己的身份。我认为,如果发生违规行为,则必须在更新中插入触发器,以回滚该触发器,这将确保trailerID不存在于任何一个

代码语言:javascript
运行
复制
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。

票数 1
EN

Stack Overflow用户

发布于 2013-04-25 09:02:25

如果可以更改表结构,我建议使用第三个表TrailersTrucks

代码语言:javascript
运行
复制
TrailersTrucks

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

换车报关

代码语言:javascript
运行
复制
Trucks

TruckID  int identity
TrailersTrucksID int null

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

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

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

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/16209015

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档