SQL_MODE设置讲解
SQL_MODE可能是比较容易让开发人员和DBA忽略的一个变量,默认为空。SQL_MODE的设置其实是比较冒险的一种设置,因为在这种设置下 可以允许一些非法操作,比如可以将NULL插入NOT NULL的字段中,也可以插入一些非法日期,如“2012-12-32”。因此在生产环境中强烈建议开发人员将这个值设为严格模式,这样有些问题可以在数 据库的设计和开发阶段就能发现,而如果在生产环境下运行数据库后发现这类问题,那么修改的代价将变得十分巨大。此外,正确地设置SQL_MODE还可以做 一些约束(Constraint)检查的工作。
对于SQL_MODE的设置,可以在MySQL的配置文件如my.cnf和my.ini中进行,也可以在客户端工具中进行,并且可以分别进行全局的设置或当前会话的设置。下面的命令可以用来查看当前SQL_MODE的设置情况。
- mysql> SELECT @@global.sql_mode\G;
- *************************** 1. row ***************************
- @@global.sql_mode:
- 1 row in set (0.00 sec)
- mysql> SELECT @@session.sql_mode\G;
- *************************** 1. row ***************************
- @@session.sql_mode: NO_UNSIGNED_SUBTRACTION
- 1 row in set (0.00 sec)
可以看到当前全局的SQL_MODE设置为空,而当前会话的设置为NO_UNSIGNED_SUBTRACTION。通过以下语句可以将当前的SQL_MODE设置为严格模式。
- mysql> SET GLOBAL sql_mode='strict_trans_tables';
- Query OK, 0 rows affected (0.00 sec)
严格模式是指将SQL_MODE变量设置为STRICT_TRANS_TABLES或STRICT_ALL_TABLES中的至少一种。现在来看一下SQL_MODE可以设置的选项。
STRICT_TRANS_TABLES:在该模式下,如果一个值不能插入到一个事务表(例如表的存储引擎为InnoDB)中,则中断当前的操作不影响非事务表(例如表的存储引擎为MyISAM)。
ALLOW_INVALID_DATES:该选项并不完全对日期的合法性进行检查,只检查月份是否在1~12之间,日期是否在1~31之间。该模式仅对DATE和DATETIME类型有效,而对TIMESTAMP无效,因为TIMESTAMP总是要求一个合法的输入。
ANSI_QUOTES:启用ANSI_QUOTES后,不能用双引号来引用字符串,因为它将被解释为识别符,示例如下:
- mysql> CREATE TABLE z ( a VARCHAR(10))ENGINE=INNODB;
- Query OK, 0 rows affected (0.00 sec)
- mysql>INSERT INTO z SELECT "aaa";
- Query OK, 1 rows affected (0.00 sec)
- mysql> SET sql_mode='ANSI_QUOTES';
- Query OK, 0 rows affected (0.00 sec)
- mysql> INSERT INTO z SELECT "aaa";
- ERROR 1054 (42S22): Unknown column 'aaa' in 'field list'
ERROR_FOR_DIVISION_BY_ZERO:在INSERT或UPDATE过程中,如果数据被零除(或MOD(X,0)),则产生错误 (否则为警告)。如果未给出该模式,那么数据被零除时MySQL返回NULL。如果用到INSERT IGNORE或UPDATE IGNORE中,MySQL生成被零除警告,但操作结果为NULL。
HIGH_NOT_PRECEDENCE NOT:操作符的优先顺序是表达式。例如,NOT a BETWEEN b AND c被解释为NOT(a BETWEEN b AND c),在一些旧版本MySQL中, 前面的表达式被解释为(NOT a)BETWEEN b AND c。启用HIGH_NOT_PRECEDENCE SQL模式,可以获得以前旧版本的更高优先级的结果。下面看一个例子:
- mysql> SELECT 0 BETWEEN -1 AND 1\G;
- *************************** 1. row ***************************
- 0 BETWEEN -1 AND 1: 1
- 1 row in set (0.00 sec)
0在-1到1之间,所以返回1,如果加上NOT,则返回0,过程如下:
- mysql> SELECT @@sql_mode\G;
- *************************** 1. row ***************************
- @@sql_mode:
- 1 row in set (0.00 sec)
- mysql> SELECT not 0 BETWEEN -1 AND 1\G;
- *************************** 1. row ***************************
- NOT 0 BETWEEN -1 AND 1: 0
- 1 row in set (0.00 sec)
但是如果启用HIGH_NOT_PRECEDENCE模式,则SELECT NOT 0 BETWEEN -1 AND 1被解释为SELECT(NOT 0)BETWEEN -1 AND 1,结果就完全相反,如下所示:
- mysql> SELECT NOT 0 BETWEEN -1 AND 1\G;
- *************************** 1. row ***************************
- NOT 0 BETWEEN -1 AND 1: 1
- 1 row in set (0.00 sec)
从上述例子中还能看出,在MySQL数据库中BETWEEN a AND b被解释为[a,b]。下面做两个简单的测试。
- mysql> SELECT 1 BETWEEN -1 AND 1\G;
- *************************** 1. row ***************************
- 1 BETWEEN -1 AND 1: 1
- 1 row in set (0.00 sec)
- mysql> SELECT -1 BETWEEN -1 AND 1\G;
- *************************** 1. row ***************************
- -1 BETWEEN -1 AND 1: 1
- 1 row in set (0.00 sec)
IGNORE_SPACE:函数名和括号“(”之间有空格。除了增加一些烦恼,这个选项好像没有任何好处,要访问保存为关键字的数据库、表或列名, 用户必须引用该选项。例如某个表中有user这一列,而MySQL数据库中又有user这个函数, user会被解释为函数,如果想要选择user这一列,则需要引用。
NO_AUTO_CREATE_USER:禁止GRANT创建密码为空的用户。
NO_AUTO_VALUE_ON_ZERO:该选项影响列为自增长的插入。在默认设置下,插入0或NULL代表生成下一个自增长值。如果用户希望插入的值为0,而该列又是自增长的,那么这个选项就有用了。
NO_BACKSLASH_ESCAPES:反斜杠“\”作为普通字符而非转义符,示例如下:
- mysql> SET sql_mode='';
- Query OK, 0 rows affected (0.00 sec)
- mysql> SELECT '\\'\G;
- *************************** 1. row ***************************
- \: \
- 1 row in set (0.00 sec)
- mysql> SET sql_mode='NO_BACKSLASH_ESCAPES';
- Query OK, 0 rows affected (0.00 sec)
- mysql> SET '\\'\G;
- *************************** 1. row ***************************
- \\: \\
- 1 row in set (0.00 sec)
NO_DIR_IN_CREATE:在创建表时忽视所有INDEX DIRECTORY和DATA DIRECTORY的选项。
NO_ENGINE_SUBSTITUTION:如果需要的存储引擎被禁用或未编译,那么抛出错误。默认用默认的存储引擎替代,并抛出一个异常。
NO_UNSIGNED_SUBTRACTION:之前已经介绍过,启用这个选项后两个UNSIGNED类型相减返回SIGNED类型。
NO_ZERO_DATE:在非严格模式下,可以插入形如“0000-00-00 00:00:00”的非法日期,MySQL数据库仅抛出一个警告。而启用该选项后,MySQL数据库不允许插入零日期,插入零日期会抛出错误而非警告。
NO_ZERO_IN_DATE:在严格模式下,不允许日期和月份为零。如“2011-00-01”和“2011-01-00”这样的格式是不允许的。采用日期或月份为零的格式时MySQL都会直接抛出错误而非警告,示例如下:
- mysql> SET sql_mode='NO_ZERO_IN_DATE';
- Query OK, 0 rows affected (0.00 sec)
- mysql> CREATE TABLE a ( a DATETIME );
- Query OK, 0 rows affected (0.04 sec)
- mysql> INSERT INTO a SELECT '2011-01-00';
- ERROR 1292 (22007): Incorrect datetime value: '2011-01-00' for column 'a' at row 1
ONLY_FULL_GROUP_BY:对于GROUP BY聚合操作,如果在SELECT中的列没有在GROUP BY中出现,那么这句SQL是不合法的,因为a列不在GROUP BY从句中,示例如下:
- mysql> SET sql_mode='ONLY_FULL_GROUP_BY';
- Query OK, 0 rows affected (0.00 sec)
- mysql> SELECT a,SUM(b) FROM t GROUP BY b;
- ERROR 1055 (42000): 'test.t.a' isn't in GROUP BY
PAD_CHAR_TO_FULL_LENGTH:对于CHAR类型字段,不要截断空洞数据。空洞数据就是自动填充值为0x20的数据。先来看MySQL数据库在默认情况下的表现。
- mysql> CREATE TABLE t ( a CHAR(10) );
- Query OK, 0 rows affected (0.04 sec)
- mysql> INSERT INTO t SELECT 'a';
- Query OK, 1 row affected (0.01 sec)
- Records: 1 Duplicates: 0 Warnings: 0
- mysql>SELECT a,CHAR_LENGTH(a),HEX(a) FROM t\G;
- *************************** 1. row ***************************
- a: a
- CHAR_LENGTH(a): 1
- HEX(a): 61
- 1 row in set (0.04 sec)
可以看到,在默认情况下,虽然a列是CHAR类型,但是返回的长度是1,这是因为MySQL数据库已经对后面的空洞数据进行了截断。若启用PAD_CHAR_TO_FULL_LENGTH选项,则反映的是实际存储的内容,例如:
- mysql> SELECT a,CHAR_LENGTH(a),HEX(a) FROM t\G;
- *************************** 1. row ***************************
- a: a
- CHAR_LENGTH(a): 10
- HEX(a): 61202020202020202020
- 1 row in set (0.00 sec)
可以看到在CHAR列a中实际存储的值为0x61202020202020202020。
PIPES_AS_CONCAT:将“||”视为字符串的连接操作符而非或运算符,这和Oracle数据库是一样的,也和字符串的拼接函数Concat相类似,例如:
- mysql> SET sql_mode='pipes_as_concat';
- Query OK, 0 rows affected (0.01 sec)
- mysql> SELECT 'a'||'b'||'c'\G;
- *************************** 1. row ***************************
- 'a'||'b'||'c': abc
- 1 row in set (0.00 sec)
REAL_AS_FLOAT:将REAL视为FLOAT的同义词,而不是DOUBLE的同义词。
STRICT_ALL_TABLES:对所有引擎的表都启用严格模式。(STRICT_TRANS_TABLES只对支持事务的表启用严格模式)。
在严格模式下,一旦任何操作的数据产生问题,都会终止当前的操作。对于启用STRICT_ALL_TABLES选项的非事务引擎来说,这时数据可能停留在一个未知的状态。这可能不是所有非事务引擎愿意看到的一种情况,因此需要非常小心这个选项可能带来的潜在影响。
下面的几种SQL_MODE设置是之前讨论的几种选项的组合。
ANSI:等同于REAL_AS_FLOAT、PIPES_AS_CONCAT和ANSI_QUOTES、IGNORE_SPACE的组合。
ORACLE:等同于PIPES_AS_CONCAT、 ANSI_QUOTES、IGNORE_SPACE、 NO_KEY_OPTIONS、 NO_TABLE_OPTIONS、 NO_FIELD_OPTIONS和NO_AUTO_CREATE_USER的组合。
TRADITIONAL:等同于STRICT_TRANS_TABLES、 STRICT_ALL_TABLES、NO_ZERO_IN_DATE、NO_ZERO_DATE、 ERROR_FOR_DIVISION_BY_ZERO、NO_AUTO_CREATE_USER和 NO_ENGINE_SUBSTITUTION的组合。
MSSQL:等同于PIPES_AS_CONCAT、 ANSI_QUOTES、 IGNORE_SPACE、NO_KEY_OPTIONS、NO_TABLE_OPTIONS和 NO_FIELD_OPTIONS的组合。
DB2:等同于PIPES_AS_CONCAT、ANSI_QUOTES、 IGNORE_SPACE、NO_KEY_OPTIONS、 NO_TABLE_OPTIONS和NO_FIELD_OPTIONS的组合。
MYSQL323:等同于NO_FIELD_OPTIONS和HIGH_NOT_PRECEDENCE的组合。
MYSQL40:等同于NO_FIELD_OPTIONS和HIGH_NOT_PRECEDENCE的组合。
MAXDB:等同于PIPES_AS_CONCAT、ANSI_QUOTES、IGNORE_SPACE、NO_KEY_OPTIONS、 NO_TABLE_OPTIONS、 NO_FIELD_OPTIONS和 NO_AUTO_CREATE_USER的组合。
原文地址:http://book.51cto.com/art/201204/331329.htm
SQL_MODE设置讲解的更多相关文章
- IntelliJ IDEA 教程设置讲解
IntelliJ IDEA 常用设置讲解 说明 IntelliJ在业界被公认为最好的java开发工具之一,尤其在智能代码助手.代码自动提示.重构.J2EE支持.Ant.JUnit.CVS整合.代码审查 ...
- mysql SQL_MODE设置
1.1. SQL_MODE设置 在生产环境中强烈建议将这个值设置为严格模式,这样有些问题可以在数据库的设计和开发阶段就能实现,而如果在生产环境下运行数据库后发现这类问题,那么修改的代价将变得十分巨 ...
- MySQL数据类型:SQL_MODE设置不容忽视
[IT168 技术]SQL_MODE可能是比较容易让开发人员和DBA忽略的一个变量,默认为空.SQL_MODE的设置其实是比较冒险的一种设置,因为在这种设置下可以允许一些非法操作,比如可以将NULL插 ...
- MySQL timespan设置 sql_mode设置
Timespan设置: 在MySQL5.7版本中创建表 CREATE TABLE `investor_seat` ( `id` int(11) NOT NULL AUTO_INCREMENT , `i ...
- Mysql sql_mode设置 timestamp default 0000-00-00 00:00:00 创建表失败处理
往数据库里创建新表的时候报错: [Err] 1067 - Invalid default value for 'updateTime' DROP TABLE IF EXISTS `passwd_res ...
- IntelliJ IDEA 常用设置讲解
说明 IntelliJ IDEA 有很多人性化的设置我们必须单独拿出来讲解,也因为这些人性化的设置让我们这些 IntelliJ IDEA 死忠粉更加死心塌地使用它和分享它. 常用设置 IntelliJ ...
- IntelliJ IDEA 常用设置讲解3
IntelliJ IDEA 有很多人性化的设置我们必须单独拿出来讲解,也因为这些人性化的设置让我们这些 IntelliJ IDEA 死忠粉更加死心塌地使用它和分享它. 常用设置 如上图 Gif 所示, ...
- IntelliJ IDEA 常用设置讲解2
IntelliJ IDEA 有很多人性化的设置我们必须单独拿出来讲解,也因为这些人性化的设置让我们这些 IntelliJ IDEA 死忠粉更加死心塌地使用它和分享它. 常用设置 如上图 Gif 所示, ...
- IntelliJ IDEA 常用设置讲解1
IntelliJ IDEA 有很多人性化的设置我们必须单独拿出来讲解,也因为这些人性化的设置让我们这些 IntelliJ IDEA 死忠粉更加死心塌地使用它和分享它. 常用设置 IntelliJ ID ...
随机推荐
- HDFS初识
参看原文 [Hadoop]HDFS的运行原理 参看原文 还不懂HDFS的工作原理?快来扫扫盲 简介 HDFS(Hadoop Distributed File System) Hadoop分布式文件系统 ...
- 02 java 基础:java 文件名与类名关系 CLASSPATH
java 类修饰符:通常情况下使用 public 修饰,此时,java 强制要求 .java 文件名需与该 public 修饰类名一致,否则无法编译通过.如若没有加修饰符,文件名与类名可无任何关联. ...
- nginx应用场景,特性,目录结构,常用模块,内置变量,URL和URI,http状态码,配置文件详解
1.nginx介绍 1丶俄罗斯人开发的,开源www服务软件 2丶软件一共780K 3丶nginx本身是一款静态(html,js,css,jpg等)www软件 4丶静态小文件高并发,同时占用的资源很少, ...
- 转:python cgi编程
转:http://www.runoob.com/Python/python-cgi.html 什么是CGI CGI 目前由NCSA维护,NCSA定义CGI如下: CGI(Common Gateway ...
- B. Black Square(字符串)
B. Black Square time limit per test 1 second memory limit per test 256 megabytes input standard inpu ...
- 使用ICSharpCode.SharpZipLib+Aspose模板批量导出Word
由于是Web端的项目,所以点击按钮之后直接从Aspose模板读取数据,然后在内存中操作,而不是下载到本地后再打包弄到内存中下载.废话不多说,直接上代码 public ActionResult Expo ...
- PM过程的一些典型场景和问题
如何进行团队激励 如何进行目标管理 如何进行绩效考核 如何处理团队沟通(技巧) 详述几种软件过程理论 需求分析和度量 测试过程和工具 开发管理过程
- POJ 2348 Euclid's Game 博弈论
http://poj.org/problem?id=2348 顺便说,必应翻译真的好用,比谷歌翻译好用100倍. 很难判断这道题的具体博弈类型. 有两种写法,一种是找规律,一种是推理得到关系后循环(或 ...
- [ARC062F]Painting Graphs with AtCoDeer
题意:一个无向图,用$k$种不同的颜色给每条边染色,问能染出多少种不同的图,如果两张图能通过循环移位环边使得颜色相同,那么这两张图被认为是相同的 数学太差伤不起啊...补了一下Burnside定理的证 ...
- 【推导】【凸包】MIPT-2016 Pre-Finals Workshop, Taiwan NTU Contest, Sunday, March 27, 2016 Problem D. Drawing Hell
平面上n个点,两个人交替决策,用线段连接两个点,但不能跨越其他点或者已经存在的线段.不能做的人算输,问你谁赢. 实际上,跟两个人的决策无关,n个点将平面三角剖分,只需要算出有几条边即可. 凸包上如果有 ...