MsSql

关注公众号 jb51net

关闭
首页 > 数据库 > MsSql > SQLServer DML 操作

SQL Server DML 操作的项目实战

作者:半桶水专家

DML即数据操作语言,主要负责对表中的数据进行新增、修改、删除和合并,本文就来详细的介绍一下SQL Server DML 操作的项目实战,感兴趣的可以了解一下

数据定义(DDL)决定数据库长什么样,而数据操作(DML)决定数据库每天在做什么。 对于绝大多数业务系统来说,真正运行最频繁的不是 CREATE TABLE,而是 INSERT、UPDATE、DELETE 等 DML 操作。

本文将系统介绍 SQL Server 中最常用的 DML(Data Manipulation Language,数据操作语言)语句,包括 INSERT、UPDATE、DELETE、MERGE、OUTPUT 的使用方法、典型业务场景、性能优化技巧以及生产环境中的注意事项。

一、什么是 DML?

DML(Data Manipulation Language)即数据操作语言,主要负责对表中的数据进行新增、修改、删除和合并

SQL Server 中最核心的 DML 语句包括:

可以把数据库比作一本账本:

二、INSERT——新增数据

INSERT 用于向表中写入新数据。

基本语法

INSERT INTO 表名 (列1, 列2, ...)
VALUES (值1, 值2, ...);

场景一:插入单条用户数据

INSERT INTO Users
(
    UserName,
    Email,
    CreateTime
)
VALUES
(
    'Tom',
    'tom@test.com',
    GETDATE()
);

适用于:

场景二:一次插入多条数据

INSERT INTO Users
(
    UserName,
    Email
)
VALUES
('Alice','alice@test.com'),
('Bob','bob@test.com'),
('Jack','jack@test.com');

SQL Server 2008 起支持这种写法。

相比循环 INSERT,效率明显更高。

场景三:从查询结果插入

例如归档历史订单。

INSERT INTO OrderHistory
(
    OrderID,
    UserID,
    Amount
)
SELECT
    OrderID,
    UserID,
    Amount
FROM Orders
WHERE Status='Completed';

这种方式通常比程序循环导入快得多。

场景四:使用 DEFAULT

INSERT INTO Users
(
    UserName,
    Status
)
VALUES
(
    'Jerry',
    DEFAULT
);

要求字段定义了默认值。

例如:

Status INT DEFAULT 1

性能与注意事项

建议:

三、UPDATE——修改数据

UPDATE 用于修改已有记录。

基本语法

UPDATE 表名
SET 列=值
WHERE 条件;

场景一:修改用户手机号

UPDATE Users
SET Phone='13800001111'
WHERE UserID=1001;

场景二:订单批量修改状态

UPDATE Orders
SET Status='Completed'
WHERE PayStatus='Paid';

典型应用:

支付成功后更新订单状态。

场景三:基于 JOIN 更新

例如同步会员等级。

UPDATE U
SET U.LevelName=L.LevelName
FROM Users U
INNER JOIN UserLevel L
ON U.LevelID=L.LevelID;

这种 UPDATE 是 SQL Server 非常实用的扩展。

UPDATE 注意事项

务必带 WHERE 条件。

建议先执行:

SELECT *
FROM Orders
WHERE Status='Pending';

确认影响范围后再:

UPDATE Orders
SET Status='Processing'
WHERE Status='Pending';

这是 DBA 最基本的操作规范。

四、DELETE——删除数据

DELETE 删除的是数据,而不是表。

基本语法

DELETE
FROM 表名
WHERE 条件;

场景一:删除单个用户

DELETE
FROM Users
WHERE UserID=1001;

场景二:删除测试数据

DELETE
FROM Orders
WHERE UserID=-1;

很多开发环境都会保留这种测试账号。

场景三:删除过期日志

DELETE
FROM SystemLog
WHERE CreateTime < DATEADD(MONTH,-6,GETDATE());

这是日志清理最常见的方式。

DELETE 与 TRUNCATE 的区别

对比项DELETETRUNCATE
删除方式按行删除整表快速清空
WHERE支持不支持
日志较多较少
Identity不重置重置
触发器会触发不触发 DELETE Trigger

一般来说:

如果存在外键引用,TRUNCATE 通常无法执行。

五、MERGE——同步数据(UPSERT)

MERGE 可以一次完成:

因此也称 UPSERT

基本语法

MERGE Target AS T
USING Source AS S
ON T.ID=S.ID
WHEN MATCHED THEN
    UPDATE ...
WHEN NOT MATCHED THEN
    INSERT ...;

场景一:同步用户信息

MERGE Users AS T
USING TempUsers AS S
ON T.UserID=S.UserID

WHEN MATCHED THEN
UPDATE SET
    T.UserName=S.UserName,
    T.Email=S.Email

WHEN NOT MATCHED THEN
INSERT
(
    UserID,
    UserName,
    Email
)
VALUES
(
    S.UserID,
    S.UserName,
    S.Email
);

非常适合:

场景二:同步商品库存

每天 ERP 导入库存:

MERGE ProductStock AS T
USING ImportStock AS S
ON T.ProductID=S.ProductID

WHEN MATCHED THEN
UPDATE SET
Stock=S.Stock

WHEN NOT MATCHED THEN
INSERT(ProductID,Stock)
VALUES(S.ProductID,S.Stock);

MERGE 注意事项

SQL Server 多个版本曾修复过 MERGE 的边界 Bug,生产环境建议:

六、OUTPUT——获取受影响的数据

很多人不知道,SQL Server 可以直接返回本次 DML 操作的数据。

INSERT OUTPUT

INSERT INTO Users
(
    UserName
)
OUTPUT INSERTED.UserID,
       INSERTED.UserName
VALUES
(
    'Lucy'
);

返回:

UserID
UserName

无需再次查询。

UPDATE OUTPUT

UPDATE Orders
SET Amount=Amount+100

OUTPUT
DELETED.Amount AS OldAmount,
INSERTED.Amount AS NewAmount

WHERE OrderID=10;

其中:

非常适合:

DELETE OUTPUT

DELETE
FROM Users

OUTPUT
DELETED.*

WHERE UserID=100;

删除前的数据可以直接保存到日志表。

七、事务管理:保证数据一致性

多个 DML 通常需要作为一个整体执行。

BEGIN TRAN;

UPDATE Account
SET Balance=Balance-100
WHERE UserID=1;

UPDATE Account
SET Balance=Balance+100
WHERE UserID=2;

COMMIT;

发生异常:

ROLLBACK;

最佳实践:

八、DML 最佳实践

1、先 SELECT,再 UPDATE/DELETE

SELECT *
FROM Orders
WHERE Status='Pending';

确认无误后再执行修改。

2、避免锁表

对于百万级数据:

不要:

DELETE FROM Orders;

建议:

WHILE 1=1
BEGIN
    DELETE TOP (5000)
    FROM Orders
    WHERE CreateTime<'2023-01-01';

    IF @@ROWCOUNT=0 BREAK;
END

批量删除能够有效减少锁竞争与事务日志压力。

3、合理建立索引

WHERE 条件字段建议建立索引。

否则:

UPDATE、DELETE 很容易全表扫描。

4、批量导入优化

对于海量数据:

九、常见陷阱

1、忘记 WHERE

UPDATE Users
SET Status=0;

整个用户表都会被修改。

这是数据库事故中最常见的问题之一。

2、隐式类型转换

例如:

WHERE UserID='100'

如果 UserID 为 INT,SQL Server 可能发生隐式转换,影响索引使用,导致性能下降。

建议保持参数类型与字段类型一致。

3、NULL 判断错误

错误写法:

WHERE Email=NULL

正确写法:

WHERE Email IS NULL

同样:

IS NOT NULL

而不是:

!= NULL

4、外键约束

例如:

Orders

引用

Users

删除用户:

DELETE FROM Users
WHERE UserID=1;

如果订单仍存在,将提示外键冲突。

应:

十、综合案例:订单同步与归档

假设每天凌晨需要同步外部订单,并归档已完成订单。

第一步:同步新增和更新订单

MERGE Orders AS T
USING ImportOrders AS S
ON T.OrderID = S.OrderID
WHEN MATCHED THEN
    UPDATE SET
        T.Amount = S.Amount,
        T.Status = S.Status
WHEN NOT MATCHED THEN
    INSERT (OrderID, UserID, Amount, Status)
    VALUES (S.OrderID, S.UserID, S.Amount, S.Status);

第二步:记录变更日志

UPDATE Orders
SET Status = 'Archived'
OUTPUT
    INSERTED.OrderID,
    DELETED.Status,
    INSERTED.Status,
    GETDATE()
INTO OrderChangeLog
WHERE Status = 'Completed';

第三步:归档历史数据

INSERT INTO OrderHistory
SELECT *
FROM Orders
WHERE Status='Archived';

DELETE
FROM Orders
WHERE Status='Archived';

整个流程建议放入事务中执行,并结合适当索引,确保同步、日志记录和归档的一致性。

十一、SQL Server 版本差异

不同版本对 DML 能力持续增强:

总结

DML 是数据库开发中使用频率最高的一组 SQL 语句,也是最容易因为误操作而引发生产事故的部分。掌握 INSERT、UPDATE、DELETE、MERGE 与 OUTPUT 的正确使用方式,不仅能够完成日常的数据维护工作,更能编写出安全、高效、易维护的数据处理程序。

最后,牢记几条经验法则:

到此这篇关于SQL Server DML 操作的项目实战的文章就介绍到这了,更多相关SQLServer DML 操作内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

您可能感兴趣的文章:
阅读全文