[MySQL学习]STRICT_ALL_TABLES对应的OUT of RANGE VALUE FOR COLUMN和DATA truncated FOR COLUMN

昨天在存储过程中用了语句insert into a select from b。在应用中发现bigint字段插入到int字段的时候,数值被截断了,插入后已经不是所要的值。因为存储过程中没有用到异常捕捉的处理,所以一开始并未发现错误,只是在比对数据的时候才发现不对。后来比对了两张表,才发现是字段类型不一样。接下来就试着验证了一下(window下的测试环境)。

创建两张表

CREATE TABLE T_INT(id INT ,vname VARCHAR(20));
CREATE TABLE T_BIGINT(id BIGINT ,vname VARCHAR(40));

测试bigint插入到int:如果超过了int的最大值,则直接截成最大值power(2,31)-1。如果是直接在命令行下操作时,会有警告提示。

</pre><p></p><p></p><pre code_snippet_id="397037" snippet_file_name="blog_20140618_3_2598704" name="code" class="sql">INSERT INTO t_int(id,vname)VALUES(POWER(2,31),'0123456789abcdefghij');

SHOW WARNINGS;
1264 OUT of RANGE VALUE FOR COLUMN 'id' AT ROW 1;

SELECT * FROM t_int;
SELECT POWER(2,31)
2147483648
2147483647

测试varchar(40)插入到varchar(20):同样也会直接按照字段最大值截取,命令行下会有警告抛出。

INSERT INTO t_int(id,vname)VALUES(POWER(2,31),'0123456789abcdefghij1');
SHOW WARNINGS;
1264 OUT of RANGE VALUE FOR COLUMN 'id' AT ROW 1;
1265 DATA truncated FOR COLUMN 'vname' AT ROW 1;

id	vname
2147483647	0123456789abcdefghij
2147483647	0123456789abcdefghij

INSERT INTO T_BIGINT(id,vname)VALUES(POWER(2,31),'0123456789abcdefghij1');
INSERT INTO t_int SELECT * FROM t_bigint;

因为我用的是SQLyog,默认的模式是空,所以在这个上面调试的时候,就出问题了。在应用中出错,是因为我的url中没有指定客户端的sql_mode。

/*[17:15:32][  31 ms]*/ SHOW VARIABLES LIKE 'lower_case_table_names';
/*[17:15:32][   0 ms]*/ SET NAMES 'utf8';
/*[17:15:32][   0 ms]*/ SET sql_mode='';
/*[17:15:32][  16 ms]*/ SHOW DATABASES;

在cmd下直接连接MySQL是不会有问题,因为我已经在配置文件中配置了sql_mode。

mysql> INSERT INTO t_int(id,vname)VALUES(POWER(2,31),'0123456789abcdefghij');
ERROR 1264 (22003): Out of range value for column 'id' at row 1
mysql>
mysql> show variables like '%mode%';
+--------------------------+----------------------------------------------------
------------+
| Variable_name            | Value
            |
+--------------------------+----------------------------------------------------
------------+
| innodb_autoinc_lock_mode | 1
            |
| slave_exec_mode          | STRICT
            |
| sql_mode                 | STRICT_TRANS_TABLES,NO_AUTO_CREATE_USER,NO_ENGINE_S
UBSTITUTION |
+--------------------------+----------------------------------------------------
------------+
3 rows in set (0.00 sec)

mysql>

但是如果将insert语句封装到存储过程中,不会报错,只会有有警告。

mysql> call PRO_INSERT();
Query OK, 1 row affected, 3 warnings (0.01 sec)

mysql> select * from t_int;
+------------+----------------------+
| id         | vname                |
+------------+----------------------+
| 2147483647 | 0123456789abcdefghij |
| 2147483647 | 0123456789abcdefghij |
+------------+----------------------+
2 rows in set (0.00 sec)

mysql> set sql_mode='STRICT_ALL_TABLES';
Query OK, 0 rows affected (0.00 sec)

mysql> call PRO_INSERT();
Query OK, 1 row affected, 3 warnings (0.03 sec)

mysql> select * from t_int;
+------------+----------------------+
| id         | vname                |
+------------+----------------------+
| 2147483647 | 0123456789abcdefghij |
| 2147483647 | 0123456789abcdefghij |
| 2147483647 | 0123456789abcdefghij |
| 2147483647 | 0123456789abcdefghij |
+------------+----------------------+
4 rows in set (0.00 sec)

mysql> show variables like '%mode%';
+--------------------------+-------------------+
| Variable_name            | Value             |
+--------------------------+-------------------+
| innodb_autoinc_lock_mode | 1                 |
| slave_exec_mode          | STRICT            |
| sql_mode                 | STRICT_ALL_TABLES |
+--------------------------+-------------------+
3 rows in set (0.00 sec)

mysql>

出问题的原因就是因为sql_mode。还有就是我没有异常处理机制。下一篇先贴一下sql_mode.

解决方案,直接抛错。在存储过程中SET sql_mode=‘STRICT_TRANS_TABLES,NO_ENGINE_SUBSTITUTION‘;(昨天晚听课时叶总提醒,在存储过程中set sql_mode)

mysql> call PRO_INSERT();
Query OK, 1 row affected, 3 warnings (0.01 sec)

mysql> show warnings;
+---------+------+---------------------------------------------+
| Level   | Code | Message                                     |
+---------+------+---------------------------------------------+
| Warning | 1264 | Out of range value for column 'id' at row 1 |
| Warning | 1264 | Out of range value for column 'id' at row 2 |
| Warning | 1265 | Data truncated for column 'vname' at row 2  |
+---------+------+---------------------------------------------+
3 rows in set (0.00 sec)

mysql> call PRO_INSERT();
ERROR 1264 (22003): Out of range value for column 'id' at row 1
mysql>

存储过程

DELIMITER $$

USE `test`$$

DROP PROCEDURE IF EXISTS `PRO_INSERT`$$

CREATE DEFINER=`root`@`%` PROCEDURE `PRO_INSERT`()
BEGIN
SET sql_mode='STRICT_TRANS_TABLES,NO_ENGINE_SUBSTITUTION';
INSERT INTO t_int(id,vname)VALUES(POWER(2,31),'0123456789abcdefghij');
INSERT INTO t_int(id,vname)VALUES(POWER(2,31),'0123456789abcdefghij1');
    END$$

DELIMITER ;

[MySQL学习]STRICT_ALL_TABLES对应的OUT of RANGE VALUE FOR COLUMN和DATA truncated FOR COLUMN

时间: 2024-10-14 04:11:16

[MySQL学习]STRICT_ALL_TABLES对应的OUT of RANGE VALUE FOR COLUMN和DATA truncated FOR COLUMN的相关文章

mysql Out of range value adjusted for column导致Warning(1265)Data truncated for column &#39;column_name&#39; at row 1

今天下午,我们的一个开发来找我,说线上有个环境报了"Warning(1265)Data truncated for column 'column_name' at row 1",定义的字段长度decimal(32,4),实际的小数点有超过4位的,但是大部分的账户登录查询的时候都没有问题,已知的就一个账户进行查询的时候会出现这个问题,看数据没有什么特别异常的. 于是,过去协助排查,临时拷贝了个存储过程,还真蹊跷,查询其他数据都没有问题,但是一到这一条记录就报错,在update报错的语句前

mysql中出现的Data truncated for column

1.先描述一下自己出现的问题. 如果你想把允许为空值的勾去掉...恰巧数据库中的数据 processed_f 为空没有值....这时候你对数据表结构做更改的时候就会出现Data truncated for column processed_f 的提示..解决方式即为  给数据库中的字段processed_f    赋值 .这时候你在保存.就不会出现这个错误了. 2.网上他人遇到的..mysql中想一个数据库中插入一条记录时,有可能因为好多原因,会出现Data truncated for colu

Mysql load data infile 导入数据出现:Data truncated for column

[1]Mysql load data infile 导入数据出现:Data truncated for column .... 可能原因: (1)数据库表的字段类型长度不够,或改为其他数据类型(即类型错误)试试. (2)Myysql的my.ini配置文件中有一个max_allowed_packet配置项,默认是4M. 如果没有修改默认的这个配置项而你要导入的文件大于4M的话,可能出现上述类似的数据导入错误. Good Good Study, Day Day Up. 顺序 选择 循环 总结 原文地

[Mysql]由Data truncated for column联想到的sql_mode配置

系统日志中出现了 ata truncated for column 'agent' at row 1 mysql出现这个问题的原因,无非就是字符集设置 或者是 字段过长导致的. mysql在初始化的时候已经统一为utf-8了,所以可以忽略这个问题. 字符串过长从而导入插入失败 一种方式是修改字段长度,可是我这个字段没法知道到底多长存储合适,不太好 一种方式是在程序中截取字符串,这个方法可行,也比较好. 但是我又想了想,以前的时候为啥会自动截断,这次就插入不进去了了呢? 原因是mysql的sql_

Mysql学习笔记(二)数据类型 补充

原文:Mysql学习笔记(二)数据类型 补充 PS:简单的补充一下数据类型里的String类型以及列类型... 学习内容: 1.String类型 2.列类型存储需求 String类型: i.char与varchar char与varchar的类型相似,但是他们的保存方式和检索方式不同... char的存储结构是固定长度的存储...即指定了几个字节,那么就占用几个字节,如char(4),那么无论存入的是什么字串,那么都占用四个字节...char的 可表示长度范围为0-255的任何值,当保存的字节不

我的MYSQL学习心得(四) 数据类型

MYSQL里的BLOB数据类型 BLOB是一个二进制大对象,用来存储可变数量的数据.BLOB类型分为4种:TinyBlob.Blob.MediumBlob.LongBlob, 这几个类型之间的唯一区别是在存储文件的最大大小上不同. MySQL的四种BLOB类型     类型 大小(单位:字节) TinyBlob                            最大 255Blob                                  最大 65KMediumBlob      

MySQL学习系列2--MySQL执行计划分析EXPLAIN

1.Explain语法 EXPLAIN SELECT -- 变体:   EXPLAIN EXTENDED SELECT -- 将执行计划"反编译"成SELECT语句,运行SHOW WARNINGS 可得到被MySQL优化器优化后的查询语句 2.执行计划分析和实例 创建员工表Employee create table Employee ( ID int auto_increment, Ename varchar(32), Age int, Salary float, MID int, P

mysql学习笔记 第五天

使用分区数据表: 分区数据表和merge数据表具有相似的作用,但是分区数据表确确实实是一个数据表 ,不像merge是列出数据表的逻辑关系,并且分区数据表可以包括像myisam以外的 的数据表.创建分区数据表: create table 里给出数据列和索引,然后用partition by 定义一个用来把数据行分配 到各个分区的分区函数:[将数据表分成四个区] create table log_partition( dt datetime not null, info varchar(100) no

MySQL学习笔记—SQL服务器模式汇总

MySQL学习笔记-SQL服务器模式汇总 MySQL服务器可以以不同的SQL模式来操作,并且可以为不同客户端应用不同模式.这样每个应用程序可以根据自己的需求来定制服务器的操作模式. 模式定义MySQL应支持哪些SQL语法,以及应执行哪种数据验证检查.这样可以更容易地在不同的环境中使用MySQL,并结合其它数据库服务器使用MySQL. 你可以用–sql-mode="modes"选项启动mysqld来设置默认SQL模式.如果你想要重设,该值还可以为空(–sql-mode ="&q