SQL Server UPDATE 语句是修改数据库表中现有数据的最常用 DML(数据操作语言)语句之一。与 DELETE 命令不同,UPDATE 命令根据条件更新或替换表记录。更新行时,它会在修改前锁定该行,并在更新完成后释放锁定。
SQL Server UPDATE 语句允许您借助 WHERE 子句中指定的条件更新单个或多个列。但是,您可以省略条件来更新整个表。
以下是一些我们可以使用 SQL Server UPDATE 语句的情况,但不仅限于此。
- 在插入记录时出现数据录入错误。
- 当前表数据不相关,您想用另一个最新源表更新它。
- 更新表中的非活动记录。
- 当您想根据表达式更新单个或多个行或列时。例如,更新黑色产品的价格、薪资上涨、最新技术或热门产品的投资更新。
SQL UPDATE 语句语法
UPDATE 语句的语法如下所示。
UPDATE [Table_Name]
SET [Column1] = [Value1],
[Column2] = [Value2],
[ColumnN] = [ValueN]
WHERE Condition
- 在这里,UPDATE 关键字通知服务器您要修改/更新某个记录。
- Column1…ColumnN: 您要更改的列名。
- Value1…ValueN:提供列的新值。
- SET 关键字将新值分配给列。
- WHERE Condition:在这里,我们必须提供筛选器或条件。如果条件为 TRUE,则查询才会更新记录。
注意: 如果您缺少 WHERE 子句,它将更新表中给定列的所有行。
以下一系列示例将帮助您理解 SQL Server UPDATE 语句在单列/多列以及带/不带 WHERE 子句的情况。此外,还包括如何将 UPDATE 与 LIKE、JOIN、OUTPUT 子句等结合使用。为了演示所有这些,我们使用以下查询创建了两个简单的表。我们将主要使用 employee 表来执行不同类型的更新操作。
CREATE TABLE department (
Dept_id INT PRIMARY KEY,
DepartmentName VARCHAR(100) NOT NULL
);
CREATE TABLE employee (
id INT IDENTITY(1,1) PRIMARY KEY,
Name VARCHAR(100) NOT NULL,
Education VARCHAR(100),
HireDate DATE,
Salary MONEY,
Sales MONEY,
Dept_id INT,
FOREIGN KEY (Dept_id) REFERENCES department(Dept_id)
);
INSERT INTO department VALUES (1, 'Sales');
INSERT INTO department VALUES (2, 'Manager');
INSERT INTO department VALUES (3, 'HR');
INSERT INTO employee VALUES ('John', 'Masters Degree', '2009-01-14', 2000000, 5000, 1);
INSERT INTO employee VALUES ('Bruce', 'Degree','2008-01-31', 800000, 7000, 1);
INSERT INTO employee VALUES ('Teddy', 'B.Tech', '2007-12-05',1500000, 10000, 2);
INSERT INTO employee VALUES ('Julie', 'B.Tech', '2010-12-06', 1200000, 0, 3);
INSERT INTO employee VALUES ('Tracy', 'Partial High School', '2012-05-30', 500000, 2000, 1);
在单列上执行 SQL UPDATE 语句
在使用 UPDATE 语句时,WHERE 子句起着至关重要的作用。在接下来的部分中,我们将讨论其缺失的后果,但目前,我们将使用它。
最常见的场景之一是根据特定条件更新单个记录。例如,更新员工的年龄、客户地址或电子邮件 ID 等。以下查询将把名为 Tracy 的员工的 Education 从“部分高中”更新为“学位”。
UPDATE employee
SET Education = 'Degree'
WHERE Name = 'Tracy'
请参阅下表以查看更改。
更新多条记录
此外,您可以使用 SQL UPDATE 语句更改单列中的多行。例如,我们想为拥有技术学士学位的员工增加 25000 薪水。在这种情况下,以下查询将更新所有拥有“学士学位”的员工的薪水。
UPDATE employee
SET Salary = Salary + 25000
WHERE Education = 'B.Tech'
每次 UPDATE 语句执行后,使用以下查询查看更改后 employee 表中的数据。
SELECT * FROM employee
结果是
| id | 姓名 | 教育 | 入职日期 | 薪水 | 销售额 | 部门 ID |
|---|---|---|---|---|---|---|
| 1 | 约翰 | 硕士学位 | 2009-01-14 | 2000000.00 | 5000.00 | 1 |
| 2 | 布鲁斯 | 学位 | 2008-01-31 | 800000.00 | 7000.00 | 1 |
| 3 | 泰迪 | 工学学士 | 2007-12-05 | 1525000.00 | 10000.00 | 2 |
| 4 | 朱莉 | 工学学士 | 2010-12-06 | 1225000.00 | 0.00 | 3 |
| 5 | 特蕾西 | 学位 | 2012-05-30 | 500000.00 | 2000.00 | 1 |
提示: 在更新任何记录之前,请务必理解表设计;否则,您将遇到错误。例如,更新身份列、主键列、向非空列添加 NULL 值等。
在多列上执行 SQL UPDATE 语句
在上面的示例中,我们使用 WHERE 子句更新单个列中的记录或行。但是,您可以使用 UPDATE 语句和 WHERE 子句的组合,通过单个语句修改多个列。例如,同时更改新调动员工的部门名称和经理名称。
注意: 在单个 UPDATE 语句中更新多个列时,我们必须使用逗号分隔这些列。
在此示例中,我们将为员工 ID 为 4 的员工更新薪水,在现有金额上增加 15000,并将销售额设置为 100。
UPDATE employee
SET Salary = Salary + 15000, Sales = 100
WHERE id = 4
--WHERE Name = 'Julie'
从下表中可以看到,ID 号 4 的薪水和销售额已更新。
更新多行和多列
想象一下,您想更新属于学位教育的员工的销售额和薪水。这意味着我们想使用单个 UPDATE 语句同时更新多个列和行。
以下查询将为拥有学位证书的员工的薪水增加 77000,销售额增加 250。
UPDATE employee
SET Salary = Salary + 77000, Sales = Sales + 250
WHERE Education = 'Degree'
带有表达式的 SQL UPDATE 语句
这是另一个示例,我们希望将 B.Tech 员工的薪水提高 20%。
UPDATE employee
SET Salary = Salary * 1.20
WHERE Education = 'B.Tech'
结果是
| id | 姓名 | 教育 | 入职日期 | 薪水 | 销售额 | 部门 ID |
|---|---|---|---|---|---|---|
| 1 | 约翰 | 硕士学位 | 2009-01-14 | 2000000.00 | 5000.00 | 1 |
| 2 | 布鲁斯 | 学位 | 2008-01-31 | 877000.00 | 7250.00 | 1 |
| 3 | 泰迪 | 工学学士 | 2007-12-05 | 1830000.00 | 10000.00 | 2 |
| 4 | 朱莉 | 工学学士 | 2010-12-06 | 1488000.00 | 100.00 | 3 |
| 5 | 特蕾西 | 学位 | 2012-05-30 | 577000.00 | 2250.00 | 1 |
默认值
如果您的表具有默认值,并且您想使用默认信息更新列,则可以使用 UPDATE 语句。例如,有一个默认的教育信息为“高中”,并且您想更新特定的员工。
UPDATE employee
SET Education = DEFAULT
WHERE Name = 'Bruce'
使用 TOP 子句更新
我们可以使用 SQL UPDATE 语句和 TOP 子句的组合来修改前 n 条或百分比的行。例如,如果您想为前 20 名员工(根据他们对组织的承诺)的工资增加 50%。
UPDATE TOP (20) employee
SET Salary = Salary * 1.50
使用 DATETIME 函数的 SQL UPDATE 语句
除了常规列,您还可以使用 UPDATE 语句更新日期和时间列,或在 WHERE 条件中使用它们来更新常规列。例如,如果您想将特定产品的订单或发货日期更新为当前日期,您可以编写以下查询。
UPDATE products
SET ShippingDate = GETDATE()
WHERE productName = 'Mobile'
-- WHERE productid = 2
同样,您可以在 WHERE 条件中使用 日期和时间函数 来更新常规列。以下查询将为工作超过 15 年的员工的薪水增加 50%。
UPDATE employee
SET Salary = Salary + Salary * 0.50
WHERE DATEDIFF(year, HireDate, GETDATE()) > 15
输出
| id | 姓名 | 教育 | 入职日期 | 薪水 | 销售额 | 部门 ID |
|---|---|---|---|---|---|---|
| 1 | 约翰 | 硕士学位 | 2009-01-14 | 3000000.00 | 5000.00 | 1 |
| 2 | 布鲁斯 | 学位 | 2008-01-31 | 1315500.00 | 7250.00 | 1 |
| 3 | 泰迪 | 工学学士 | 2007-12-05 | 2745000.00 | 10000.00 | 2 |
| 4 | 朱莉 | 工学学士 | 2010-12-06 | 1488000.00 | 100.00 | 3 |
| 5 | 特蕾西 | 学位 | 2012-05-30 | 577000.00 | 2250.00 | 1 |
不带 WHERE 子句的 SQL UPDATE 语句
在我们之前的示例中,我们展示了在 UPDATE 语句中使用 WHERE 子句的重要性。如果您不小心或故意想删除 WHERE 条件,UPDATE 语句将修改给定列中存在的所有行。这就像一个完整的表更新,这在大多数情况下可能并非如此。
尽管它有自己的缺点,但首先,让我向您展示不带 WHERE 条件的 UPDATE 语句的主要目的。假设政府已将所有商品和服务(或任何特定商品)的某些税值提高到 0.5%。然后我们可以使用此语句将这些值更改为新值。或者您想提高商品价格,那么您可以使用它。
假设一家公司已经盈利,并希望将组织中所有员工的工资提高 10%。在这种情况下,您编写以下查询以将工资提高 10%。
UPDATE employee SET Salary = Salary + Salary * 0.10
上面提到的例子是特例,但在大多数情况下,在 UPDATE 语句中省略 WHERE 子句是一场灾难。例如,下面的查询会将所有员工的工资更新为 900000,这是一个错误。所以,请务必小心条件。
UPDATE employee SET Salary = 900000
这里,我们没有指定 WHERE 条件。这就是为什么服务器更改了所有六条记录。
带有子查询的 SQL UPDATE 语句
在执行正常修改时,用户可以提供所需的值。但是,在某些情况下,我们必须将子查询与 UPDATE 语句一起使用,以根据 子查询 返回的结果修改现有值。
想象一下,您想增加销售额最高的员工的工资,即高于平均水平的员工。在这种情况下,使用子查询查找员工的平均销售额。接下来,主 UPDATE 语句查询中的 WHERE 子句会通过增加 25% 的奖金来修改这些员工的工资。
UPDATE employee SET Salary = Salary + Salary * 0.25 WHERE Sales > (SELECT AVG(Sales) FROM employee)
结果表是
| id | 姓名 | 教育 | 入职日期 | 薪水 | 销售额 | 部门 ID |
|---|---|---|---|---|---|---|
| 1 | 约翰 | 硕士学位 | 2009-01-14 | 1125000.00 | 5000.00 | 1 |
| 2 | 布鲁斯 | 学位 | 2008-01-31 | 1125000.00 | 7250.00 | 1 |
| 3 | 泰迪 | 工学学士 | 2007-12-05 | 1125000.00 | 10000.00 | 2 |
| 4 | 朱莉 | 工学学士 | 2010-12-06 | 900000.00 | 100.00 | 3 |
| 5 | 特蕾西 | 学位 | 2012-05-30 | 900000.00 | 2250.00 | 1 |
如何从另一个表更新表数据?
如果您查看上述查询的输出,所有员工的工资都已更改为 90000,并且教育和销售额也发生了一些变化。在这里,我们想使用备份表更新工资列。
使用 SQL Server UPDATE 语句从第二个表的数据修改第一个表的记录的基本语法如下所示。
UPDATE [Table1] SET [Column1] = (SELECT expression/Column FROM Table2 WHERE Condition) WHERE Condition
在此示例中,我们展示了如何使用来自另一个 emp 表的记录来更新表数据。在这里,我们使用另一个 emp 表的数据刷新了 employee 表中的记录。
UPDATE employee SET Salary = (SELECT Salary FROM emp WHERE employee.id = emp.id)
如果遇到表有新列,并且需要从另一个表更新信息的情况。在这种情况下,您可以使用上述技术或 JOIN。例如,让我修改表并添加一个新列以输入部门名称。
ALTER TABLE employee ADD Department VARCHAR(100) NULL
下面的查询使用 Dept_id 作为两个表之间的公共列,并使用另一个表中的值更新 Department 列。请注意 WHERE 条件,如果您将 Dept_Id 替换为 id(即员工 id),结果将是一个大错误。
UPDATE employee SET Department = ( SELECT DepartmentName FROM department WHERE employee.[Dept_id] = department.[Dept_id] )
带有 JOIN 的 SQL UPDATE 语句
我们将采用之前提到的相同示例来演示 JOIN 函数与 UPDATE 语句的结合。在这里,我们将使用部门表更新新创建的部门列。这比上一个方法更好。
UPDATE employee SET employee.Department = d.DepartmentName FROM employee e JOIN department d ON e.Dept_id = d.Dept_id
结果是
| id | 姓名 | 教育 | 入职日期 | 薪水 | 销售额 | 部门 ID | 部门 |
|---|---|---|---|---|---|---|---|
| 1 | 约翰 | 硕士学位 | 2009-01-14 | 2000000.00 | 5000.00 | 1 | 销售额 |
| 2 | 布鲁斯 | 学位 | 2008-01-31 | 800000.00 | 7250.00 | 1 | 销售额 |
| 3 | 泰迪 | 工学学士 | 2007-12-05 | 1500000.00 | 10000.00 | 2 | 经理 |
| 4 | 朱莉 | 工学学士 | 2010-12-06 | 1200000.00 | 100.00 | 3 | 人力资源 |
| 5 | 特蕾西 | 学位 | 2012-05-30 | 500000.00 | 2250.00 | 1 | 销售额 |
为了演示同样的效果,在使用上述查询之前,请使用下面的查询将 Department 更新为 NULL 值。然后,编写上述查询进行测试。
UPDATE employee
SET Department = NULL
执行完成后,使用以下查询删除新创建的列。
ALTER TABLE employee
DROP COLUMN Department
在上一节中,我们使用查询更新了员工的薪水。但是,我们还必须更新教育和销售额,才能将表恢复到原始位置。在这种情况下,您可以使用备份表作为 JOIN 参考,并使用旧值更新员工表。
UPDATE employee
SET employee.Education = emp.Education,
employee.Salary = emp.Salary,
employee.Sales = emp.Sales
FROM employee e JOIN emp ON e.id = emp.id
结合 LIKE 运算符使用 UPDATE
SQL Server UPDATE 语句允许您使用 LIKE 运算符根据通配符搜索执行修改。例如,以下 LIKE 查询将更新所有名称以 T 开头的员工的薪水和销售额。
UPDATE employee
SET Sales = 20000,
Salary = Salary + 29000
WHERE Name LIKE 'T%'
结果集
| id | 姓名 | 教育 | 入职日期 | 薪水 | 销售额 | 部门 ID |
|---|---|---|---|---|---|---|
| 1 | 约翰 | 硕士学位 | 2009-01-14 | 2000000.00 | 5000.00 | 1 |
| 2 | 布鲁斯 | 学位 | 2008-01-31 | 800000.00 | 7000.00 | 1 |
| 3 | 泰迪 | 工学学士 | 2007-12-05 | 1529000.00 | 20000.00 | 2 |
| 4 | 朱莉 | 工学学士 | 2010-12-06 | 1200000.00 | 0.00 | 3 |
| 5 | 特蕾西 | 部分高中 | 2012-05-30 | 529000.00 | 20000.00 | 1 |
SQL UPDATE 语句存储过程
在此示例中,我们在 存储过程 中使用 UPDATE 语句。尽管有多个带有输入参数的示例,但我们将使用一个简单的示例。在这里,存储过程中的 UPDATE 语句检查每个员工的销售额是否低于平均值。如果为真,它将通过减少 5% 来更改员工的薪水。
IF OBJECT_ID ( 'sp_Example', 'P' ) IS NOT NULL
DROP PROCEDURE sp_Example;
GO
CREATE PROCEDURE sp_Example
AS
BEGIN
SET NOCOUNT ON;
UPDATE employee
SET Salary = Salary - Salary * 0.05
WHERE Sales < (SELECT AVG(Sales) FROM employee)
END
GO
如果您运行上述查询,它将显示以下消息。
Messages
-------
Command(s) completed successfully.
让我使用 EXEC 命令(执行命令)来执行 UPDATE 存储过程
EXEC dbo.sp_Example
现在,让我们看看存储过程的执行是否改变了姓氏和职业
SELECT * FROM employee
带 OUTPUT 子句的 SQL UPDATE 语句
微软提供了一个很棒的 OUTPUT 子句概念。当您将 OUTPUT 子句与 UPDATE 语句一起使用时,查询不仅会更改记录,还会返回更改的信息和受影响的行。它为查询执行者提供了有价值的信息,以准确了解发生了什么。
以下查询将为所有拥有学士或硕士学位的员工的销售额增加 5000。
UPDATE employee
SET Sales = Sales + 5000
OUTPUT INSERTED.id, INSERTED.Name, INSERTED.Education, INSERTED.Sales
WHERE Education LIKE '%D%'
上述查询中的 OUTPUT 子句将返回员工 ID、姓名、教育程度和销售信息作为结果。
| id | 姓名 | 教育 | 销售额 |
|---|---|---|---|
| 1 | 约翰 | 硕士学位 | 10000.00 |
| 2 | 布鲁斯 | 学位 | 12000.00 |
OUTPUT 语句之后的最终结果是
| id | 姓名 | 教育 | 入职日期 | 薪水 | 销售额 | 部门 ID |
|---|---|---|---|---|---|---|
| 1 | 约翰 | 硕士学位 | 2009-01-14 | 1900000.00 | 10000.00 | 1 |
| 2 | 布鲁斯 | 学位 | 2008-01-31 | 760000.00 | 12000.00 | 1 |
| 3 | 泰迪 | 工学学士 | 2007-12-05 | 1529000.00 | 20000.00 | 2 |
| 4 | 朱莉 | 工学学士 | 2010-12-06 | 1140000.00 | 0.00 | 3 |
| 5 | 特蕾西 | 部分高中 | 2012-05-30 | 529000.00 | 20000.00 | 1 |
使用 Management Studio 的 SQL Server UPDATE 语句
如果您可以访问 Management Studio,请使用 Intellisense 生成 UPDATE 语句。为此,右键单击表,然后选择“脚本表为 -> UPDATE TO -> 新查询编辑器窗口”。
选择“新查询编辑器窗口”选项后,它将生成以下语句查询。如您所见,它显示了所有列名及其将接受的数据类型。您所要做的就是用所需的值替换 < > 中的文本并修改 where 条件。
Management Studio 生成的代码是
UPDATE [dbo].[employee]
SET [Name] = <Name, varchar(100),>
,[Education] = <Education, varchar(100),>
,[HireDate] = <HireDate, date,>
,[Salary] = <Salary, money,>
,[Sales] = <Sales, money,>
,[Dept_id] = <Dept_id, int,>
WHERE <Search Conditions,,>
您可以使用上述任何示例来检查此代码。
选项 2:编辑前 200 行
有一个名为“编辑前 200 行”的选项。右键单击表并选择“编辑前 200 行”选项。您可以根据需要更新值,但限制为 200 行。
SQL UPDATE 语句最佳实践
- 在执行 UPDATE 语句之前,始终备份表(数据)。
- 使用 WHERE 子句避免更新表中的所有记录。在 WHERE 子句中使用索引列以提高查询性能。
- 在更新任何记录之前,使用 SELECT 语句 检查我们是否要修改它。
- 将完整的 UPDATE 语句插入 BEGIN 和 END 事务 中,以根据要求提交或回滚整个过程。
- 使用 TRY CATCH 块处理错误。