[英]t-sql single default value for multiple records
I have an MSSQL Server 2008 table that associates multiple photos to houses, as follows: 我有一个MSSQL Server 2008表,将多张照片与房屋相关联,如下所示:
HouseID - with foreign key to House table
PhotoID - with foreign key to Photo table
It's all working great, with an unique constraint on PhotoID so that a photo cannot be associated with multiple houses. 一切都很好,对PhotoID具有独特的约束,因此照片不能与多个房屋相关联。
I would like to specify a default photo for the house records. 我想为房屋记录指定默认照片。 The table is updated as such 该表将这样更新
HouseID
PhotoID
isDefault
The issue is that there can only be a single isDefault = 1 for a set of photos for a house. 问题在于,一套房子的照片只能有一个isDefault = 1。
In MSSQL Server 2008, how do I ensure that there is only a single isDefault = 1 for a given House ID, and the other records are isDefault = 0? 在MSSQL Server 2008中,如何确保给定房屋ID只有一个isDefault = 1,而其他记录是isDefault = 0? Is it better to use a trigger, or is there a better way? 使用触发器更好还是有更好的方法? If a trigger, any suggestions on the syntax to ensure optimization? 如果是触发器,则对确保优化的语法有何建议?
Lastly, I need this to work on the Insert and on the Update events. 最后,我需要它来处理Insert和Update事件。
Update: 更新:
The following worked like a charm. 以下作品颇有魅力。 Comments? 评论?
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
As you describe it, you would need to use triggers. 正如您描述的那样,您将需要使用触发器。
However, if you make a small change to the data structure, you can do it with regular constraints, I think. 但是,我认为,如果对数据结构进行少量更改,则可以在常规约束下进行。 Instead of storing isDefault
at the photo-level, store DefaultPhotoId
at the house-level. 与其在照片级存储isDefault
, DefaultPhotoId
在房屋级存储DefaultPhotoId
。 That way, you can never have more than one default photo, no matter what you do. 这样一来,无论您做什么,都不能拥有多个默认照片。
If you want to ensure that there is a default, then set it up as NOT NULL
. 如果要确保存在默认值,则将其设置为NOT NULL
。
In MSSQL Server 2008, how do I ensure that there is only a single isDefault = 1 for a given House ID, and the other records are isDefault = 0? 在MSSQL Server 2008中,如何确保给定房屋ID只有一个isDefault = 1,而其他记录是isDefault = 0?
Why yes as Yves Samèr pointed out in this answer you can use use a filtered index 为什么是如YvesSamèr在此答案中指出的那样,您可以使用过滤索引
CREATE UNIQUE INDEX photo_isDefault
ON Photos(HouseID) WHERE isDefault = 1
The error that is produced is 产生的错误是
Cannot insert duplicate key row in object 'dbo.Photos' with unique index 'photo_isDefault'.: INSERT INTO Photos (houseID, isDefault) VALUES (1,1) 无法在具有唯一索引'photo_isDefault'的对象'dbo.Photos'中插入重复的键行。:INSERT INTO Photos(houseID,isDefault)值(1,1)
You could also opt to use a INDEXED VIEW or as you noted a trigger will do as well. 您还可以选择使用INDEXD VIEW,或者正如您提到的,触发器也可以。
I actually think that triggers might be overkill. 我实际上认为触发器可能会过大。 Just use CASE statements. 只需使用CASE语句即可。 Here's an example of the UPDATE statement (replacing the variables with whatever scripting language you're using): 这是UPDATE语句的示例(用您使用的任何脚本语言替换变量):
UPDATE HousePhoto
SET isDefault =
(
CASE
WHEN
(PhotoID = @PhotoID)
THEN
1
ELSE
0
END
)
WHERE HouseID = @HouseId
Of course, you could always just use two queries. 当然,您始终可以只使用两个查询。
UPDATE HousePhoto SET isDefault = 0 WHERE HouseID = @HouseID
UPDATE HousePhoto SET isDefault = 1 WHERE HouseID = @HouseID AND PhotoID = @PhotoID
There another approach: use a "reverse" FK: 还有另一种方法:使用“反向” FK:
It is crucial to note the usage of the identifying relationship and the resulting composite PK in Photo
: {HouseId, PhotoNo}
. 至关重要的是要注意在Photo
使用标识关系和合成的PK: {HouseId, PhotoNo}
。 This serves two purposes: 这有两个目的:
House
composite. 使FK in House
复合。 Since one of the FK fields is also in the PK ( HouseId
), it cannot be NULL, so it is crucial to have another field that can be NULL ( DefaultPictureNo
). 由于FK字段之一也位于PK( HouseId
)中,因此它不能为NULL,因此具有另一个可以为NULL的字段( DefaultPictureNo
)至关重要。 If any of the FK fields is NULL, the FK is not enforced which allows us to break the chicken-and-egg problem when inserting new data 1 in the presence of such circular FKs. 如果任何 FK字段为NULL,则不会强制执行FK,这使我们能够在存在此类循环FK的情况下插入新数据1时解决“鸡与蛋”问题。 Compared to using isDefault
flag and the associated filtered index, this approach makes the following tradeoffs: 与使用isDefault
标志和关联的过滤索引相比,此方法进行了以下权衡:
Photo
PK. 缺点:不能对Photo
PK使用自动增量。 Picture
, at the price of interfering more with clustering in House
. TIE:对Picture
聚类产生较少的干扰,但要对House
聚类产生更多的干扰。 2 2 1 Ie enables us to insert a house without setting the default picture right away, which would be impossible since this is a new house and has no pictures yet. 1 Ie使我们能够插入房屋而无需立即设置默认图片,这将是不可能的,因为这是一栋新房屋,尚无图片。
2 Secondary indexes can be expensive in clustered tables, and the FK in House
will need a supporting index. 2个辅助索引可以在集群表昂贵,而FK在House
将需要一个支撑指数。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.