更新时间:2024-12-06 GMT+08:00
分享

DDL

表1 DDL语法兼容介绍

概述

详细语法说明

差异

建表和修改表时支持创建主键、UNIQUE索引、外键约束

ALTER TABLE、CREATE TABLE

  • 在GaussDB中,当约束关联的表为ustore,且SQL语句中指定为using btree时,底层会建立为ubtree。
  • 在GaussDB中,允许将外键作为分区键。
  • 索引名、约束名、key名GaussDB是SCHEMA下唯一,MySQL是表下唯一。
  • MySQL和GaussDB主键上支持列的个数上限不同。

支持自增列

ALTER TABLE、CREATE TABLE

  • GaussDB的自动增长列建议为索引的第一个字段,否则建表时产生警告,MySQL自动增长列必须为索引第一个字段,否则建表时会报错。GaussDB含有自动增长列的表进行某些操作时会产生错误,例如:ALTER TABLE EXCHANGE PARTITION。
  • GaussDB的AUTO_INCREMENT = value语法,value必须为小于2^127的正数。MySQL可以为0,GaussDB不可以。
  • GaussDB中当自增值已经达到字段数据类型的最大值时,继续自增将产生错误。MySQL有些场景产生错误或警告,有些场景仍自增为最大值。
  • 不支持innodb_autoinc_lock_mode系统变量,GaussDB的GUC参数auto_increment_cache=0时,批量插入自动增长列的行为与MySQL系统变量innodb_autoinc_lock_mode=1相似。
  • GaussDB的自动增长列在导入数据或者进行Batch Insert执行计划的插入操作时,对于混合0、NULL和确定值的场景,如果产生错误,后续插入自增值不一定与MySQL完全一致。
    • 提供auto_increment_cache参数,可以控制预留自增值的数量。
  • GaussDB的并行导入或插入自动增长列触发自增时,每个并行线程预留的缓存值也只在其线程中使用,未完全使用完毕的话,也会出现表中自动增长列的值不连续的情况。并行插入产生的自增值结果无法保证与MySQL完全一致。
  • GaussDB的本地临时表中的自动增长列批量插入时不会预留自增值,正常场景不会产生不连续的自增值。MySQL临时表与普通表中的自动增长列自增结果一致。
  • GaussDB的SERIAL数据类型为原有的自增列,与AUTO_INCREMENT自增列有差异。MySQL的SERIAL数据类型就是AUTO_INCREMENT自增列。
  • GaussDB不允许auto_increment_offset的值大于auto_increment_increment的值,会产生错误。MySQL允许,并说明auto_increment_offset会被忽略。
  • 在表有主键或索引的情况下,ALTER TABLE命令重写表数据的顺序与MySQL不一定相同,GaussDB按表数据存储顺序重写,MySQL会按主键或索引顺序重写,导致自增值的顺序可能不同。
  • GaussDB使用ALTER TABLE命令添加或修改自增列时,第一次预留自增值的数量是表统计信息中的行数,统计信息的行数不一定与MySQL一致。
  • GaussDB的last_insert_id函数返回值为128位的整型。
  • GaussDB在触发器或用户自定义函数中自增时,刷新last_insert_id返回值。MySQL不刷新。
  • GaussDB的对GUC参数auto_increment_offset和auto_increment_increment设置超出范围的值会产生错误。MySQL会自动改为边界值。
  • sql_mode设置no_auto_value_on_zero参数,表定义的自动增长列为非NOT NULL约束,向表中插入数据不指定自动增长列的值时,GaussDB中自动增长列插入NULL值,且不触发自增;MySQL中自动增长列插入NULL值,触发自增。

支持前缀索引

CREATE INDEX、ALTER TABLE、CREATE TABLE

  • GaussDB中前缀长度不得超过2676,键值的实际长度受内部页面限制,若字段中含有多字节字符或者一个索引上有多个键,索引行长度可能会超限报错。
  • GaussDB中主键索引中不支持前缀键,创建或添加主键时不支持指定前缀长度。

支持指定字符集与排序规则

ALTER SCHEMA、ALTER TABLE、CREATE SCHEMA、CREATE TABLE

  • 指定库级字符集时,除BINARY字符集外,暂不支持创建新库/模式的字符集与数据库的server_encoding不同。
  • 指定表级、列级字符集和字符序时,MySQL支持指定与库级字符集、字符序不同的字符集和字符序。在GaussDB中,表级、列级字符集和字符序仅支持BINARY字符集、字符序或者与库级字符集、字符序相同的字符集、字符序。
  • 若重复指定字符集或字符序,仅最后一个生效。

修改表时支持在表第一列前面或者在指定列后面添加列

ALTER TABLE

-

修改列名称/定义语法

ALTER TABLE

  • 暂不支持DROP INDEX | DROP KEY | ORDER BY子项。
  • ALTER TABLE新增列时,MySQL指定字段为NOT NULL时,会将NULL值转为对应类型的默认值插入该列,GaussDB会检查NULL值。

创建分区表语法

CREATE TABLE PARTITION、CREATE TABLE SUBPARTITION

  • MySQL在以下场景支持表达式,不支持多个分区键:
    • 使用LIST分区/RANGE分区策略,不指定COLUMNS关键字。
    • 使用HASH分区策略。
  • MySQL在以下场景不支持表达式,支持多个分区键:
    • 使用LIST分区/RANGE分区策略,指定COLUMNS关键字。
    • 使用KEY分区策略。
  • GaussDB不支持使用表达式作为分区键。
  • GaussDB仅在以下场景支持使用多个分区键:使用LIST分区/RANGE分区策略,且不指定二级分区。
  • GaussDB分区表不支持用虚拟生成列作为分区键。

建表和修改表时支持指定表级和列级comment

CREATE TABLE、ALTER TABLE

-

创建索引时支持指定索引级comment

CREATE INDEX

-

交换普通表和分区表分区的数据

ALTER TABLE PARTITION

ALTER TABLE EXCHANGE PARTITION的差异点:

  • 对于自增列,MySQL执行alter exchange partition后,自增列会被重置;GaussDB 则不会被重置,自增列则按照旧的自增值递增。
  • MySQL表或分区使用tablespace时,则无法进行分区和普通表数据的交换;GaussDB表或分区使用不同的tablespace时,仍可进行分区和普通表数据的交换。
  • 对于列默认值,MySQL不会校验默认值,因此默认值不同时也可进行分区和普通表数据的交换;GaussDB会校验默认值,如果默认值不同,则无法进行分区和普通表数据的交换。
  • MySQL在分区表或普通表上进行DROP列操作后,表结构仍然一致,则可进行分区和普通表数据的交换;GaussDB需要保证普通表和分区表的被删除列严格对齐才能进行分区和普通表数据的交换。
  • MySQL和GaussDB的哈希算法不同,所以两者在相同的hash分区存储的数据可能不一致,导致最后交换的数据也可能不一致。
  • MySQL的分区表不支持外键,普通表包含外键或其他表引用普通表的外键,则无法进行分区和普通表数据的交换;GaussDB的分区表支持外键,在两个表的外键约束一致时,则可进行分区和普通表数据的交换,GaussDB的分区表不带外键,普通表有其他表引用,如果分区表和普通表表一致,则可进行分区和普通表数据的交换。

修改分区表的分区键信息

ALTER TABLE

MySQL支持修改分区表的分区键信息,GaussDB中不支持。

支持CREATE TABLE ... LIKE语法

CREATE TABLE ... LIKE

  • 在MySQL 8.0.16 之前的版本中,CHECK约束会被语法解析但功能会被忽略,表现为不复制CHECK约束,GaussDB支持复制CHECK约束。
  • 对于主键约束名称,在建表时,MySQL所有主键约束名称固定为PRIMARY KEY,GaussDB不支持复制。
  • 对于唯一键约束名称,在建表时,MySQL支持复制,GaussDB不支持复制。
  • 对于CHECK约束名称,在建表时,MySQL 8.0.16 之前的版本无CHECK约束信息,GaussDB支持复制。
  • 对于索引名称,在建表时,MySQL支持复制,GaussDB不支持复制。
  • 在跨sql_mode模式建表时,MySQL受宽松模式和严格模式控制,GaussDB可能存在严格模式失效的情况。

    例如:源表存在默认值“0000-00-00”,在“no_zero_date”严格模式下,GaussDB建表成功,且包含默认值“0000-00-00”,严格模式失效;而MySQL建表失败,受严格模式控制。

支持增加子分区语法

ALTER TABLE [ IF EXISTS ] { table_name  [*] | ONLY table_name | ONLY ( table_name  )} add_clause;
add_clause:
ADD {{partition_less_than_item | partition_start_end_item | partition_list_item} |
PARTITION({partition_less_than_item | partition_start_end_item | partition_list_item})}

保留原分区表语法。

不支持下述语法添加多分区:

ALTER TABLE table_name ADD PARTITION (partition_definition1, partition_definition1,…);

仅支持原有添加多分区语法:

ALTER TABLE table_name ADD PARTITION (partition_definition1),  ADD PARTITION (partition_definition2[y1] ), …;

TRUNCATE子分区语法

ALTER TABLE [ IF EXISTS ]  table_name  
    truncate_clause;

支持子项有差异,对于truncate_clause:

  • M-Compatibility模式:
    TRUNCATE PARTITION  { { ALL | partition_name [, ...] } | FOR (  partition_value [, ...] )  } [ UPDATE GLOBAL INDEX ]
  • MySQL支持:
    TRUNCATE PARTITION {partition_names | ALL}

主键索引名

CREATE TABLE table_name ( col_definitine ,PRIMARY KEY [index_name] [ USING method ] ( { column_name | ( expression ) }[ ASC | DESC ] } [, ... ] ) index_parameters [USING method| COMMENT 'string'])

GaussDB中的主键指定索引名后创建的索引名为用户所指定的索引名,MySQL索引名为PRIMARY。

删除有依赖的对象

DROP drop_type name CASCADE;

在GaussDB中,删除有依赖的对象需要加CASCADE,MySQL不需要。

NOT NULL约束不允许插入NULL值

CREATE TABLE t1(id int NOT NULL DEFAULT 8);
INSERT INTO t1 VALUES(NULL);
INSERT INTO t1 VALUES(1),(NULL),(2);

在MySQL宽松模式下,会将NULL进行类型转换,并成功插入数据;在MySQL严格模式下不允许插入NULL值。在GaussDB不支持此特性,在宽松模式和严格模式下均不允许插入NULL值。

CHECK约束生效

CREATE TABLE

  • CREATE TABLE带CHECK约束的时候,MySQL 8.0会生效,MySQL 5.7只解析语法但不生效。GaussDB在此功能上同步MySQL 8.0版本,且GaussDB CHECK约束可以引用其他列,而MySQL不能。
  • GaussDB 一个表中最多只能加32767个CHECK约束。

索引的algorithm和lock选项不起作用

CREATE INDEX ...

DROP INDEX ...

M-Compatibility模式的CREATE/DROP INDEX语句中INDEX选项algorithm_option和lock_option目前只在语法上支持,创建时不报错,但实际不起作用。

CREATE TABLE hash分区和二级分区的存储与MySQL不同

CREATE TABLE

GaussDB的CREATE TABLE语句中hash分区表和二级分区表所使用的hash函数与MySQL不一致,因此hash分区表和二级分区表的存储与MySQL有区别。

分区表索引

CREATE INDEX

  • GaussDB的分区表索引分为LOCAL和GLOBAL两种。LOCAL索引与某个具体分区绑定,而GLOBAL索引则对应整个分区表。
  • LOCAL和GLOBAL索引的创建方法和默认规则具体说明参见《开发指南》中”SQL语法 > SQL语句 > C > CREATE INDEX”章节,例如:在非分区键上创建唯一索引,会默认创建为GLOBAL索引。
  • MySQL无GLOBAL索引的概念。在GaussDB中,当分区表索引为GLOBAL索引时,对表分区进行DROP、TRUNCATE、EXCHANGE等操作不会默认更新GLOBAL索引,进而导致GLOBAL索引失效,导致后续语句无法选中该索引。为了避免这种场景,建议用户在使用分区操作语法时在最后显指定UPDATE GLOBAL INDEX子句,或配置全局GUC参数enable_gpi_auto_update为true(推荐),使得在进行分区操作时自定更新GLOBAL索引。

CREATE/ALTER TABLE语句中分区表为KEY分区,不支持指定algorithm。部分分区定义入参不支持表达式。

CREATE TABLE、ALTER TABLE

GaussDB的CREATE/ALTER TABLE语句中分区表为KEY分区,不支持指定algorithm。

不支持表达式入参的语法:
  • PARTITION BY HASH()
  • PARTITION BY KEY()
  • VALUES LESS THAN()

分区表不支持LINEAR/KEY hash

CREATE TABLE ... PARTITION ...

GaussDB分区表不支持LINEAR/KEY hash。

check和auto_increment语法不能作用在同一字段

CREATE TABLE

由于MySQL 5.7的check字段不生效,check和auto_increment同时作用于同一字段只有auto_increment生效,但GaussDB报错。

删除存在依赖关系的表

DROP TABLE

GaussDB删除存在依赖的表必须加上CASCADE才能成功,MySQL不需要。

新增外键约束、修改外键约束的参考字段、被参考字段

CREATE TABLE、ALTER TABLE

  • GaussDB创建外键时支持指定MATCH FULL和MATCH SIMPLE选项,如果用户指定了MATCH PARTIAL选项,会提示报错信息。MySQL中支持指定以上选项,但并不生效,行为与MATCH SIMPLE一致。
  • GaussDB创建外键时可以指定ON [ UPDATE | DELETE ] SET DEFAULT选项。MySQL创建外键时指定ON [ UPDATE | DELETE ] SET DEFAULT选项会报错。
  • GaussDB创建外键时,必须在被参考表的被参考列上创建唯一索引。MySQL创建外键时,需要在被参考表的被参考列上创建索引,可以不是唯一索引。
  • GaussDB创建外键时,不需要在参考表的参考列上创建索引。MySQL创建外键时,需要在参考表的参考列上创建索引,如果在参考表的参考列上没有索引,则会自动添加一条对应的索引,在删除外键时,不会删除自动添加的索引。
  • GaussDB的参考表和被参考表可以都是临时表,不可以在临时表和非临时表之间创建外键。MySQL无法使用临时表作为参考表或被参考表。MySQL在创建外键指定被参考表时,不会匹配当前会话已创建的临时表。
  • GaussDB创建外键时可以不指定被参考表的被参考字段名,此时会将被参考表中的主键作为外键的被参考字段。MySQL中,必须指定被参考表的被参考字段。
  • GaussDB无论foreign_key_checks是否关闭,都可以修改参考字段或被参考字段的数据类型。MySQL仅当foreign_key_checks为off时,才可以修改参考字段或被参考字段的数据类型。
  • GaussDB可以删除参考表的参考字段,此时会级联删除相关外键约束。MySQL在删除参考表的参考字段时,会发生删除失败。
  • GaussDB当删除包含被参考表的模式,且参考表在其他模式中时, foreign_key_checks为on时,会级联删除参考表上的外键约束。在MySQL中,如果foreign_key_checks为on,则删除失败。

表定义相关选项

CREATE TABLE... 、 ALTER TABLE ...

  • GaussDB不支持以下选项:AVG_ROW_LENGTH、CHECKSUM、COMPRESSION、CONNECTION、DATA DIRECTORY、INDEX DIRECTORY、DELAY_KEY_WRITE、ENCRYPTION、INSERT_METHOD、KEY_BLOCK_SIZE、MAX_ROWS、MIN_ROWS、PACK_KEYS、PASSWORD、STATS_AUTO_RECALC、STATS_PERSISTENT、STATS_SAMPLE_PAGES。
  • 以下选项在GaussDB中不报错,但实际上也不生效:ENGINE、ROW_FORMAT。

CMK密钥轮转,轮换加密COLUMN ENCRYPTION KEY的CLIENT MASTER KEY,对COLUMN ENCRYPTION KEY明文进行重加密。

ALTER COLUMN ENCRYPTION KEY

M-Compatibility模式不支持全密态。因此不支持该语法。

密态等值查询特性使用多级加密模型,主密钥加密列密钥,列密钥加密数据。本语法用于创建主密钥对象。

CREATE CLIENT MASTER KEY

M-Compatibility模式不支持全密态。因此不支持该语法。

创建一个列加密密钥,该密钥可用于加密表中的指定列。

CREATE COLUMN ENCRYPTION KEY

M-Compatibility模式不支持全密态。因此不支持该语法。

全密态功能,传输密钥到服务端缓存,只在开启内存解密逃生通道的情况下使用。

\send_token

M-Compatibility模式不支持全密态。因此不支持该语法。

全密态功能,传输密钥到服务端缓存,只在开启内存解密逃生通道的情况下使用。

\st

M-Compatibility模式不支持全密态。因此不支持该语法。

全密态功能,销毁服务端缓存的密钥,只在开启内存解密逃生通道的情况下使用。

\clear_token

M-Compatibility模式不支持全密态。因此不支持该语法。

全密态功能,销毁服务端缓存的密钥,只在开启内存解密逃生通道的情况下使用。

\ct

M-Compatibility模式不支持全密态。因此不支持该语法。

在全密态数据库特性中,用于设置访问外部密钥管理者的参数。

\key_info KEY_INFO

M-Compatibility模式不支持全密态。因此不支持该语法。

全密态功能,用于开启三方动态库功能与加载三方动态库时的参数设置。

\crypto_module_info MODULE_INFO

M-Compatibility模式不支持全密态。因此不支持该语法。

全密态功能,用于开启三方动态库功能与加载三方动态库时的参数设置。

\cmi MODULE_INFO

M-Compatibility模式不支持全密态。因此不支持该语法。

generated always as语句不能再引用由generated always as生成的列。

Generated Always AS

GaussDB的generated always as语句不能再引用由generated always as生成的列,MySQL可以。

支持更改表名语法

ALTER TABLE tbl_name RENAME [TO | AS | =] new_tbl_name;

或RENAME {TABLE | TABLES} tbl_name TO new_tbl_name [, tbl_name2 TO new_tbl_name2, ...];

  • GaussDB的ALTER RENAME语法仅支持修改表名称功能操作,不能耦合其它功能操作。
  • GaussDB中,仅旧表名字段支持使用schema.table_name格式,且新表名与旧表名将属于同一个Schema。
  • GaussDB不支持新旧表跨Schema重命名操作;但如有权限,则可在当前Schema下修改其他Schema下表名称。
  • GaussDB的RENAME多组表的语法支持全为本地临时表的重命名,不支持本地临时表和非本地临时表组合的场景。

禁用GUC参数enable_expr_fusion

SET enable_expr_fusion= ON;

M-Compatibility模式暂不支持GUC参数enable_expr_fusion打开。

支持CREATE VIEW AS SELECT语法

CREATE VIEW table_name AS query;
  • 当不开启精度传递开关(m_format_behavior_compat_options不开启enable_precision_decimal选项)时,针对以下类型,不支持CREATE VIEW view_name AS query语法中query包含计算操作(如函数调用、使用操作符计算),仅允许直接的字段调用(如 SELECT col1 FROM table1)。精度传递开关打开(m_format_behavior_compat_options开启enable_precision_decimal选项)时可以使用。
    • BINARY[(n)]
    • VARBINARY(n)
    • CHAR[(n)]
    • VARCHAR(n)
    • TIME[(p)]
    • DATETIME[(p)]
    • TIMESTAMP[(p)]
    • BIT[(n)]
    • NUMERIC[(p[,s])]
    • DECIMAL[(p[,s])]
    • DEC[(p[,s])]
    • FIXED[(p[,s])]
    • FLOAT4[(p, s)]
    • FLOAT8[(p,s)]
    • FLOAT[(p)]
    • REAL[(p, s)]
    • FLOAT[(p, s)]
    • DOUBLE[(p,s)]
    • DOUBLE PRECISION[(p,s)]
    • TEXT
    • TINYTEXT
    • MEDIUMTEXT
    • LONGTEXT
    • BLOB
    • TINYBLOB
    • MEDIUMBLOB
    • LONGBLOB
  • 在query为简单查询场景下,M-Compatibility模式针对上述类型的计算操作进行报错提示,例如:
    m_db=# CREATE TABLE TEST (salary int(10));
    CREATE TABLE
    
    m_db=# INSERT INTO TEST VALUES(8000);
    INSERT 0 1
    
    m_db=# CREATE VIEW view1 AS SELECT salary/10 as te FROM TEST;
    ERROR:  Unsupported type numeric used with expression in CREATE VIEW statement.
    
    m_db=# CREATE VIEW view2 AS SELECT sec_to_time(salary) as te FROM TEST;
    ERROR:  Unsupported type time used with expression in CREATE VIEW statement.
  • 在query为复合查询,子查询等非简单查询场景下,M-Compatibility模式针对上述类型的计算操作与MySQL存在差异,M-Compatibility模式下新创建表的数据类型列精度属性不保留。
  • CREATE VIEW AS SELECT场景。当UNION嵌套子查询时,MySQL会对内层子查询新建临时表。若临时表的返回类型为tinytext、text、mediumtext、longtext时,MySQL会按照所属类型默认的最大字节长度进行计算。而GaussDB会以创建临时表的实际字节长度进行计算。因此最终GaussDB聚合结果的文本类型有可能小于MySQL的聚合结果。如MySQL返回longtext,GaussDB返回mediumtext。如:

    MySQL 5.7行为:

    mysql> CREATE TABLE IF NOT EXISTS tb_1 (id int,col_text2 text);
    Query OK, 0 rows affected (0.02 sec)
    
    mysql> CREATE TABLE IF NOT EXISTS tb_2 (id int,col_text2 text);
    Query OK, 0 rows affected (0.02 sec)
    
    mysql> CREATE VIEW v1 AS SELECT * FROM (SELECT cast(col_text2 AS char) c37 FROM tb_1) t1
        -> UNION ALL SELECT * FROM (SELECT cast(col_text2 as char) c37 FROM tb_2) t2;
    Query OK, 0 rows affected (0.00 sec)
    
    mysql> DESC v1;
    +-------+----------+------+-----+---------+-------+
    | Field | Type     | Null | Key | Default | Extra |
    +-------+----------+------+-----+---------+-------+
    | c37   | longtext | YES  |     | NULL    |       |
    +-------+----------+------+-----+---------+-------+
    1 row in set (0.00 sec)

    GaussDB行为:

    mysql_regression=# CREATE TABLE IF NOT EXISTS tb_1 (id int,col_text2 text);
    CREATE TABLE
    mysql_regression=# CREATE TABLE IF NOT EXISTS tb_2 (id int,col_text2 text);
    CREATE TABLE
    mysql_regression=# CREATE VIEW v1 AS SELECT * FROM (SELECT cast(col_text2 AS char) c37 from tb_1) t1
    mysql_regression-# UNION ALL SELECT * FROM (SELECT cast(col_text2 AS char) c37 FROM tb_2) t2;
    CREATE VIEW
    mysql_regression=# DESC v1;
     Field |    Type    | Null | Key | Default | Extra 
    -------+------------+------+-----+---------+-------
     c37   | mediumtext | YES  |     |         | 
    (1 row)
  • 使用bitstring常量进行视图创建时,与MySQL不一致,MySQL转换成hexstring进行创建,GaussDB使用bitstring直接创建。由于bitstring常量为unsigned值,因此GaussDB创建视图的属性为unsigned。
    • MySQL 5.7行为:
    mysql> SELECT version();
    +------------------+
    | version()        |
    +------------------+
    | 5.7.44-debug-log |
    +------------------+
    1 row in set (0.00 sec)
    
    mysql> DROP VIEW IF EXISTS v1;
    Query OK, 0 rows affected, 1 warning (0.00 sec)
    
    mysql> CREATE VIEW v1 AS SELECT b'101'/b'101' AS c22;
    Query OK, 0 rows affected (0.01 sec)
    
    mysql> DESC v1;
    +-------+-----------------------+------+-----+---------+-------+
    | Field | Type                  | Null | Key | Default | Extra |
    +-------+-----------------------+------+-----+---------+-------+
    | c22   | decimal(5,4) unsigned | YES  |     | NULL    |       |
    +-------+-----------------------+------+-----+---------+-------+
    1 row in set (0.00 sec)
    
    mysql> SHOW CREATE VIEW v1;
    +------+--------------------------------------------------------------------------------------------------------------+----------------------+----------------------+
    | View | Create View                                                                                                  | character_set_client | collation_connection |
    +------+--------------------------------------------------------------------------------------------------------------+----------------------+----------------------+
    | v1   | CREATE ALGORITHM=UNDEFINED DEFINER=`omm`@`%` SQL SECURITY DEFINER VIEW `v1` AS SELECT (0x05 / 0x05) AS `c22` | utf8mb4              | utf8mb4_general_ci   |
    +------+--------------------------------------------------------------------------------------------------------------+----------------------+----------------------+
    1 row in set (0.00 sec)
    • GaussDB行为:
    m_db=# DROP VIEW IF EXISTS v1;
    DROP VIEW
    
    m_db=# CREATE VIEW v1 AS SELECT b'101'/b'101' AS c22;
    CREATE VIEW
    
    m_db=# DESC v1;
     Field |     Type     | Null | Key | Default | Extra 
    -------+--------------+------+-----+---------+-------
     c22   | decimal(5,4) | YES  |     |         | 
    (1 row)

索引名可重名范围

CREATE TABLE、CREATE INDEX

MySQL中索引名在一个表下唯一,在不同的表下可以有相同的索引名。M-Compatibility模式中的索引名在同一个SCHEMA下唯一,在同一的SCHEMA下不可用相同的索引名。在M-Compatibility模式下,针对会自动创建索引的约束和key,也会有相同的规则。

视图依赖差异

CREATE VIEW、ALTER TABLE

MySQL中视图存储,只记录目标表的表名、列名、数据库名信息,不记录目标表的唯一标识;GaussDB会将创建视图时的SQL解析,并存储目标表的唯一标识。因此存在如下差异:

  • 修改存在视图依赖的列的数据类型,MySQL中对应的视图不感知目标表的修改,因此可以修改成功;GaussDB视图中的列禁止修改数据类型,因此无法修改该列的数据类型。
  • 重命名存在视图依赖的列,MySQL中对应的视图不感知目标表的修改,因此可以修改成功,但是后续无法查询该视图;GaussDB视图中,每个列精确存储了其对应的表和列的唯一标识,因此表中的列名可以修改成功,视图中的列名不被修改,且后续可以查询该视图。

外键差异

CREATE TABLE

  • GaussDB外键约束对类型不敏感,如果主表和从表对应的字段数据类型存在隐式类型转换就可以建成。MySQL外键类型敏感。如果两个表对应的列类型不同外键无法建成。
  • MySQL不支持通过MODIFY COLUMN或CHANGE COLUMN方式修改表列外键所在列的数据类型或列名等,GaussDB可以。

索引升降序差异

CREATE INDEX

在MySQL 5.7中,ASC | DESC被解析但是被忽略,默认行为为ASC;在MySQL 8.0及GaussDB中,ASC | DESC被解析且生效。

修改视图定义

CREATE OR REPLACE VIEW、ALTER VIEW

  • MySQL可以对视图的任何属性进行修改;GaussDB禁止修改不可更新视图当中的列名、列类型以及删除列,允许修改可更新视图列名、列类型以及删除列。
  • MySQL对嵌套视图的底层视图执行修改列操作后,只要列名存在,上层视图就可以正常使用;GaussDB对嵌套视图中底层视图做修改列名、列类型以及删除列操作,会导致上层视图不可用。

ANALYZE分区语法

ALTER TABLE tbl_name ANALYZE PARTITION {partition_names | ALL}
  • GaussDB下该语法仅支持分区统计信息收集功能。
  • MySQL下分区名partition_names 大小写不区分,GaussDB下分区名不带反引号的情况下不区分大小写,带反引号时区分大小写。
  • GaussDB下执行成功回显ALTER TABLE,执行报错由已有错误码报错信息决定,MySQL下执行结果以表格回显形式显示。

支持虚拟生成列语法

[GENERATED ALWAYS] AS ( generation_expr ) [STORED | VIRTUAL]

  • MySQL数据库中虚拟生成列支持创建索引,GaussDB数据库中不支持。
  • MySQL数据库中虚拟生成列支持作为分区键,GaussDB数据库中不支持。
  • GaussDB数据库中生成列的CHECK约束兼容MySQL 8.0数据库的行为,即CHECK约束检查生效。
  • MySQL数据库中存储生成列作为分区键时,支持ALTER TABLE修改存储生成列,GaussDB数据库中不支持。
  • MySQL数据库中向可被更新的视图中更新生成列的数据时,支持指定关键字DEFAULT,GaussDB数据库中不支持。
  • MySQL数据库中虚拟生成列支持IGNORE特性,GaussDB数据库中不支持。
  • 在GaussDB数据库中查询虚拟生成列等价于查询虚拟生成列的表达式(在表达式与列定义的数据类型、字符集或字符序不一致时,会将表达式向列定义的类型做隐式转换处理),此行为在查询虚拟生成列用于建表或建视图等其他行为,可能导致数据类型与MySQL数据库存在差异。例如:在使用CREATE TABLE AS建表时,如果源表中虚拟生成列定义为FLOAT类型,在目标表中其对应列的数据类型可能为DOUBLE,与MySQL数据库存在差异。

通过CREATE TABLE SELECT新建表并插入数据

CREATE TABLE [AS] SELECT

  • 不支持创建分区表。
  • 不支持replace/ignore。
  • 如果SELECT列非直接表列,则默认允许NULL且无默认值。如:CREATE TABLE t1 SELECT unix_timestamp('2008-01-02 09:08:07.3465') AS a,创建出来的新表的字段a允许为NULL且无默认值。
  • 如果需要使用完整的功能,需要将GUC参数m_format_behavior_compat_options开启enable_precision_decimal选项,否则由于版本兼容性问题,涉及数据类型精度相关的类型将导致行为报错。比如:如果SELECT列包含非直接表列(表达式、函数、常量等),以及union场景(因为涉及结果类型推导),都会报错。
  • 使用CREATE TABLE AS SELECT建表,表中列名最大长度为63,超过时超过部分将会被截断;MySQL超过最大长度64时报错。

ALTER TABLE tabname;

ALTER TABLE tabname;

GaussDB中不支持tablename为空。

分区键暂不支持key的column_list为空

CREATE TABLE ... PARTITION ...

GaussDB中分区键暂不支持key的column_list为空。

UTF8字符集编码最大长度不同,导致创建表/视图的字段长度产生差异

CREATE TABLE [AS] SELECT; CREATE VIEW [AS] SELECT

  • 当MySQL的字符集为utf8 ,GaussDB的字符集为utf8(utf8mb4)时,由于MySQL 的 UTF8编码最大为3字节,GaussDB的utf8(utf8mb4)的编码最大为4字节,开启guc参数m_format_behavior_compat_options = 'enable_precision_decimal'时,CREATE TABLE AS(ctas) 和CREATE VIEW AS(cvas)创建文本类型时(包括二进制文本)可能存在差异:

    由于ctas和cvas的场景会依赖字符集的最长字节长度,例如某一节点返回的最大字节长度GaussDB与MySQL均为1024,那么最终返回的字符长度,MySQL为341(1024/3),GaussDB为256(1024/4)。如:

    MySQL 5.7行为:

    mysql> CREATE TABLE t1 AS SELECT (case when true then min(521.2312) else GROUP_CONCAT(115.0414) end) res1;
    Query OK, 1 row affected (0.06 sec)
    Records: 1  Duplicates: 0  Warnings: 0
    
    mysql> DESC t1;
    +-------+--------------+------+-----+---------+-------+
    | Field | Type         | Null | Key | Default | Extra |
    +-------+--------------+------+-----+---------+-------+
    | res1  | varchar(341) | YES  |     | NULL    |       |
    +-------+--------------+------+-----+---------+-------+
    1 row in set (0.01 sec)

    GaussDB行为:

    mysql_regression=# CREATE TABLE t1 AS SELECT (case when true then min(521.2312) else GROUP_CONCAT(115.0414) end) res1;
    INSERT 0 1
    mysql_regression=# DESC t1;
     Field |     Type     | Null | Key | Default | Extra 
    -------+--------------+------+-----+---------+-------
     res1  | varchar(256) | YES  |     |         | 
    (1 row)

指定字段的默认值

CREATE TABLE、ALTER TABLE

  • MySQL 5.7指定默认值时,仅支持不带括号形式的默认值。MySQL 8.0与GaussDB支持带括号形式的默认值。
    -- GaussDB
    m_db=# DROP TABLE IF EXISTS t1, t2;
    DROP TABLE
    m_db=# CREATE TABLE t1(a DATETIME DEFAULT NOW());
    CREATE TABLE
    m_db=# CREATE TABLE t2(a DATETIME DEFAULT (NOW()));
    CREATE TABLE
    
    -- MySQL 5.7
    mysql> DROP TABLE IF EXISTS t1, t2;
    Query OK, 0 rows affected (0.04 sec)
    
    mysql> CREATE TABLE t1(a DATETIME DEFAULT NOW());
    Query OK, 0 rows affected (0.04 sec)
    
    mysql> CREATE TABLE t2(a DATETIME DEFAULT (NOW()));
    ERROR 1064 (42000): You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '(NOW()))' at line 1
    
    -- MySQL 8.0
    mysql> DROP TABLE IF EXISTS t1, t2;
    Query OK, 0 rows affected (0.17 sec)
    
    mysql> CREATE TABLE t1(a DATETIME DEFAULT NOW());
    Query OK, 0 rows affected (0.19 sec)
    
    mysql> CREATE TABLE t2(a DATETIME DEFAULT (NOW()));
    Query OK, 0 rows affected (0.20 sec)
  • MySQL给BLOB、TEXT、JSON数据类型指定默认值时必须给默认值添加括号,GaussDB给上述数据类型指定默认值时可以不添加括号。
  • GaussDB指定默认值时不会校验默认值是否溢出;MySQL指定不带括号形式的默认值时会校验是否溢出,指定带括号形式的默认值时不会校验是否溢出。
  • GaussDB支持使用DATE/TIME/TIMESTAMP开头的时间常量给字段指定默认值,MySQL使用DATE/TIME/TIMESTAMP开头的时间常量给字段指定默认值时必须在默认值外添加括号。
    -- GaussDB
    m_db=# DROP TABLE IF EXISTS t1, t2;
    DROP TABLE
    m_db=# CREATE TABLE t1(a TIMESTAMP DEFAULT TIMESTAMP '2000-01-01 00:00:00');
    CREATE TABLE
    m_db=# CREATE TABLE t2(a TIMESTAMP DEFAULT (TIMESTAMP '2000-01-01 00:00:00'));
    CREATE TABLE
    
    -- MySQL 5.7
    mysql> DROP TABLE IF EXISTS t1, t2;
    Query OK, 0 rows affected (0.02 sec)
    
    mysql> CREATE TABLE t1(a TIMESTAMP DEFAULT TIMESTAMP '2000-01-01 00:00:00');
    ERROR 1067 (42000): Invalid default value for 'a'
    mysql> CREATE TABLE t2(a TIMESTAMP DEFAULT (TIMESTAMP '2000-01-01 00:00:00'));
    ERROR 1064 (42000): You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '(TIMESTAMP '2000-01-01 00:00:00'))' at line 1
    
    -- MySQL 8.0
    mysql> DROP TABLE IF EXISTS t1, t2;
    Query OK, 0 rows affected (0.14 sec)
    
    mysql> CREATE TABLE t1(a TIMESTAMP DEFAULT TIMESTAMP '2000-01-01 00:00:00');
    ERROR 1067 (42000): Invalid default value for 'a'
    mysql> CREATE TABLE t2(a TIMESTAMP DEFAULT (TIMESTAMP '2000-01-01 00:00:00'));
    Query OK, 0 rows affected (0.19 sec)

相关文档