1
Widget Version Latest
XYZ 1.0 0
XYZ 1.1 0
XYZ 1.2 1
ABC 1.0 1
有沒有一種方法來創建一個約束,說
每個插件版本的組合可以有任意數量的0爲 最新版本的標誌,但必須有確切1發生在哪裏 最新標誌是1
?
還是我必須使用觸發器或類似的?
Widget Version Latest
XYZ 1.0 0
XYZ 1.1 0
XYZ 1.2 1
ABC 1.0 1
有沒有一種方法來創建一個約束,說
每個插件版本的組合可以有任意數量的0爲 最新版本的標誌,但必須有確切1發生在哪裏 最新標誌是1
?
還是我必須使用觸發器或類似的?
我看到兩種方法(第三個是使用視圖,但它是相當類似於第二溶液)
首先,有檢查約束
東西(這個人是醜陋,但你的想法):
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在存儲過程中停用約束,然後重新激活它。您可能需要鎖定你的表以避免任何插入/更新,而約束是停用...
另一種方式將使用計算科拉姆 n表示Latest
:
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
語句將花費更多...可依您的數據更大小。
真棒答案 - 學會兩個偉大的事情。謝謝。 – Ryan
問題:當您插入新行(用最新版本),你必須把最新的。例如,'小工具:XYZ','版本:1.3'。所以這一個必須有最新= 1,但是'XYZ/1.2'必須更新以使最新= 0,因爲它不再是最新值。有一段時間,您需要接受兩條最新= 1(通過窗口小部件)或沒有最新= 1的線...... –
在我的s/p中,我先刪除所有現有窗口小部件版本上的最新標誌,我認爲這符合上面的約束。 – Ryan
那麼,當你刪除標誌,有一個而當'必須恰好1 occurence其中最新的標誌是1'不再有效...... –