SQL_MODE可能是比较容易让开发人员和DBA忽略的一个变量,默认为空。SQL_MODE的设置其实是比较冒险的一种设置,因为在这种设置下 可以允许一些非法操作,比如可以将NULL插入NOT NULL的字段中,也可以插入一些非法日期,如“2012-12-32”。因此在生产环境中强烈建议开发人员将这个值设为严格模式,这样有些问题可以在数 据库的设计和开发阶段就能发现,而如果在生产环境下运行数据库后发现这类问题,那么修改的代价将变得十分巨大。此外,正确地设置SQL_MODE还可以做 一些约束(Constraint)检查的工作。

对于SQL_MODE的设置,可以在MySQL的配置文件如my.cnf和my.ini中进行,也可以在客户端工具中进行,并且可以分别进行全局的设置或当前会话的设置。下面的命令可以用来查看当前SQL_MODE的设置情况。

  1. mysql> SELECT @@global.sql_mode\G;
  2. *************************** 1. row ***************************
  3. @@global.sql_mode:
  4. 1 row in set (0.00 sec)
  5. mysql> SELECT @@session.sql_mode\G;
  6. *************************** 1. row ***************************
  7. @@session.sql_mode: NO_UNSIGNED_SUBTRACTION
  8. 1 row in set (0.00 sec)

可以看到当前全局的SQL_MODE设置为空,而当前会话的设置为NO_UNSIGNED_SUBTRACTION。通过以下语句可以将当前的SQL_MODE设置为严格模式。

  1. mysql> SET GLOBAL sql_mode='strict_trans_tables';
  2. 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后,不能用双引号来引用字符串,因为它将被解释为识别符,示例如下:

  1. mysql> CREATE TABLE z ( a VARCHAR(10))ENGINE=INNODB;
  2. Query OK, 0 rows affected (0.00 sec)
  3. mysql>INSERT INTO z SELECT "aaa";
  4. Query OK, 1 rows affected (0.00 sec)
  5. mysql> SET sql_mode='ANSI_QUOTES';
  6. Query OK, 0 rows affected (0.00 sec)
  7. mysql> INSERT INTO z SELECT "aaa";
  8. 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模式,可以获得以前旧版本的更高优先级的结果。下面看一个例子:

  1. mysql> SELECT 0 BETWEEN -1 AND 1\G;
  2. *************************** 1. row ***************************
  3. 0 BETWEEN -1 AND 1: 1
  4. 1 row in set (0.00 sec)

0在-1到1之间,所以返回1,如果加上NOT,则返回0,过程如下:

    1. mysql> SELECT @@sql_mode\G;
    2. *************************** 1. row ***************************
    3. @@sql_mode:
    4. 1 row in set (0.00 sec)
    5. mysql> SELECT not 0 BETWEEN -1 AND 1\G;
    6. *************************** 1. row ***************************
    7. NOT 0 BETWEEN -1 AND 1: 0
    8. 1 row in set (0.00 sec)

但是如果启用HIGH_NOT_PRECEDENCE模式,则SELECT NOT 0 BETWEEN -1 AND 1被解释为SELECT(NOT 0)BETWEEN -1 AND 1,结果就完全相反,如下所示:

  1. mysql> SELECT NOT 0 BETWEEN -1 AND 1\G;
  2. *************************** 1. row ***************************
  3. NOT 0 BETWEEN -1 AND 1: 1
  4. 1 row in set (0.00 sec)

从上述例子中还能看出,在MySQL数据库中BETWEEN a AND b被解释为[a,b]。下面做两个简单的测试。

  1. mysql> SELECT 1 BETWEEN -1 AND 1\G;
  2. *************************** 1. row ***************************
  3. 1 BETWEEN -1 AND 1: 1
  4. 1 row in set (0.00 sec)
  5. mysql> SELECT -1 BETWEEN -1 AND 1\G;
  6. *************************** 1. row ***************************
  7. -1 BETWEEN -1 AND 1: 1
  8. 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:反斜杠“\”作为普通字符而非转义符,示例如下:

  1. mysql> SET sql_mode='';
  2. Query OK, 0 rows affected (0.00 sec)
  3. mysql> SELECT '\\'\G;
  4. *************************** 1. row ***************************
  5. \: \
  6. 1 row in set (0.00 sec)
  7. mysql> SET sql_mode='NO_BACKSLASH_ESCAPES';
  8. Query OK, 0 rows affected (0.00 sec)
  9. mysql> SET '\\'\G;
  10. *************************** 1. row ***************************
  11. \\: \\
  12. 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都会直接抛出错误而非警告,示例如下:

  1. mysql> SET sql_mode='NO_ZERO_IN_DATE';
  2. Query OK, 0 rows affected (0.00 sec)
  3. mysql> CREATE TABLE a ( a DATETIME );
  4. Query OK, 0 rows affected (0.04 sec)
  5. mysql> INSERT INTO a SELECT '2011-01-00';
  6. 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从句中,示例如下:

  1. mysql> SET sql_mode='ONLY_FULL_GROUP_BY';
  2. Query OK, 0 rows affected (0.00 sec)
  3. mysql> SELECT a,SUM(b) FROM t GROUP BY b;
  4. ERROR 1055 (42000): 'test.t.a' isn't in GROUP BY

PAD_CHAR_TO_FULL_LENGTH:对于CHAR类型字段,不要截断空洞数据。空洞数据就是自动填充值为0x20的数据。先来看MySQL数据库在默认情况下的表现。

  1. mysql> CREATE TABLE t ( a CHAR(10) );
  2. Query OK, 0 rows affected (0.04 sec)
  3. mysql> INSERT INTO t SELECT 'a';
  4. Query OK, 1 row affected (0.01 sec)
  5. Records: 1  Duplicates: 0  Warnings: 0
  6. mysql>SELECT a,CHAR_LENGTH(a),HEX(a) FROM t\G;
  7. *************************** 1. row ***************************
  8. a: a
  9. CHAR_LENGTH(a): 1
  10. HEX(a): 61
  11. 1 row in set (0.04 sec)

可以看到,在默认情况下,虽然a列是CHAR类型,但是返回的长度是1,这是因为MySQL数据库已经对后面的空洞数据进行了截断。若启用PAD_CHAR_TO_FULL_LENGTH选项,则反映的是实际存储的内容,例如:

  1. mysql> SELECT a,CHAR_LENGTH(a),HEX(a) FROM t\G;
  2. *************************** 1. row ***************************
  3. a: a
  4. CHAR_LENGTH(a): 10
  5. HEX(a): 61202020202020202020
  6. 1 row in set (0.00 sec)

可以看到在CHAR列a中实际存储的值为0x61202020202020202020。

PIPES_AS_CONCAT:将“||”视为字符串的连接操作符而非或运算符,这和Oracle数据库是一样的,也和字符串的拼接函数Concat相类似,例如:

  1. mysql> SET sql_mode='pipes_as_concat';
  2. Query OK, 0 rows affected (0.01 sec)
  3. mysql> SELECT 'a'||'b'||'c'\G;
  4. *************************** 1. row ***************************
  5. 'a'||'b'||'c': abc
  6. 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设置讲解的更多相关文章

  1. IntelliJ IDEA 教程设置讲解

    IntelliJ IDEA 常用设置讲解 说明 IntelliJ在业界被公认为最好的java开发工具之一,尤其在智能代码助手.代码自动提示.重构.J2EE支持.Ant.JUnit.CVS整合.代码审查 ...

  2. mysql SQL_MODE设置

    1.1.   SQL_MODE设置 在生产环境中强烈建议将这个值设置为严格模式,这样有些问题可以在数据库的设计和开发阶段就能实现,而如果在生产环境下运行数据库后发现这类问题,那么修改的代价将变得十分巨 ...

  3. MySQL数据类型:SQL_MODE设置不容忽视

    [IT168 技术]SQL_MODE可能是比较容易让开发人员和DBA忽略的一个变量,默认为空.SQL_MODE的设置其实是比较冒险的一种设置,因为在这种设置下可以允许一些非法操作,比如可以将NULL插 ...

  4. MySQL timespan设置 sql_mode设置

    Timespan设置: 在MySQL5.7版本中创建表 CREATE TABLE `investor_seat` ( `id` int(11) NOT NULL AUTO_INCREMENT , `i ...

  5. Mysql sql_mode设置 timestamp default 0000-00-00 00:00:00 创建表失败处理

    往数据库里创建新表的时候报错: [Err] 1067 - Invalid default value for 'updateTime' DROP TABLE IF EXISTS `passwd_res ...

  6. IntelliJ IDEA 常用设置讲解

    说明 IntelliJ IDEA 有很多人性化的设置我们必须单独拿出来讲解,也因为这些人性化的设置让我们这些 IntelliJ IDEA 死忠粉更加死心塌地使用它和分享它. 常用设置 IntelliJ ...

  7. IntelliJ IDEA 常用设置讲解3

    IntelliJ IDEA 有很多人性化的设置我们必须单独拿出来讲解,也因为这些人性化的设置让我们这些 IntelliJ IDEA 死忠粉更加死心塌地使用它和分享它. 常用设置 如上图 Gif 所示, ...

  8. IntelliJ IDEA 常用设置讲解2

    IntelliJ IDEA 有很多人性化的设置我们必须单独拿出来讲解,也因为这些人性化的设置让我们这些 IntelliJ IDEA 死忠粉更加死心塌地使用它和分享它. 常用设置 如上图 Gif 所示, ...

  9. IntelliJ IDEA 常用设置讲解1

    IntelliJ IDEA 有很多人性化的设置我们必须单独拿出来讲解,也因为这些人性化的设置让我们这些 IntelliJ IDEA 死忠粉更加死心塌地使用它和分享它. 常用设置 IntelliJ ID ...

随机推荐

  1. HDFS初识

    参看原文 [Hadoop]HDFS的运行原理 参看原文 还不懂HDFS的工作原理?快来扫扫盲 简介 HDFS(Hadoop Distributed File System) Hadoop分布式文件系统 ...

  2. 02 java 基础:java 文件名与类名关系 CLASSPATH

    java 类修饰符:通常情况下使用 public 修饰,此时,java 强制要求 .java 文件名需与该 public 修饰类名一致,否则无法编译通过.如若没有加修饰符,文件名与类名可无任何关联. ...

  3. nginx应用场景,特性,目录结构,常用模块,内置变量,URL和URI,http状态码,配置文件详解

    1.nginx介绍 1丶俄罗斯人开发的,开源www服务软件 2丶软件一共780K 3丶nginx本身是一款静态(html,js,css,jpg等)www软件 4丶静态小文件高并发,同时占用的资源很少, ...

  4. 转:python cgi编程

    转:http://www.runoob.com/Python/python-cgi.html 什么是CGI CGI 目前由NCSA维护,NCSA定义CGI如下: CGI(Common Gateway ...

  5. B. Black Square(字符串)

    B. Black Square time limit per test 1 second memory limit per test 256 megabytes input standard inpu ...

  6. 使用ICSharpCode.SharpZipLib+Aspose模板批量导出Word

    由于是Web端的项目,所以点击按钮之后直接从Aspose模板读取数据,然后在内存中操作,而不是下载到本地后再打包弄到内存中下载.废话不多说,直接上代码 public ActionResult Expo ...

  7. PM过程的一些典型场景和问题

    如何进行团队激励 如何进行目标管理 如何进行绩效考核 如何处理团队沟通(技巧) 详述几种软件过程理论 需求分析和度量 测试过程和工具 开发管理过程

  8. POJ 2348 Euclid's Game 博弈论

    http://poj.org/problem?id=2348 顺便说,必应翻译真的好用,比谷歌翻译好用100倍. 很难判断这道题的具体博弈类型. 有两种写法,一种是找规律,一种是推理得到关系后循环(或 ...

  9. [ARC062F]Painting Graphs with AtCoDeer

    题意:一个无向图,用$k$种不同的颜色给每条边染色,问能染出多少种不同的图,如果两张图能通过循环移位环边使得颜色相同,那么这两张图被认为是相同的 数学太差伤不起啊...补了一下Burnside定理的证 ...

  10. 【推导】【凸包】MIPT-2016 Pre-Finals Workshop, Taiwan NTU Contest, Sunday, March 27, 2016 Problem D. Drawing Hell

    平面上n个点,两个人交替决策,用线段连接两个点,但不能跨越其他点或者已经存在的线段.不能做的人算输,问你谁赢. 实际上,跟两个人的决策无关,n个点将平面三角剖分,只需要算出有几条边即可. 凸包上如果有 ...