0

0

Mysql的Procedure 参数为NULL问题分析

高洛峰

高洛峰

发布时间:2016-12-02 14:48:26

|

1915人浏览过

|

来源于php中文网

原创

 最近写过程时发现一个有趣的事情,mysql 的procedure 在传参的过程中,遇到一些“非法”的参数是有自己独特的处理方式。例如本来定义是int的参数,结果被传入的是null
,mysql 的procedure会正常执行。
库表结构:
    create database db5;
 
use db5;
 
drop table if exists t;
create table t(
id int primary key auto_increment,
value int
);
 
create table t2(
id int primary key auto_increment,
value float
);
创建procedure:
   delimiter //
create procedure p14 (in parameter1 int)
begin
declare variable1 int;
set variable1 = parameter1 + 1;
insert into t(value) values (variable1);
end;
 //
delimiter ;
 
运行结果:
 
 
mysql> call p14(5);
query ok, 1 row affected (0.02 sec)
 
mysql> select * from t;
+----+-------+
| id | value |
+----+-------+
| 2 |     6 |
+----+-------+
1 row in set (0.00 sec)
 
mysql> call p14(null);
query ok, 1 row affected (0.04 sec)
 
mysql> select * from t;
+----+-------+
| id | value |
+----+-------+
| 2 |     6 |
| 3 | null |
+----+-------+
2 rows in set (0.00 sec)
 
 
大家注意到没有,当参数parameter1传入等于5时,表插入6,数据正常。
当参数parameter1传入为null时,表插入null,这是为什么呢。
 
关于这点大家可以看看声明变量的语句,文档给出了这样的解释:declare这个语句被用来声明局部变量。要给变量提供一个默认值,请包含一个default子句。值可以被指定为一个表达式,不需要为一个常数。如果没有default子句,初始值为null。
 
上面这样又有了一个新的问题:null=null+1?哈哈,有点意思了,此时的set variable1 = parameter1 + 1;会有一个怎样合理的解释呢?
 
这是王老师给的解释(第二条很经典呀~~~):
1 null+1=null
因为null表现为“类似指针”,也就是指向“0地址的内容”,如果这个内容为“null”,则表现为null。这就是指定int也为空的原因。但是,如果“内容”有值,则表现为不空,对于mysql而言,是个“随机数”或0;当这个地址内容存储时,值就固定了;
 
 
2 如果a=b+1,只有b为null时,a才为null;set a=b+1,是否可理解为set (b+1),a已经在‘当前’替换,这样a是谁不重要,重要的是b+1;
本想法没有验证,主要是分离不了set,而mysql5的文档,有支持这一说法,但英文版本是用“替换”,不是中文的“设置”表达,感觉意思更为接近!(set)
 
一个新的问题:当a=1/b,b=0时,也能运行成功吗?
 
mysql>
 
delimiter //
create procedure p15 (in parameter1 int)
begin
declare variable2 float(5,3);
 set variable2 =1/ parameter1;
 insert into t2(value) values (variable2);
end;
//
delimiter ;
 
执行结果:
 
mysql> call p15(0);
query ok, 1 row affected (0.03 sec)
 
mysql> select * from t2;
+----+-------+
| id | value |
+----+-------+
| 1 | null |
+----+-------+
1 row in set (0.00 sec)
 
mysql> call p15(1);
query ok, 1 row affected (0.03 sec)
 
mysql> select * from t2;
+----+-------+
| id | value |
+----+-------+
| 1 | null |
| 2 |     1 |
 
读者注意没有? 这个也能运行成功。其实这个问题在mysql的sql服务器模式参数细节中可以找到。
mysql服务器可以以不同的sql模式来操作,并且可以为不同客户端应用不同模式。这样每个应用程序可以根据自己的需求来定制服务器的操作模式。
模式定义mysql应支持哪些sql语法,以及应执行哪种数据验证检查。这样可以更容易地在不同的环境中使用mysql,并结合其它数据库服务器使用mysql。
你可以用--sql-mode="modes"选项启动mysqld来设置默认sql模式。如果你想要重设,该值还可以为空(--sql-mode ="")。
你还可以在启动后用set [session|global] sql_mode='modes'语句设置sql_mode变量来更改sql模式。设置 global变量时需要拥有super权限,并且会影响从那时起连接的所有客户端的操作。设置session变量只影响当前的客户端。任何客户端可以随时更改自己的会话 sql_mode值。
modesis是用逗号(‘,’)间隔开的一系列不同的模式。你可以用select @@sql_mode语句查询当前的模式。默认值是空(没有设置任何模式)。
strict_trans_tables
为所有存储引擎启用严格模式。非法数据值被拒绝。后面有详细说明。
· strict_trans_tables
为事务存储引擎启用严格模式,也可能为非事务存储引擎启用严格模式。后面有详细说明。
严格模式控制mysql如何处理非法或丢失的输入值。有几种原因可以使一个值为非法。例如,数据类型错误,不适合列,或超出范围。当新插入的行不包含某列的没有显示定义default子句的值,则该值被丢失。
对于事务表,当启用strict_all_tables或strict_trans_tables模式时,如果语句中有非法或丢失值,则会出现错误。语句被放弃并滚动。
对于非事务表,如果插入或更新的第1行出现坏值,两种模式的行为相同。语句被放弃,表保持不变。如果语句插入或修改多行,并且坏值出现在第2或后面的行,结果取决于启用了哪个严格选项:
error_for_division_by_zero
在严格模式,在insert或update过程中,如果被零除(或mod(x,0)),则产生错误(否则为警告)。如果未给出该模式,被零除时mysql返回null。如果用到insert ignore或update ignore中,mysql生成被零除警告,但操作结果为null。
还有些其他参数,读者可以参详mysql的文档。
 
当我们给sql_mode 中加入error_for_division_by_zero参数时,重启mysql
mysql> show variables like 'sql_mode';
+---------------+---------------------------------------------------------------
----------------------------+
| variable_name | value
                            |
+---------------+---------------------------------------------------------------
----------------------------+
| sql_mode      | strict_trans_tables,error_for_division_by_zero,no_auto_create_
user,no_engine_substitution |
+---------------+---------------------------------------------------------------
----------------------------+
1 row in set (0.00 sec)
 
mysql> select 1/0;
+------+
| 1/0 |
+------+
| null |
+------+
1 row in set, 1 warning (0.00 sec)
 
我们看到了1 warning,我们在看下这个warning:
mysql> show warnings;
+-------+------+---------------+
| level | code | message       |
+-------+------+---------------+
| error | 1365 | division by 0 |
+-------+------+---------------+
1 row in set (0.00 sec)
 
mysql> exit
bye
我们把sql_mode 中去掉error_for_division_by_zero参数时,重启mysql,试试看:
 
c:\documents and settings\administrator>net stop mysql
mysql 服务正在停止.
mysql 服务已成功停止。
 
 
c:\documents and settings\administrator>net start mysql
 
mysql 服务已经启动成功。
 
 
mysql> select 1/0;
+------+
| 1/0 |
+------+
| null |
+------+
1 row in set (0.00 sec)
 
mysql> show warnings;
empty set (0.02 sec)
这时warnings的内容为空。
问题到这里,读者也知道这是为什么了。有空再试试别的数据库,看看也是不是这样

热门AI工具

更多
DeepSeek
DeepSeek

幻方量化公司旗下的开源大模型平台

豆包大模型
豆包大模型

字节跳动自主研发的一系列大型语言模型

通义千问
通义千问

阿里巴巴推出的全能AI助手

腾讯元宝
腾讯元宝

腾讯混元平台推出的AI助手

文心一言
文心一言

文心一言是百度开发的AI聊天机器人,通过对话可以生成各种形式的内容。

讯飞写作
讯飞写作

基于讯飞星火大模型的AI写作工具,可以快速生成新闻稿件、品宣文案、工作总结、心得体会等各种文文稿

即梦AI
即梦AI

一站式AI创作平台,免费AI图片和视频生成。

ChatGPT
ChatGPT

最最强大的AI聊天机器人程序,ChatGPT不单是聊天机器人,还能进行撰写邮件、视频脚本、文案、翻译、代码等任务。

相关专题

更多
Python 序列化
Python 序列化

本专题整合了python序列化、反序列化相关内容,阅读专题下面的文章了解更多详细内容。

0

2026.02.02

AO3官网入口与中文阅读设置 AO3网页版使用与访问
AO3官网入口与中文阅读设置 AO3网页版使用与访问

本专题围绕 Archive of Our Own(AO3)官网入口展开,系统整理 AO3 最新可用官网地址、网页版访问方式、正确打开链接的方法,并详细讲解 AO3 中文界面设置、阅读语言切换及基础使用流程,帮助用户稳定访问 AO3 官网,高效完成中文阅读与作品浏览。

91

2026.02.02

主流快递单号查询入口 实时物流进度一站式追踪专题
主流快递单号查询入口 实时物流进度一站式追踪专题

本专题聚合极兔快递、京东快递、中通快递、圆通快递、韵达快递等主流物流平台的单号查询与运单追踪内容,重点解决单号查询、手机号查物流、官网入口直达、包裹进度实时追踪等高频问题,帮助用户快速获取最新物流状态,提升查件效率与使用体验。

27

2026.02.02

Golang WebAssembly(WASM)开发入门
Golang WebAssembly(WASM)开发入门

本专题系统讲解 Golang 在 WebAssembly(WASM)开发中的实践方法,涵盖 WASM 基础原理、Go 编译到 WASM 的流程、与 JavaScript 的交互方式、性能与体积优化,以及典型应用场景(如前端计算、跨平台模块)。帮助开发者掌握 Go 在新一代 Web 技术栈中的应用能力。

11

2026.02.02

PHP Swoole 高性能服务开发
PHP Swoole 高性能服务开发

本专题聚焦 PHP Swoole 扩展在高性能服务端开发中的应用,系统讲解协程模型、异步IO、TCP/HTTP/WebSocket服务器、进程与任务管理、常驻内存架构设计。通过实战案例,帮助开发者掌握 使用 PHP 构建高并发、低延迟服务端应用的工程化能力。

5

2026.02.02

Java JNI 与本地代码交互实战
Java JNI 与本地代码交互实战

本专题系统讲解 Java 通过 JNI 调用 C/C++ 本地代码的核心机制,涵盖 JNI 基本原理、数据类型映射、内存管理、异常处理、性能优化策略以及典型应用场景(如高性能计算、底层库封装)。通过实战示例,帮助开发者掌握 Java 与本地代码混合开发的完整流程。

5

2026.02.02

go语言 注释编码
go语言 注释编码

本专题整合了go语言注释、注释规范等等内容,阅读专题下面的文章了解更多详细内容。

62

2026.01.31

go语言 math包
go语言 math包

本专题整合了go语言math包相关内容,阅读专题下面的文章了解更多详细内容。

55

2026.01.31

go语言输入函数
go语言输入函数

本专题整合了go语言输入相关教程内容,阅读专题下面的文章了解更多详细内容。

27

2026.01.31

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
MySQL 教程
MySQL 教程

共48课时 | 2万人学习

MySQL 初学入门(mosh老师)
MySQL 初学入门(mosh老师)

共3课时 | 0.3万人学习

简单聊聊mysql8与网络通信
简单聊聊mysql8与网络通信

共1课时 | 820人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号