SQL 存储过程与函数教程

13次阅读

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

SQL 存储过程与函数教程

SQL 存储过程和函数不是“学完就能用”的东西,关键看你要解决什么问题——需要改变数据就用存储过程,需要返回单个值参与查询就用函数;混用或强行替换,八成会踩权限、事务或性能坑。

什么时候必须用 CREATE PROCEDURE 而不是 CREATE FUNCTION

核心判断标准:是否执行写操作(INSERTUPDATEDELETE)或调用其他写操作逻辑。

  • CREATE FUNCTION 在大多数数据库(如 MySQL 8.0+、PostgreSQL)中禁止修改表,否则直接报错 Invalid function definition: Cannot modify a table in a function
  • 事务控制只在存储过程中有效:START TRANSACTIONROLLBACK 这些语句不能出现在函数体内
  • 如果你要批量导入日志、更新用户状态并记录审计时间戳,只能走 CREATE PROCEDURE
  • 函数适合做计算封装,比如把 user_id 转成脱敏手机号,这种纯读 + 计算的场景才该用 CREATE FUNCTION

RETURNSELECT 在函数里的行为差异

MySQL 和 PostgreSQL 对函数返回机制处理完全不同,不注意会返回空或报错。

  • 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

存储过程里传参用 INOUT 还是 INOUT

不是语义区分,是调用方式和变量生命周期决定的。

  • IN 参数只进不出,过程内改了也不影响外部变量;适合传过滤条件、ID 等输入值
  • OUT 参数不传初始值,过程结束后才能读取,调用时得用变量接收:CALL proc_name(@result); SELECT @result;
  • INOUT 是两头都占,但要注意:MySQL 里它本质是传引用,如果过程里做了 SET param = NULL,外部变量也会变 NULL,不是副本
  • 别指望用 OUT 返回多行结果集——那是结果集本身的事,OUT 只能塞单个值

真正难的不是语法,是搞清哪一层该做什么事:函数不该碰数据,存储过程不该当计算工具,权限和事务边界划在哪,比怎么写更影响上线成败。

text=ZqhQzanResources