問題通過CTE
更新數據的一個子集我剛剛遇到使用上的熱膨脹係數更新語句的概念。 這似乎是一個很好的方法,但是我之前沒有看到它,以及我被介紹給它的上下文(即在一些寫得不好的代碼中發現它)表明作者不知道他們在做什麼。 是否有人知道有任何理由不對CTE進行更新/在做這些時應該考慮哪些因素(假設CTE提供了一些好處;例如允許您更新任意子集的數據)。
全部信息
我最近發現在我們的生產環境中的一些可怕的代碼,其中有人已明確在嘗試就如何更新單行或數據。我已經整理了佈局以使其可讀,但是保留了原來的邏輯。
CREATE PROCEDURE [dbo].[getandupdateWorkOrder]
-- Add the parameters for the stored procedure here
-- @p1 xml Output
AS
BEGIN
WITH T AS
(
SELECT XMLDoc
, Retrieved
from [Transcode].[dbo].[WorkOrder]
where WorkOrderId IN
(
SELECT TOP 1 WorkOrderId
FROM
(
SELECT DISTINCT(WorkOrderId)
, Retrieved
FROM [Transcode].[dbo].[WorkOrder]
WHERE Retrieved = 0
) as c
)
AND Retrieved = 0
)
UPDATE T
SET Retrieved = 1
Output inserted.XMLDoc
END
我可以輕鬆更新這下面不會影響邏輯:
CREATE PROCEDURE [dbo].[GetAndUpdateWorkOrder]
AS
BEGIN
WITH T AS
(
SELECT top 1 XMLDoc
, Retrieved
from [WorkOrder]
where Retrieved = 0
)
UPDATE T
SET Retrieved = 1
Output inserted.XMLDoc
END
但是代碼也向我介紹了一個新的概念;您可以更新CTE /查看底層表中的更新(我之前認爲CTE只讀取了從原始表中選擇的數據的內存中副本,因此無法修改)。 如果我沒有看到最初的代碼,但需要一些東西,表現這樣如下我寫它:
CREATE PROCEDURE [dbo].[GetAndUpdateWorkOrder]
AS
BEGIN
UPDATE [WorkOrder]
SET Retrieved = 1
Output inserted.XMLDoc
where Id in
(
select top 1 Id
from [WorkOrder]
where Retrieved = 0
--order by Id --I'd have included this too; but not including here to ensure my rewrite is *exactly* the same as the original in terms of functionality, including the unpredictable part (the bonus of not including this is a performance benefit; though that's negligible given the data in this table)
)
END
其通過CTE進行更新的代碼看起來清爽多了(即你不甚至需要依靠一個唯一的ID來工作)。 然而,由於原始代碼的其他部分寫得很糟糕,我對這種新技術感到擔憂,所以想在將這種方法添加到我的庫中之前,先看看專家對這種方法的看法。
只有當CTE從單個表中選擇時,纔可以直接在CTE上使用'UPDATE','DELETE'或'INSERT'。否則,你必須加入它。 –
沒有'ORDER BY'的'SELECT TOP 1 WorkOrderId'不是確定性的。 –
@TimSchmelter - 對於'update'不是這樣,但更新的列必須全部來自同一個表。 –