0

我有一个 MSSQL Server 2008 表,它将多张照片与房屋相关联,如下所示:

HouseID - with foreign key to House table
PhotoID - with foreign key to Photo table

一切都很好,对 PhotoID 有一个独特的约束,因此一张照片不能与多个房子相关联。

我想为房屋记录指定一张默认照片。该表是这样更新的

HouseID
PhotoID
isDefault

问题是房子的一组照片只能有一个 isDefault = 1。

在 MSSQL Server 2008 中,如何确保给定的 House ID 只有一个 isDefault = 1,而其他记录是 isDefault = 0?使用触发器更好,还是有更好的方法?如果是触发器,对确保优化的语法有什么建议吗?

最后,我需要它来处理插入和更新事件。

更新:

以下工作就像一个魅力。注释?

CREATE VIEW HousePhoto_isDefault AS 
SELECT yourSchema.HousePhoto.houseID, yourSchema.HousePhoto.isDefault
FROM yourSchema.HousePhoto WHERE isDefault = 1
GO

CREATE UNIQUE CLUSTERED INDEX idx_HousePhoto_isDefault
ON HousePhoto_isDefault (houseID)
GO
4

4 回答 4

0

在 MSSQL Server 2008 中,如何确保给定的 House ID 只有一个 isDefault = 1,而其他记录是 isDefault = 0?

为什么是的,正如Yves Samèr在这个答案中指出的那样, 您可以使用过滤索引

CREATE UNIQUE INDEX photo_isDefault 
    ON Photos(HouseID) WHERE isDefault = 1 

演示

产生的错误是

无法在具有唯一索引“photo_isDefault”的对象“dbo.Photos”中插入重复的键行。:插入照片(houseID,isDefault)值(1,1)

您也可以选择使用 INDEXED VIEW 或者正如您所指出的,触发器也可以。

于 2013-04-15T21:11:15.373 回答
0

正如您所描述的,您需要使用触发器。

但是,我认为,如果您对数据结构进行小幅更改,则可以使用常规约束来进行。与其存储isDefault在照片级别,不如存储DefaultPhotoId在房屋级别。这样一来,无论您做什么,您都不能拥有超过一张默认照片。

如果要确保有默认值,请将其设置为NOT NULL.

于 2013-04-15T20:51:36.297 回答
0

我实际上认为触发器可能是矫枉过正。只需使用 CASE 语句。这是 UPDATE 语句的示例(用您使用的任何脚本语言替换变量):

UPDATE HousePhoto
SET isDefault = 
(
    CASE
        WHEN
            (PhotoID = @PhotoID)
        THEN
            1
        ELSE
            0
    END
)
WHERE HouseID = @HouseId

当然,您总是可以只使用两个查询。

  UPDATE HousePhoto SET isDefault = 0 WHERE HouseID = @HouseID
  UPDATE HousePhoto SET isDefault = 1 WHERE HouseID = @HouseID AND PhotoID = @PhotoID
于 2013-04-15T21:14:23.953 回答
0

还有另一种方法:使用“反向”FK:

ER模型

[SQL 小提琴]

重要的是要注意识别关系的使用和由此产生的复合 PK 在Photo:中{HouseId, PhotoNo}。这有两个目的:

  • 确保如果照片是某些房子的默认照片,则它必须属于同一房子。
  • 使 FK 成为House复合材料。由于其中一个 FK 字段也在 PK ( HouseId) 中,因此它不能为 NULL,因此拥有另一个可以为 NULL ( DefaultPictureNo) 的字段至关重要。如果任何FK 字段为 NULL,则不会强制执行 FK,这允许我们在存在此类循环 FK 的情况下插入新数据1时打破先有鸡还是先有蛋的问题。

与使用isDefault标志和相关的过滤索引相比,这种方法进行了以下权衡:

  • PRO:避免额外字段的开销。如果图片的总数与默认图片的数量相比非常高,这可能很重要。
  • 缺点:使PhotoPK 使用自动增量变得不切实际。
  • 缺点:如果您在存在此类循环 FK 的情况下尝试使用声明性引用操作(例如 ON DELETE CASCADE),MS SQL Server 会报错。您需要使用触发器实现引用操作。这是一个 MS SQL Server 的怪癖,通常不适用于其他 DBMS。
  • TIE:对集群的干扰较少,Picture代价是对集群的干扰更多House2
  • PRO:它适用于不支持过滤索引的 DBMS(这里不是很重要,但值得一提)。

1 ie 可以让我们在不立即设置默认图片的情况下插入房子,这是不可能的,因为这是一个新房子,还没有图片。

2二级索引在聚簇表中可能很昂贵,并且 FK inHouse将需要一个支持索引。

于 2013-04-16T15:04:29.317 回答