SQL Server 2012 中 Update FROM子句

本文探讨了在SQL Server环境中,如何使用UPDATE语句结合FROM子句和MERGE语句来更新表数据的方法。详细比较了两种方法的效果,并强调了在特定场景下使用MERGE语句的优势。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

首先说明一下需求以及环境

创建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

转载于:https://www.cnblogs.com/cnLing/p/3316178.html

<think>我们正在讨论SQLServer中的UPDATE语句,特别是使用FROM子句的语法。根据用户的问题,他想知道是否可以在UPDATE中使用FROM子句,并请求示例。在SQLServer中,UPDATE语句可以使用FROM子句来指定其他表,以便基于这些表来更新目标表。这通常用于根据其他表中的数据来更新目标表。参考引用[3]中的示例,它展示了使用FROM子句UPDATE语句。我们来看一下:引用[3]的示例:UPDATEt1SETt1.Column1=t2.Column2OUTPUTinserted.ID,inserted.Column1INTOLogTable(ID,Column1)FROMTable1t1INNERJOINTable2t2ONt1.ID=t2.ID;这个例子中,UPDATE语句更新了表Table1(别名为t1)的Column1字段,将其设置为Table2(别名为t2)的Column2字段的值。更新条件是t1.ID等于t2.ID。同时,使用了OUTPUT子句将更新的数据插入到LogTable中。但是,请注意,在SQLServer中,UPDATE语句的FROM子句并不是标准SQL的一部分,它是SQLServer的扩展语法。下面我们将提供一个更清晰的示例,不使用OUTPUT子句,以便专注于FROM子句的用法。示例:假设我们有两个表:Employees和SalaryAdjustments。我们想要根据SalaryAdjustments表中的调整金额来更新Employees表中的薪水。-Employees表结构:EmployeeID,EmployeeName,Salary-SalaryAdjustments表结构:EmployeeID,AdjustmentAmount现在,我们想将每个员工的薪水增加AdjustmentAmount。可以使用如下UPDATE语句:```sqlUPDATEeSETe.Salary=e.Salary+s.AdjustmentAmountFROMEmployeeseINNERJOINSalaryAdjustmentssONe.EmployeeID=s.EmployeeID;```在这个示例中,我们通过FROM子句将Employees表(别名为e)和SalaryAdjustments表(别名为s)连接起来,然后根据连接的条件更新Employees表中的Salary字段。需要注意的是,在UPDATE子句中,我们使用了表的别名(e)来指定要更新的列,这样SQLServer就知道我们要更新的是哪个表的列。另外,如果只想更新满足特定条件的行,可以在语句末尾添加WHERE子句,例如:```sqlUPDATEeSETe.Salary=e.Salary+s.AdjustmentAmountFROMEmployeeseINNERJOINSalaryAdjustmentssONe.EmployeeID=s.EmployeeIDWHEREs.AdjustmentAmount>100;--只调整大于100的```总结:SQLServer支持在UPDATE语句中使用FROM子句,以便基于其他表来更新目标表。根据用户要求,我们生成相关问题:§§相关问题§§1.在UPDATE语句中使用FROM子句时,如何避免更新多行?2.能否在UPDATEFROM子句中使用子查询?3.在SQLServer中,UPDATE语句的FROM子句和标准SQL中的多表更新有什么不同?</think> 在 SQL Server 中,`UPDATE` 语句确实可以使用 `FROM` 子句来实现基于其他表的条件更新。这种语法特别适用于需要根据关联表中的数据来更新目标表的情况。 ### 基本语法结构: ```sql UPDATE 目标表 SET 目标列 = 源值 FROM 目标表 [别名] JOIN 关联表 [别名] ON 连接条件 [WHERE 过滤条件] ``` ### 实用示例: #### 示例 1:基于关联表更新字段 ```sql -- 根据产品类别调整产品价格 UPDATE p SET p.UnitPrice = p.UnitPrice * c.PriceMultiplier FROM Products p INNER JOIN ProductCategories c ON p.CategoryID = c.CategoryID WHERE c.CategoryName = 'Premium'; ``` ▸ 说明: 此语句将`Premium`类别产品的单价乘以对应的价格系数。通过`INNER JOIN`确保只更新存在关联类别的产品 [^1]。 #### 示例 2:多表关联更新 ```sql -- 根据订单和客户信息更新订单状态 UPDATE o SET o.Status = 'VIP_PROCESSING' FROM Orders o INNER JOIN Customers c ON o.CustomerID = c.CustomerID INNER JOIN CustomerLevels cl ON c.LevelID = cl.LevelID WHERE cl.LevelName = 'Platinum'; ``` ▸ 说明: 通过两层关联(客户→客户等级),将`Platinum`级别客户的所有订单状态更新为`VIP_PROCESSING` [^3]。 #### 示例 3:带子查询的更新 ```sql -- 将库存量低于平均值的产品标记为低库存 UPDATE p SET p.StockFlag = 'LOW' FROM Products p WHERE p.UnitsInStock < ( SELECT AVG(UnitsInStock) FROM Products ); ``` ▸ 说明: 子查询计算所有产品的平均库存量,`WHERE`子句筛选出低于该平均值的产品进行标记。 ### 关键注意事项: 1. **别名必需**: 目标表在`FROM`子句中必须使用别名(如示例中的`p`、`o`) 2. **连接条件明确**: 多表连接时需明确指定关联条件,避免笛卡尔积导致的意外更新 3. **可结合 OUTPUT 子句**: ```sql UPDATE p SET UnitPrice = UnitPrice * 1.1 OUTPUT deleted.UnitPrice AS OldPrice, inserted.UnitPrice AS NewPrice FROM Products p... ``` 可捕获更新前后的数据变化 [^2] ### 应用场景: 1. 批量更新关联数据(如根据汇率更新价格) 2. 数据状态迁移(如根据规则批量更新订单状态) 3. 数据清洗(使用参考表修正异常值)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值