必须用create procedure而非create function的核心判断标准是执行写操作(insert、update、delete)或调用其他写操作逻辑,因函数禁止修改表且不支持事务控制。

SQL 存储过程和函数不是“学完就能用”的东西,关键看你要解决什么问题——需要改变数据就用存储过程,需要返回单个值参与查询就用函数;混用或强行替换,八成会踩权限、事务或性能坑。
什么时候必须用 CREATE PROCEDURE 而不是 CREATE FUNCTION
核心判断标准:是否执行写操作(INSERT、UPDATE、DELETE)或调用其他写操作逻辑。
-
CREATE FUNCTION在大多数数据库(如 MySQL 8.0+、PostgreSQL)中禁止修改表,否则直接报错Invalid function definition: Cannot modify a table in a function - 事务控制只在存储过程中有效:
START TRANSACTION、ROLLBACK这些语句不能出现在函数体内 - 如果你要批量导入日志、更新用户状态并记录审计时间戳,只能走
CREATE PROCEDURE - 函数适合做计算封装,比如把
user_id转成脱敏手机号,这种纯读+计算的场景才该用CREATE FUNCTION
RETURN 和 SELECT 在函数里的行为差异
MySQL 和 PostgreSQL 对函数返回机制处理完全不同,不注意会返回空或报错。
使用模板与程序分离的方式构建,依靠专门设计的数据库操作类实现数据库存取,具有专有错误处理模块,通过 Email 实时报告数据库错误,除具有满足购物需要的全部功能外,成新商城购物系统还对购物系统体系做了丰富的扩展,全新设计的搜索功能,自定义成新商城购物系统代码功能代码已经全面优化,杜绝SQL注入漏洞前台测试用户名:admin密码:admin888后台管理员名:admin密码:admin888
- MySQL 函数必须用
RETURN返回单个标量值,写SELECT ...不报错但不输出结果,调用时像SELECT my_func(123)才能拿到值 - PostgreSQL 函数可以声明为
RETURNS TABLE(...),这时函数体里用RETURN QUERY SELECT ...,调用方式变成SELECT * FROM my_func(123) - 别在 MySQL 函数里写
SELECT @var := col FROM t想间接返回——变量赋值不等于函数返回,调用结果仍是NULL
权限不足导致 CREATE FUNCTION 失败的常见原因
不是语法错,是账号缺特定全局权限,尤其在生产环境部署时突然卡住。
- MySQL 要求账号有
CREATE ROUTINE权限,且log_bin_trust_function_creators必须设为ON(否则主从复制可能中断) - PostgreSQL 要求对目标 schema 有
USAGE,且对函数语言(如plpgsql)有USAGE权限 - 函数里如果查了其他 schema 的表,调用者账号还得有对应
SELECT权限——函数不会继承定义者权限(除非显式加SECURITY DEFINER)
存储过程里传参用 IN、OUT 还是 INOUT?
不是语义区分,是调用方式和变量生命周期决定的。
-
IN参数只进不出,过程内改了也不影响外部变量;适合传过滤条件、ID 等输入值 -
OUT参数不传初始值,过程结束后才能读取,调用时得用变量接收:CALL proc_name(@result); SELECT @result; -
INOUT是两头都占,但要注意:MySQL 里它本质是传引用,如果过程里做了SET param = NULL,外部变量也会变NULL,不是副本 - 别指望用
OUT返回多行结果集——那是结果集本身的事,OUT只能塞单个值
真正难的不是语法,是搞清哪一层该做什么事:函数不该碰数据,存储过程不该当计算工具,权限和事务边界划在哪,比怎么写更影响上线成败。









