您将需要创建一个索引视图,这将有效地结合预告片。
对于这一点,你必须创建一个微小的支撑表:
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。
同意。在尝试更新或插入之前,编写SP来首先运行Select语句来检查预告片的存在可能更容易。但我正在寻找一个使用索引的优雅解决方案。 – navigator 2013-04-26 04:12:40
嗯,我不喜欢触发器,因为它们可能很难调试。你可以在联合上创建一个视图,然后(你应该可以)使得结果列唯一。 (我怀疑会触发引擎盖下)。http://msdn.microsoft.com/en-us/library/aa933148%28v=sql.80%29.aspx表明这应该工作 – 2013-04-26 08:55:54
@IanP:你不能在'UNION'上创建一个索引视图。 – Quassnoi 2013-04-26 13:37:19