如果我有桌子
{{1}}
有没有办法创建一个说
的约束每个widget-version组合可以包含任意数量的0 最新版本的标志但必须恰好有1次出现在哪里 最新的旗帜是1
或者我是否必须使用触发器或类似物?
答案 0 :(得分:1)
我看到两种方式(第三种方式是使用View,但它与第二种解决方案非常相似)
首先,带有检查约束
某事(这个很难看,但你已经明白了):create function [dbo].[checkLatest](@widget varchar(3))
returns bit
as
begin
declare @numOfLatest int;
declare @lastValue int;
declare @maxVersion decimal(18,2);
select @maxVersion = MAX([Version]) from Table1 where Widget = @widget;
--check if there's only one Latest = 1 by Widget
select @numOfLatest = COUNT(*) from Table1 where Widget = @widget and Latest = 1;
--check if Latest = 1 for max version
select @lastValue = Latest from Table1 where [Version] = @maxVersion and Widget = @widget;
return case when @numOfLatest = 1 and @lastValue = 1 then 1 else 0 end
end
GO
然后
ALTER TABLE Table1
WITH CHECK ADD CONSTRAINT CK_LAtest
CHECK (checkLatest(Widget) = 1)
注意:当您在存储过程中将所有最新标志设置为0时,您必须停用约束,然后重新激活它。您可能需要锁定表以避免在禁用约束时进行任何插入/更新...
另一种方式是为Latest
使用计算的colum n:
create function setLatest(@Widget varchar(3), @Version decimal(18,2))
returns bit
as
begin
declare @result bit = 0;
with cte as (select [Version], ROW_NUMBER() over(PARTITION by [Widget] order by [Version] desc) rn from dbo.Table1 where Widget = @Widget)
select @result = case when @Version = [Version] then 1 else 0 end from
cte where rn = 1
and @Version = [Version]
return @result;
end
然后删除最新列
alter table Table1 drop column Latest;
并将其重新添加为计算列
alter table Table1 add Latest as setLatest(Widget, [Version]);
按照它的计算,它永远不会出错,但...... SELECT
语句会花费更多......可能取决于数据的大小。