原作者:杨明翰
在MySQL中如果不指定sql_mode 等于 ANSI或者ONLY_FULL_GROUP_BY时,select、having和order by 子句可以使用非聚合列。这种写法虽然不规范,也不能保证非聚合列返回数据的唯一性,但是在实际使用中还是比较常见的。
# SQL_mode不包含ANSI或者ONLY_FULL_GROUP_BY
mysql> select @@sql_mode;
+--------------------------------------------+
| @@sql_mode |
+--------------------------------------------+
| STRICT_TRANS_TABLES,NO_ENGINE_SUBSTITUTION |
+--------------------------------------------+
1 row in set (0.00 sec)
mysql> select * from t3;
+------+-------+------+
| id | name | age |
+------+-------+------+
| 1 | andy | 60 |
| 2 | lee | 30 |
| 3 | yun | 50 |
| 4 | tony | 60 |
| 5 | candy | 30 |
| 6 | luss | 50 |
+------+-------+------+
6 rows in set (0.00 sec)
mysql> select name,age from t3 group by age;
+------+------+
| name | age |
+------+------+
| andy | 60 |
| lee | 30 |
| yun | 50 |
+------+------+
3 rows in set (0.00 sec)
这种在MySQL中“特殊”的语法,在PG、MogDB等数据库中执行会报错。导致迁移到其他数据库时业务侧需要做针对性的调整,增加了迁移的工作量。
##在MogDB中创建一个MySQL兼容性的数据库,执行相同SQL 报错。
MogDB=# create database db_m dbcompatibility ='B';
CREATE DATABASE
MogDB=# \c db_m
Non-SSL connection (SSL connection is recommended when requiring high-security)
You are now connected to database "db_m" as user "omm".
db_m=# create table t3(id int ,name varchar(255),age int);
CREATE TABLE
db_m=# insert into t3 values (1,'andy',60),(2,'lee',30),(3,'yun',50), (4,'tony',60),(5,'candy',30),(6,'luss',50);
INSERT 0 6
db_m=# select * from t3;
id | name | age
----+-------+-----
1 | andy | 60
2 | lee | 30
3 | yun | 50
4 | tony | 60
5 | candy | 30
6 | luss | 50
(6 rows)
db_m=# select name,age from t3 group by age;
ERROR: column "t3.name" must appear in the GROUP BY clause or be used in an aggregate function
LINE 1: select name,age from t3 group by age;
为了解决这个常见需求,MogDB提供了dolphin 插件包,支持通过设置sql_mode兼容 select子句使用非聚合列的语法。下面进行测试
- 安装dolphin插件
su - omm
cd $GPHOME/script/
mkdir -p static
#下载对应版本的插件安装包
cd static/
wget -c https://cdn-mogdb.enmotech.com/mogdb-media/3.0.0/Plugins-3.0.0-CentOS-x86_64.tar.gz
chmod +x Plugins-3.0.0-CentOS-x86_64.tar.gz
[omm@node1 static]$ gs_install_plugin_local --all
SUCCESS: pg_trgm
SUCCESS: dblink
SUCCESS: orafce
SUCCESS: wal2json
SUCCESS: pg_repack
SUCCESS: pg_bulkload
SUCCESS: pg_prewarm
SUCCESS: dolphin
SUCCESS: whale
SUCCESS: postgis
注意:只有以MySQL兼容创建的数据库才能使用dolphin插件 否则会报错
MogDB=# CREATE EXTENSION dolphin;
ERROR: please create extension "dolphin" with B type DBCOMPATIBILITY
以MySQL兼容模式创建数据库,安装dolphin插件
#安装前需要设置系统参数并重启数据库
MogDB=# alter system set shared_preload_libraries=dolphin;
NOTICE: please restart the database for the POSTMASTER level parameter to take effect.
ALTER SYSTEM SET
#以MySQL兼容模式创建数据库,安装dolphin脚本
MogDB=# create database db_mysql dbcompatibility = 'B';
CREATE DATABASE
MogDB=# \c db_mysql
Non-SSL connection (SSL connection is recommended when requiring high-security)
You are now connected to database "db_mysql" as user "omm".
db_mysql=# CREATE EXTENSION dolphin;
CREATE EXTENSION
dolphin插件提供了类似MySQL的sql_mode参数,可以通过调整sql_mode的配置实现更强的MySQL兼容性
## 默认为严格模式,在此模式下 非聚合列的查询会报错
db_mysql=# create table t3(id int ,name varchar(255),age int);
CREATE TABLE
db_mysql=# insert into t3 values (1,'andy',60),(2,'lee',30),(3,'yun',50), (4,'tony',60),(5,'candy',30),(6,'luss',50);
INSERT 0 6
db_mysql=# select * from t3;
id | name | age
----+-------+-----
1 | andy | 60
2 | lee | 30
3 | yun | 50
4 | tony | 60
5 | candy | 30
6 | luss | 50
(6 rows)
db_mysql=# select name,age from t3 group by age;
ERROR: column "t3.name" must appear in the GROUP BY clause or be used in an aggregate function
LINE 1: select name,age from t3 group by age;
我们将sql_mode置空,再来执行非聚合列的查询就可以正常返回结果。
db_mysql=# set sql_mode = '';
SET
db_mysql=# select name,age from t3 group by age;
name | age
------+-----
andy | 60
yun | 50
lee | 30
(3 rows)
安装并使用dolphin插件可以显著的提升MySQL兼容性,除了非聚合列的查询外 对 空值的处理、timestamp的默认值设置 都可以做到和MySQL的处理逻辑一致。 有兴趣可以深入研究下。
「喜欢这篇文章,您的关注和赞赏是给作者最好的鼓励」
关注作者
【版权声明】本文为墨天轮用户原创内容,转载时必须标注文章的来源(墨天轮),文章链接,文章作者等基本信息,否则作者和墨天轮有权追究责任。如果您发现墨天轮中有涉嫌抄袭或者侵权的内容,欢迎发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。




