一、基本概念
1. 函数 (Function)
定义: 完成特定功能、有返回值的数据库对象
特点:
必须有返回值 (单个值或表)
可以在 SQL 语句中直接调用
通常用于计算和转换数据
不能有副作用(不能修改数据库状态)
sql
-- 示例:标量函数(返回单个值)
CREATE FUNCTION dbo.GetEmployeeName(@EmpID INT)
RETURNS VARCHAR(100)
AS
BEGIN
DECLARE @Name VARCHAR(100);
SELECT @Name = Name FROM Employees WHERE EmpID = @EmpID;
RETURN @Name;
END;
-- 使用
SELECT dbo.GetEmployeeName(1001);
-- 示例:表值函数(返回表)
CREATE FUNCTION dbo.GetEmployeesByDept(@DeptID INT)
RETURNS TABLE
AS
RETURN (
SELECT * FROM Employees WHERE DeptID = @DeptID
);
2. 存储过程 (Stored Procedure)
定义:预编译的 SQL 代码块 ,可包含复杂的业务逻辑
特点:
可以没有返回值 ,也可以有多个返回值 (通过 OUTPUT 参数)
不能在 SQL 语句中直接调用(使用 EXEC 执行)
可以修改数据库状态 (INSERT、UPDATE、DELETE)
支持复杂的事务处理和错误处理
性能更好(预编译)
sql
-- 示例:存储过程
CREATE PROCEDURE sp_UpdateEmployeeSalary
@EmpID INT,
@IncreasePercent DECIMAL(5,2),
@NewSalary DECIMAL(10,2) OUTPUT
AS
BEGIN
BEGIN TRANSACTION;
TRY
UPDATE Employees
SET Salary = Salary * (1 + @IncreasePercent/100)
WHERE EmpID = @EmpID;
SELECT @NewSalary = Salary FROM Employees WHERE EmpID = @EmpID;
COMMIT TRANSACTION;
END TRY
BEGIN CATCH
ROLLBACK TRANSACTION;
THROW;
END CATCH;
END;
-- 使用
DECLARE @NewSal DECIMAL(10,2);
EXEC sp_UpdateEmployeeSalary 1001, 10, @NewSal OUTPUT;
3. 聚集/聚合函数 (Aggregate Function)
定义 :对一组值进行计算 并返回单个值 的函数
特点 :
内置函数 (SUM、AVG、COUNT、MAX、MIN 等)
通常与 GROUP BY 一起使用
对多行数据进行聚合计算
返回单个汇总值
sql
-- 示例:聚合函数
SELECT
DeptID,
COUNT(*) AS EmployeeCount, -- 计数
AVG(Salary) AS AvgSalary, -- 平均
SUM(Salary) AS TotalSalary, -- 求和
MAX(Salary) AS MaxSalary, -- 最大
MIN(Salary) AS MinSalary -- 最小
FROM Employees
GROUP BY DeptID;
二、主要区别

三、联系与共同点
1. 都是数据库对象
都存储在数据库中
都可以重复使用
都能提高代码复用性
2. 都能封装逻辑
sql
-- 函数封装计算逻辑
CREATE FUNCTION dbo.CalculateTax(@Amount DECIMAL)
RETURNS DECIMAL
AS BEGIN
RETURN @Amount * 0.13;
END;
-- 存储过程封装业务流程
CREATE PROCEDURE sp_ProcessOrder
@OrderID INT
AS
BEGIN
-- 检查库存
-- 更新订单状态
-- 扣减库存
-- 记录日志
END;
-- 聚合函数封装统计逻辑
SELECT AVG(Salary) FROM Employees; -- 封装了求平均的逻辑
3. 都可以带参数
sql
-- 函数参数
SELECT dbo.GetEmployeeName(1001);
-- 存储过程参数
EXEC sp_UpdateSalary 1001, 10;
-- 聚合函数(隐式参数)
SELECT AVG(Salary) -- Salary 是隐式参数
4. 可以组合使用
sql
-- 在存储过程中使用函数和聚合函数
CREATE PROCEDURE sp_DepartmentStats
@DeptID INT
AS
BEGIN
DECLARE @AvgSalary DECIMAL;
-- 使用聚合函数
SELECT @AvgSalary = AVG(Salary)
FROM Employees
WHERE DeptID = @DeptID;
-- 使用自定义函数
SELECT
EmpID,
Name,
dbo.CalculateTax(Salary) AS Tax
FROM Employees
WHERE DeptID = @DeptID;
END;
四、使用场景建议
✅ 使用函数的场景
需要在查询中计算或转换数据
需要返回单个值或表
逻辑相对简单,无副作用
✅ 使用存储过程的场景
复杂的业务流程
需要事务控制
需要批量处理数据
需要错误处理
多个相关操作需要一起执行
✅ 使用聚合函数的场景
统计分析
报表生成
数据汇总
GROUP BY 分组计算
五、实际例子对比
sql
-- 1. 函数:计算员工年龄
CREATE FUNCTION dbo.CalculateAge(@BirthDate DATE)
RETURNS INT
AS
BEGIN
RETURN DATEDIFF(YEAR, @BirthDate, GETDATE());
END;
-- 2. 存储过程:处理员工晋升
CREATE PROCEDURE sp_PromoteEmployee
@EmpID INT,
@NewPosition VARCHAR(50)
AS
BEGIN
BEGIN TRANSACTION;
UPDATE Employees
SET Position = @NewPosition,
Salary = Salary * 1.2,
PromoteDate = GETDATE()
WHERE EmpID = @EmpID;
INSERT INTO PromotionHistory (EmpID, NewPosition, PromoteDate)
VALUES (@EmpID, @NewPosition, GETDATE());
COMMIT TRANSACTION;
END;
-- 3. 聚合函数:统计部门信息
SELECT
d.DeptName,
COUNT(e.EmpID) AS EmpCount, -- 聚合:计数
AVG(dbo.CalculateAge(e.BirthDate)) AS AvgAge, -- 聚合 + 函数
SUM(e.Salary) AS TotalBudget -- 聚合:求和
FROM Departments d
LEFT JOIN Employees e ON d.DeptID = e.DeptID
GROUP BY d.DeptName;