在 SQL Server(以及大多数数据库)中,存储过程(Stored Procedure)和函数(Function)都是用来封装 SQL 逻辑的对象,但它们在用途、特性和限制上有明显的区别。
区别总结
1. 返回值
- 存储过程:可以返回 0 个或多个结果集,可以通过
OUTPUT
参数返回值,也可以用RETURN
返回一个整数。 - 函数:必须 返回一个值(标量值、表值或标量表函数),不能返回多个结果集。
2. 调用方式
- 存储过程:使用
EXEC
或EXECUTE
调用。EXEC usp_GetUsers @Status = 'Active';
- 函数:可以在 SQL 语句里直接调用,如
SELECT
、WHERE
、JOIN
等。SELECT dbo.fn_GetUserName(1);
3. 是否可以在 SQL 语句中使用
- 存储过程:不能在
SELECT
或WHERE
中使用。 - 函数:可以在 SQL 语句中使用,像内置函数(
LEN()
,GETDATE()
)一样。
4. 事务控制
- 存储过程:可以在其中 使用事务控制语句(
BEGIN TRAN
,COMMIT
,ROLLBACK
)。 - 函数:不允许显式事务控制。
5. 是否允许副作用(修改数据)
- 存储过程:可以执行
INSERT
、UPDATE
、DELETE
、MERGE
等 DML 操作。 - 函数:标量函数中通常 不允许修改数据库数据,表值函数返回的只是查询结果集。
6. 错误处理
- 存储过程:支持
TRY...CATCH
错误处理。 - 函数:不支持
TRY...CATCH
,错误处理能力有限。
7. 编译与性能
- 存储过程:通常会被编译并缓存执行计划,适合复杂的业务逻辑和批量处理。
- 函数:适合封装计算逻辑或可复用的查询片段,但过度使用标量函数可能导致性能下降。
对比表
特性 | 存储过程(Stored Procedure) | 函数(Function) |
---|---|---|
返回值 | 可无返回值,可返回多个结果集 | 必须返回值(标量/表) |
调用方式 | EXEC | SELECT dbo.fn() |
SQL语句中使用 | ❌ 不可直接用 | ✅ 可在 SELECT、WHERE、JOIN 中使用 |
修改数据 | ✅ 允许 | ❌ 一般不允许 |
事务控制 | ✅ 支持 | ❌ 不支持 |
错误处理 | ✅ TRY…CATCH | ❌ 不支持 |
适用场景 | 复杂逻辑、批量处理 | 封装计算逻辑、复用查询 |
一句话总结:
- 存储过程 更像是 任务执行器(可操作数据、事务处理),
- 函数 更像是 工具函数(返回计算或查询结果,可嵌入 SQL 使用)。