如果要挖井,就要挖到水出为止 [登录·注册]

吕滔博客

首页 开发 运维 工具 摄影

为什么在有的服务器上禅道、蝉知、然之安装会报错? 之理解MySQL的SQL_MODE

数据库 memory 发布于October 11, 2017 标签: MySQL

最近用蝉知的CMS建站比较多,感觉蛮顺手的,但在给客户安装的时候却会出现安装报错,其原因也很简单

查看了一下他们的install.sql文件中,有些时间字段的默认值是0000-00-00 00:00:00 ... 额,我个人习惯将时间值存int类型,这样程序处理上还有查询计算上会方便一些,可能他们为了在看数据库的时候方便一目了然的认出时间吧...不管它的初衷,要改程序不太可能了,以后也不好升级.我还是改我的数据库的兼容模式吧

MySQL5.5以后,其默认使用的是一种严格模式,也就是说,像禅知用的这种默认值的方式就会报错.SO,我们今天来说一说这个SQL_MODEL的相关的东东

SQL_MODE:通过对其正确的设置可以完成一些约束检查的工作,设置时,可在配置文件my.cnf或my.ini中进行,也可在客户端中进行,并可分别进行全局的设置或当前会话的设置。

查看SQL_MODE设置情况():

mysql> SHOW VARIABLES LIKE 'SQL_MODE';
+---------------+----------------------------------------------------------------+
| Variable_name | Value                                                          |
+---------------+----------------------------------------------------------------+
| sql_mode      | STRICT_TRANS_TABLES,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION |
+---------------+----------------------------------------------------------------+
1 row in set (0.03 sec)

或者(全局)

mysql> SELECT @@global.SQL_MODE;
+----------------------------------------------------------------+
| @@global.SQL_MODE                                              |
+----------------------------------------------------------------+
| STRICT_TRANS_TABLES,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION |
+----------------------------------------------------------------+
1 row in set (0.00 sec)

亦或(当前会话)

mysql> SELECT @@session.SQL_MODE;
+----------------------------------------------------------------+
| @@session.SQL_MODE                                             |
+----------------------------------------------------------------+
| STRICT_TRANS_TABLES,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION |
+----------------------------------------------------------------+
1 row in set (0.00 sec)

亦或

mysql> SELECT @@SQL_MODE;
+----------------------------------------------------------------+
| @@session.SQL_MODE                                             |
+----------------------------------------------------------------+
| STRICT_TRANS_TABLES,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION |
+----------------------------------------------------------------+
1 row in set (0.00 sec)

设置方法很简单

mysql> SET global sql_mode='STRICT_TRANS_TABLES';
Query OK, 0 rows affected (0.00 sec)

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

介绍一下几种模式

STRICT_TRANS_TALES(严格模式):
只对支持事务的表启用严格模式

STRICT_ALL_TABLES(严格模式):
对所有引擎的表都启用严格模式

ALLOW_INVALID_DATES
不完全对日期合法性作检查,只检查月份是否在1~12,日期是否在1~31之间;仅对DATE和DATETIME有效,而对TIMESTAMP无效,因为TIMESTAMP总要求一个合法的输入。

ANSI_QUOTES
启用后,不能用双引号来引用字符串,因为"(双引号)将被解释为标识符

mysql> CREATE TABLE a ( a char(5));
Query OK, 0 rows affected (0.26 sec)

mysql> INSERT INTO a SELECT 'abc';
Query OK, 1 row affected (0.05 sec)
Records: 1 Duplicates: 0 Warnings: 0

mysql> SET SQL_MODE='ANSI_QUOTES';
Query OK, 0 rows affected (0.00 sec)

mysql> INSERT INTO a SELECT "abc";
ERROR 1054 (42S22): Unknown column 'abc' in 'field list'

mysql> SELECT @@session.sql_mode;
+--------------------+
| @@session.sql_mode |
+--------------------+
| ANSI_QUOTES        |
+--------------------+
1 row in set (0.00 sec)

ERROR_FOR_DIVISION_BY_ZERO
启用后,在insert或update过程中,若数据被零除(或MOD(x,0),则产生错误,若未启用,则产生警告,数据被零除时系统返回NULL。

HIGH_NOT_PRECEDENCE
启用后,可获得以前旧版本的优先级:
NOT a BETWEEN b AND c这个语句:
now: NOT (a BETWEEN b AND c)
before: (NOT a) BETWEEN b AND c

IGNORE_SPACE
启用后,忽略函数名和括号"("之间空格,要访问保存为关键字的数据库名,表名,列名时,需启用。

mysql> SELECT NOW();
ERROR 1630 (42000): FUNCTION test.NOW does not exist. Check the 'Function Name Parsing and Resolution' section in the Reference Manual
mysql> SET SQL_MODE='IGNORE_SPACE';
Query OK, 0 rows affected (0.00 sec)

mysql> SELECT NOW();
+---------------------+
| NOW ()              |
+---------------------+
| 2015-10-08 17:49:35 |
+---------------------+
1 row in set (0.00 sec)

NO_AUTO_CREATE_USER
禁止GRANT创建密码为空的用户。

NO_AUTO_VALUE_ON_ZERO
在自增长的列中插入0或NULL将不会是下一个自增长值。

O_BACKSLASH_ESCAPES
反斜杠\作为普通字符而非转义字符

mysql> SET SQL_MODE='';
Query OK, 0 rows affected (0.00 sec)

mysql> SELECT '\\';
+---+
| \ |
+---+
| \ |
+---+
1 row in set (0.00 sec)

mysql> SET SQL_MODE='NO_BACKSLASH_ESCAPES';
Query OK, 0 rows affected (0.00 sec)

mysql> SELECT '\\';
+----+
| \\ |
+----+
| \\ |
+----+
1 row in set (0.00 sec)

NO_DIR_IN_CREATE
在创建表时忽略所有index directory和data directory的选项。

NO_ENGINE_SUBSTITUTION
启用后,若需要的存储引擎被禁用或未编译,则抛出错误;未启用时将用默认的存储引擎代替,并抛出一个异常。

NO_UNSIGNED_SUBSTRACTION
启用后,两个UNSIGNED类型相减返回SIGNED类型。

NO_ZERO_DATE
启用后,不允许插入"0000-00-00 00:00:00"形如此类的零日期,这将抛出一个错误,若未启用,则可插入但仅会抛出一个警告。

NO_ZERO_IN_DATE
启用后,不允许月份和日期为零,和NO_ZERO_DATE一起启用,如"1999-01-00"将抛出错误而非警告。
若单独启用本项,则会抛出warning,然后插入如“0000-00-00 00:00:00”。

ONLY_FULL_GROUP_BY
对于GROUP BY聚合操作,若select中的列没有在group by中出现,那么这句SQL是不合法的。

PAD_CHAR_TO_FULL_LENGTH
启用后,对于CHAR类型将不会截断空洞数据

mysql> CREATE TABLE a ( a char(10), b varchar(10));
Query OK, 0 rows affected (0.29 sec)

mysql> INSERT INTO a SELECT 'a','b';
Query OK, 1 row affected (0.03 sec)
Records: 1 Duplicates: 0 Warnings: 0;

mysql> SELECT CHAR_LENGTH(a), CHAR_LENGTH(b) FROM a;
+----------------+----------------+
| CHAR_LENGTH(a)  | CHAR_LENGTH(b)  |
+----------------+----------------+
| 1              | 1              |
+----------------+----------------+
1 row in set (0.01 sec)

mysql> SET SQL_MODE='PAD_CHAR_TO_FULL_LENGTH';
Query OK, 0 rows affected (0.00 sec)

mysql> SELECT CHAR_LENGTH(a), CHAR_LENGTH(b) FROM a;
+----------------+----------------+
| CHAR_LENGTH(a) | CHAR_LENGTH(b) |
+----------------+----------------+
| 10             | 1              |
+----------------+----------------+
1 row in set (0.00 sec)

PIPES_AS_CONCAT
将"||"视为连接操作符而非"或运算符"。

REAL_AS_FLOAT
将REAL视为FLOAT的同义词而非DOUBLE的同义词。

蝉知相关产品的解决办法也就很明了啦~~:

先查看本地的模式

mysql> SELECT @@global.SQL_MODE;
+---------------------------------------------------------------------------------------------+
| @@global.SQL_MODE                                                                           |
+---------------------------------------------------------------------------------------------+
| STRICT_TRANS_TABLES,NO_ZERO_DATE,NO_ZERO_IN_DATE,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION |
+---------------------------------------------------------------------------------------------+
1 row in set (0.00 sec)

然后去掉NO_ZERO_DATENO_ZERO_IN_DATE

SET global sql_mode='STRICT_TRANS_TABLES,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION';

当然你也可以在my.cnf中配置

[mysqld]
sql-mode="STRICT_TRANS_TABLES,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION"

这样就可以不用每次设置啦

相关推荐

添加新评论

网站状态

  • 栏目分类:49个
  • 发布文章:1505篇
  • 用户评论:712条
  • 开博至今:4035天

正则速查

[abc] 匹配中括号中的单个字符,如a或b或c
[^abc] 匹配除了a、b、c等字符的其他单个字符
[a-z] 匹配一个字符范围,如a到z
[a-zA-Z] 匹配一个字符范围,如a-z 或 A-Z
^ 匹配行的开始
$ 匹配行的结束
\A 匹配一个字符串的开始
\z 匹配一个字符串的结束
. 匹配任意单个字符
\s 匹配空白字符,如空格,TAB
\S 匹配非空白字符
\d 匹配一个数字
\D 匹配非数字
\w 匹配一个字母
\W 匹配非字母
\b 匹配字符边界
(...) 引用所有括号中的内容
(a|b) a或者b
a? 零个或1个a
a* 零个或多个a
a+ 1个或多个a
a{3} 3次重复的a
a{3,} 3次或3次以上重复的a
a{3,6} 3到6次重复的a

修正符

/g 查找所有可能的匹配
/i 不区分大小写
/m 多行匹配
/s 单行匹配
/x 忽略空白模式
/e 可执行模式,PHP专有
/A 强制从目标字符串开头匹配
/D 使用$限制结尾字符,则不允许结尾有换行
/U 只匹配最近的一个字符串;不重复匹配

最新回复

  • 7ee5bec831b4e528c3a1d46ab8dd40c9: pid是传入当前获取的id值.在后台查询当前这个id值下的下级分类.
  • Uncaught ReferenceError: form is not defined: Uncaught ReferenceError: form is...
  • 春熙路: 8年的老博主了、致敬
  • hello: hello world
  • memory: 好的,感谢您的反馈。翻译完了也没有校验。。。 检查了一下,med...
  • jiangnvshi: 不知道你还记不记得之前你翻译的medoo文档:http://me...
  • 态度xiaomi: 不错不错。
  • memory: 回头我写个php的demo.
  • zjj: 请问有没有具体pid使用的方法呢?
  • 潇湘居士: 恩,如果是在局域网内部进行系统迁移,我们对比过 SSH 的压缩和...
  • memory: 文中的方案还是比较局限,个人认为还是适合主机迁移的时候比较好使。...
  • 潇湘居士: 使用 axel 或者 aria2 开启多线程下载,同样能达到相同...
  • 八角网赚站: 竟然还有这种操作
  • memory: 以前还有站点统计或百度统计撒的,这两产品到了今年已经开始不争气啦...
  • 夏日博客: 原来 Nginx 还有可以这样分析统计。
  • tomxuetao: 能个实例吗?
  • memory: 哈哈哈。。。话说也没毛病。