SQL Server 2012 中 Update FROM子句


首先說明一下需求以及環境

創建Table1以及Table2兩張表,並插入一下數據

USE AdventureWorks2012;

GO

IF OBJECT_ID ('dbo.Table1', 'U') IS NOT NULL

DROP TABLE dbo.Table1;

GO

IF OBJECT_ID ('dbo.Table2', 'U') IS NOT NULL

DROP TABLE dbo.Table2;

GO

CREATE TABLE dbo.Table1

(ColA int NOT NULL, ColB decimal(10,3) NOT NULL);

GO

CREATE TABLE dbo.Table2

(ColA int PRIMARY KEY NOT NULL, ColB decimal(10,3) NOT NULL);

GO

INSERT INTO dbo.Table1 VALUES(1, 20.0),(2, 30.0);

INSERT INTO dbo.Table2 VALUES(1, 0.1),(2, 0.2);

如何通過一個update語句直接使Table2得到以下結果(僅是奇葩業務需求,請勿吐槽)

可以看出請產生的結果集如使用SELECT 僅需使用簡單INNER JOIN來獲得

SELECT dbo.Table2.ColA,

dbo.Table2.ColB

FROM dbo.Table2

INNER JOIN dbo.Table1

ON (dbo.Table2.ColA = dbo.Table1.ColA);

而對於SQL Server 因為UPDATE 具有From子句 可以寫出如下語句,但強烈不建議使用的此方法來進行

UPDATE dbo.Table2

SET dbo.Table2.ColB = dbo.Table2.ColB + dbo.Table1.ColB

FROM dbo.Table2

INNER JOIN dbo.Table1

ON (dbo.Table2.ColA = dbo.Table1.ColA);

官方解釋如下

Use caution when specifying the FROM clause to provide the criteria for the update operation. The results of an UPDATE statement are undefined if the statement includes a FROM clause that is not specified in such a way that only one value is available for each column occurrence that is updated, that is if the UPDATE statement is not deterministic.

指定 FROM 子句為更新操作提供條件時務須小心。 如果 UPDATE 語句包含了未指定每個更新列的位置只有一個可用值的 FROM 子句(換句話說,如果 UPDATE 語句是不確定性的),則其結果將不明確。

Support for use of the READUNCOMMITTED and NOLOCK hints in the FROM clause that apply to the target table of an UPDATE or DELETE statement will be removed in a future version of SQL Server. Avoid using these hints in this context in new development work, and plan to modify applications that currently use them.

在 SQL Server 的未來版本中,將不再支持在 FROM 子句中使用應用於 UPDATE 或 DELETE 語句目標表的 READUNCOMMITTED 和 NOLOCK 提示。 請避免在新的開發工作上下文中使用這些提示,並計划修改當前使用它們的應用程序。

 

個人建議使用MERGE來實現此項功能

MERGE dbo.Table2 AS target

USING (SELECT ColA,ColB FROM dbo.Table1)

    AS source (ColA,COlB)

ON (target.ColA = source.ColA)

WHEN MATCHED

THEN UPDATE SET target.ColB = target.ColB + source.ColB

;

有興趣的同學可以將Table1的數據更改如以下

TRUNCATE TABLE table1;

INSERT INTO dbo.Table1 VALUES(2, 10.0), (1, 20.0),(1, 40.0),(2, 30.0);

 

使用Update后Table2的結果(注意這是一個未確定性的結果集,不代表可以運行處結果結果一定是正確的)

使用MERGE是結果,這個錯誤信息很好的闡述的這個錯誤的原因

Msg 8672, Level 16, State 1, Line 1

The MERGE statement attempted to UPDATE or DELETE the same row more than once. This happens when a target row matches more than one source row. A MERGE statement cannot UPDATE/DELETE the same row of the target table multiple times. Refine the ON clause to ensure a target row matches at most one source row, or use the GROUP BY clause to group the source rows.

 

Oracle 部分,有空我寫一下

是錯誤的,Oracle中(僅在12c中測試)不允許update多行值對於多行列的更新

http://www.cnblogs.com/JasonLiao/archive/2009/12/23/1630895.html

 

Update解釋

http://msdn.microsoft.com/en-us/library/ms177523.aspx

FROM子句

http://msdn.microsoft.com/en-us/library/ms177523.aspx#OtherTables

MERGE 解釋

http://msdn.microsoft.com/en-us/library/bb510625.aspx

Oracle 中Update

http://docs.oracle.com/cd/E11882_01/server.112/e41084/statements_10008.htm#SQLRF01708


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM