最近从 MySQL 迁移到 GoldenDB踩过一个坑。之前分享过。再来回顾一下。事故现场我们先创建一张表 test_1SQL 如下CREATE TABLEtest_1 ( idint(8) NOTNULL AUTO_INCREMENT, column1varchar(1) COLLATE utf8_bin DEFAULTNULL, date_time datetime DEFAULTNULL, PRIMARY KEY (id) ) ENGINEInnoDB AUTO_INCREMENT11DEFAULTCHARSETutf8 COLLATEutf8_bin往 test_1 插入 1 条数据如下图INSERT INTO test_1(column1,date_time)VALUES (a,NOW());然后我们创建一张跟 test1 表结构一样的表 test2CREATE TABLE test_2 LIKE test_1;执行下面 SQL,insert into test_2(column1,date_time) select column1, now() from test_1;这条 SQL 并不复杂从 test1 表查出数据写到 test2 表。但不知道写代码的小伙伴出于什么考虑在 column1 上加了双引号。这个 SQL 在 MySQL(8.0 版本)上执行是没有问题的但是放到了 GoldenDB 上就报错了因为双引号包着的字段返回的是 column1 这个字符串最终字段超长报错Data too long for column column1 at row 1。问题根因如果这个坑直接甩锅给 GoldenDB并不合适。为什么这么说呢公司专业的 DBA 大佬给了解答之所以这个 SQL 在 MySQL 上运行没问题在 GoldenDB 上就会出错是因为 ANSI_QUOTES 这个参数配置不一致。ANSI_QUOTES 是 MySQL 数据库中的 SQL 模式选项用于调整标识符与字符串常量的引用规则使其符合 ANSI SQL 标准。可以使用下面的 SQL 临时开启-- 仅对当前会话开启 SET SESSION sql_mode ANSI_QUOTES; -- 对之后的所有新连接生效重启后失效 SET GLOBAL sql_mode ANSI_QUOTES;或者修改配置文件开启这样可以永久生效。ANSI_QUOTES 介绍开启开启 ANSI_QUOTES 后双引号 () 被解释为标识符引号作用与反引号 () 相同用于引用数据库、表、字段等名称。例如下面 SQL 中的 name 被解释为列名而 my_table 被解释为表名。SELECT name FROM my_table;而单引号则被解释为字符串比如下面 SQL 查找结果返回 name 这个字符串SELECT name FROM my_table;关闭关闭 ANSI_QUOTES 后默认关闭双引号 () 被解释为字符串引号与单引号 () 的作用完全相同。反引号 () 被用于引用标识符如数据库名、表名、字段名。下面的两个 SQL 返回的都是 name 这个字符串SELECT name FROM my_table; SELECT name FROM my_table;为什么要使用 ansi_quotes 呢主要有 2 个原因1.兼容性和可移植性如果你的应用程序需要与多种遵循 ANSI SQL 标准的数据库如 PostgreSQL, Oracle, GoldenDB保持兼容启用 ANSI_QUOTES 会很有帮助。这可以统一使用双引号来引用标识符而不用担心数据库迁移会发生因为引号导致的异常。在信创改造的大背景下这个参数作用很大。2.SQL 规范一些开发团队要求必须遵循 SQL 标准明确区分单引号用于字符串双引号用于标识符。这可以使 SQL 的意图更加清晰减少歧义。总结ANSI_QUOTES 是 MySQL 数据库中的 SQL 模式选项用于调整标识符与字符串常量的引用规则使其符合 ANSI SQL 标准。这个配置开启对于 SQL 规范化和数据库迁移很有帮助。