mysql自定义函数必须显式声明deterministic、no sql或reads sql data,否则报error 1418;pg中create or replace function不自动刷新依赖视图;sql server函数参数不支持getdate()默认值;各库return语法与null处理差异显著。

MySQL 中 CREATE FUNCTION 必须带 DETERMINISTIC 或其他特性声明
MySQL 严格要求自定义函数必须显式声明确定性行为,否则会报错 ERROR 1418 (HY000): This function has none of DETERMINISTIC, NO SQL, or READS SQL DATA。这不是可选提醒,是硬性校验。
原因在于 MySQL 的二进制日志(binlog)和主从复制机制需要预判函数是否可能产生非一致结果。即使函数逻辑上确实不访问数据、也不依赖时间,也得“签字画押”。
-
DETERMINISTIC:输入相同则输出一定相同(如字符串截取、数学计算) -
NO SQL:函数体内完全不包含任何 SQL 语句(最安全,推荐优先用) -
READS SQL DATA:只读查询,不修改数据(如SELECT COUNT(*) FROM users WHERE status = arg) - 避免用
MODIFIES SQL DATA——存储函数不允许写数据,要用请改用存储过程
示例:
CREATE FUNCTION get_month_name(m INT) RETURNS VARCHAR(10) NO SQL BEGIN RETURN CASE m WHEN 1 THEN 'Jan' WHEN 2 THEN 'Feb' ELSE 'N/A' END; END;
PostgreSQL 里 CREATE OR REPLACE FUNCTION 默认不自动更新依赖视图
在 PostgreSQL 中,用 CREATE OR REPLACE FUNCTION 修改函数体后,已存在的视图、物化视图或函数调用不会自动重编译。如果原函数返回字段名/类型变了,而视图仍按旧签名缓存结构,后续查视图就可能报 column does not exist 或类型不匹配错误。
这不是 bug,是 PG 的计划缓存优化策略。它把函数调用内联展开,一旦缓存生成,就不跟踪底层函数变更。
- 手动刷新依赖对象:对视图执行
CREATE OR REPLACE VIEW xxx AS ...重新定义一次 - 对物化视图:运行
REFRESH MATERIALIZED VIEW xxx - 开发期建议加注释说明:“此函数被 view_user_summary 依赖”,便于协作时意识到影响范围
- 避免在函数返回中使用
RECORD或未明确列定义的SETOF—— 这会让依赖更脆弱
SQL Server 函数不能用 GETDATE() 做默认参数值
SQL Server 的标量函数(CREATE FUNCTION)不支持像存储过程那样给参数设 GETDATE() 这类运行时函数作为默认值,否则会提示 Invalid use of a side-effecting operator 'getdate' within a function。
本书全面介绍PHP脚本语言和MySOL数据库这两种目前最流行的开源软件,主要包括PHP和MySQL基本概念、PHP扩展与应用库、日期和时间功能、PHP数据对象扩展、PHP的mysqli扩展、MySQL 5的存储例程、解发器和视图等。本书帮助读者学习PHP编程语言和MySQL数据库服务器的最佳实践,了解如何创建数据库驱动的动态Web应用程序。
根本原因是 SQL Server 要求函数必须是纯计算性的(deterministic),而 GETDATE() 每次调用结果不同,违反该约束;哪怕你没显式声明 WITH SCHEMABINDING,系统也会做隐式检查。
- 正确做法:把时间参数留空,调用方传入
GETDATE(),例如dbo.calc_age(@birth_date, GETDATE()) - 若真想封装,默认逻辑移到调用侧,或改用内联表值函数(ITVF),但 ITVF 本身也不能含非确定性函数
- 注意
SYSDATETIME()、NEWID()、NEWSEQUENTIALID()同样被禁止
跨数据库移植函数时,RETURN 语法和空值处理差异最大
看似一样的“返回一个值”,各数据库对 RETURN 的位置、类型推断、NULL 隐式转换规则完全不同。直接复制粘贴大概率报错或行为异常。
比如 MySQL 允许函数末尾省略 RETURN(返回 NULL),PostgreSQL 强制最后一行必须是 RETURN 表达式;SQL Server 要求标量函数必须有且仅有一个 RETURN 语句。
- MySQL:支持
RETURN NULL;,也接受函数体末尾无RETURN(返回NULL) - PostgreSQL:必须写
RETURN expr;,且类型需与声明的RETURNS严格一致,NULL::TEXT和NULL在某些上下文不等价 - SQL Server:不支持
RETURN NULL写法(除非声明为RETURNS INT且NULL可隐式转),必须显式写RETURN @val,且@val不能为空未赋值变量 - 统一建议:所有函数开头初始化返回变量(如
DECLARE @result VARCHAR(50) = NULL;),结尾统一RETURN @result;,减少歧义
函数不是写完就能跑通的黑盒——它的生命周期从创建那一刻起,就绑定了所在数据库的执行模型、日志策略和缓存机制。稍不留神,一个 NO SQL 漏写,或一次没刷新的视图,就会在上线后某个凌晨三点把你叫醒。









