该语句用于在 OceanBase 数据库中创建新表。

    格式

    1. CREATE TABLE [IF NOT EXISTS] tblname
    2. (create_definition,...)
    3. [table_options]
    4. [partition_options];
    5. CREATE TABLE [IF NOT EXISTS] tblname
    6. LIKE oldtblname
    7. create_definition:
    8. colname column_definition
    9. | PRIMARY KEY (index_col_name [, index_col_name...]) [index_type] [index_options]...
    10. | {INDEX|KEY} [indexname] (index_col_name,...) [index_type] [index_options]...
    11. | UNIQUE [INDEX|KEY] [indexname] (index_col_name,...) [index_type] [index_options]...
    12. | FULLTEXT [INDEX|KEY] [indexname] (index_col_name,...) CTXCAT(index_col_name,...) [index_options]...
    13. column_definition:
    14. data_type [NOT NULL | NULL] [DEFAULT defaultvalue] [AUTO_INCREMENT] [UNIQUE [KEY]]
    15. | [[PRIMARY] KEY] [COMMENT string’]
    16. | [data_type] [GENERATED ALWAYS] AS (expression)
    17. [VIRTUAL | STORED] [UNIQUE [KEY]] [COMMENT comment]
    18. [NOT NULL | NULL] [[PRIMARY] KEY]
    19. data_type:
    20. TINYINT[(length)] [UNSIGNED] [ZEROFILL]
    21. | SMALLINT[(length)] [UNSIGNED] [ZEROFILL]
    22. | MEDIUMINT[(length)] [UNSIGNED] [ZEROFILL]
    23. | INT[(length)] [UNSIGNED] [ZEROFILL]
    24. | INTEGER[(length)] [UNSIGNED] [ZEROFILL]
    25. | BIGINT[(length)] [UNSIGNED] [ZEROFILL]
    26. | REAL[(length,decimals)] [UNSIGNED] [ZEROFILL]
    27. | DOUBLE[(length,decimals)] [UNSIGNED] [ZEROFILL]
    28. | FLOAT[(length,decimals)] [UNSIGNED] [ZEROFILL]
    29. | DECIMAL[(length[,decimals])] [UNSIGNED] [ZEROFILL]
    30. | NUMERIC[(length[,decimals])] [UNSIGNED] [ZEROFILL]
    31. | DATE
    32. | TIME[(fsp)]
    33. | TIMESTAMP[(fsp)]
    34. | DATETIME[(fsp)]
    35. | YEAR
    36. | CHAR[(length)] [CHARACTER SET charsetname] [COLLATE collationname]
    37. | VARCHAR(length) [CHARACTER SET charsetname] [COLLATE collationname]
    38. | BINARY[(length)]
    39. | VARBINARY(length)
    40. index_col_name:
    41. colname [(length)] [ASC | DESC]
    42. index_type:
    43. USING BTREE
    44. index_options:
    45. index_option [index_option…]
    46. index_option:
    47. GLOBAL [LOCAL]
    48. |COMMENT 'string'
    49. |COMPRESSION [=] {NONE | LZ4_1.0 | ZSTD_1.0 | SNAPPY_1.0 | ZLIB_1.0}
    50. |BLOCK_SIZE [=] size
    51. |STORING(columname_list)
    52. |VISIBLE [INVISIBLE]
    53. columname_list:
    54. colname [, colname…]
    55. table_options:
    56. table_option [table_option]...
    57. table_option:
    58. [DEFAULT] {CHARACTER SET| CHARSET} [=] charsetname
    59. | [DEFAULT] COLLATE [=] collationname
    60. | COMMENT [=] string
    61. | COMPRESSION [=] {NONE | LZ4_1.0 | ZSTD_1.0 | SNAPPY_1.0 | ZLIB_1.0}
    62. | EXPIRE_INFO [=] expr
    63. | REPLICA_NUM [=] num
    64. | TABLE_ID [=] id
    65. | BLOCK_SIZE [=] size
    66. | USE_BLOOM_FILTER [=] {True | False}
    67. | STEP_MERGE_NUM [=] num
    68. | TABLEGROUP [=] tablegroupname
    69. | PRIMARY_ZONE [=] zonelist
    70. | AUTO_INCREMENT [=] num| PCTFREE [=] integer
    71. | LOCALITY [=] locality
    72. partition_options:
    73. PARTITION BY
    74. HASH(expr)
    75. |KEY(column_list)
    76. PARTITIONS num
    77. [partition_definition ...]
    78. partition_definition:
    79. COMMENT [=] 'string'

    说明

    注意: OceanBase内部数据以b树为索引,按照 Primary Key 排序。OceanBase 1.0 支持创建只有主键列的表,也可以不指定主键,系统会自动生成。

    CREATE TABLE 支持 UNIQUE约束;暂不支持创建临时表,暂不支持CHECK约束;不支持创建表的同时从其他表导入功能。

    • 使用 IF NOT EXISTS 时,即使创建的表已经存在,也不会报错,如果不指定时,则会报错。

    • NOT NULL、DEFAULT、AUTO_INCREMENT 用于列的完整性约束。

    • **table_option** 内容请参见表选项,各子句间用“,”隔开。

    • index_option 中,可以指定GLOBAL、LOCAL关键字,表述全局或局部索引。默认是 GLOBAL index。VISIBLE 和 INVISIBLE 关键字,表述可见索引或不可见索引,可见及不可见是对优化器而言的。创建带有Parition的表时index一定要加LOCAL关键字。如果没有加,系统将报错。

    表选项

    参数

    含义

    示例

    CHARACTERSET

    指定该表所有字符串的编码,用于对外提供元数据信息。目前仅支持 UTF8MB4。

    CHARACTERSET = ‘utf8mb4’

    COMMENT

    添加注释信息。

    COMMENT=’createby Bruce’

    COMPRESSION

    存储数据时使用的压缩方法名,目前提供的方法有以下几种:

    • NONE
    • LZ4_1.0(默认值)
    • ZSTD_1.0
    • SNAPPY_1.0
    • ZLIB_1.0

    COMPRESSION= NONE

    REPLICA_NUM

    这个表的partition总副本数,默认值为3。

    REPLICA_NUM= 3

    TABLE_ID

    指定表的ID。需要打开 RootService 的配置项开关“ddl_system_table_switch”。

    TABLE_ID=2000

    BLOCK_SIZE

    设置 Partition 的微块大小。

    默认为16K。

    USE_BLOOM_FILTER

    对本表读取数据时,是否使用Bloom Filter。

    • False:默认值,不使用。
    • True:使用。

    USE_BLOOM_FILTER= False

    STEP_MERGE_NUM

    设置渐近合并步数。

    STEP_MERGE_NUM现在在限制是1~64。

    默认值为1。

    STEP_MERGE_NUM= 5

    TABLEGROUP

    表所属表格组。

    REPLICA_NUM

    这个表的 Partition 总副本数,默认值为3。

    REPLICA_NUM = 3

    PRIMARY_ZONE

    主集群。

    AUTO_INCREMENT

    自增字段初始值

    AUTO_INCREMENT = 5

    PCTFREE

    指定宏块保留空闲空间的百分表

    语法 pctfree是oracle已有的配置项,和我们的语义很接近,这块为了和oracle兼容,我们使用相同的名称。

    • 建表

    CREATE TABLE table_name (column_definition) PCTFREE [=] integer

    • 修改

    ALTER TABLE table_name PCTFREE [=] integer

    说明:

    1. 建表如果未指定pctfree,默认值为10。
    2. pctfree 必须是整型,合法区间为 [0,50)。

    示例

    1. 执行以下命令,创建数据库表。
    1. CREATE TABLE test (c1 int primary key, c2 VARCHAR(50)) REPLICA_NUM = 3, PRIMARY_ZONE = 'zone1';

    或者也可以执行以下命令来创建数据库表。

    1. CREATE TABLE test (c1 int, c2 VARCHAR(50), primary key(c1)) REPLICA_NUM = 3, PRIMARY_ZONE = 'zone1';
    1. 执行以下命令查看表信息。
    1. SHOW tables;
    2. DESCRIBE test;

    示例结果如下:

    CREATE TABLE - 图1

    报错

    • 语法错误时报 ERROR 1064 (42000): You have an error in your SQL syntax

    • 表名重复,报 ERROR 1050 (42S01): Table 'test' already exists

    • 表名超出限定长度,报 ERROR 1059 (42000): Identifier name 'XXXX' is too long

    • 创建表时,分区名重复,报 ERROR 1517 (HY000): Duplicate partition name XX

    1. mysql> create table employeestest(id int) partition by range(id) (partition dpname values less than (10), partition dPname values less than (20));
    2. ERROR 1517 (HY000): Duplicate partition name 'dPname'

    创建生成列

    OceanBase支持创建生成列特性,在创建生成列的时候需要定义生成列依赖的表达式,生成列的值来源于被定义的表达式计算结果的值,因此在向表中插入数据的时候,不能为生成列指定要插入的值。

    下面的示例将为我们展示生成列的使用,在统计姓名的表格中,我们一般需要分别统计 first name(名)和 lastname(姓),同时我们又希望能够查询到全名,而全名刚好是 first_name·last_name 的结果,这个时候就可以使用生成列特性。

    1. CREATE TABLE t1(
    2. first_name varchar(100),
    3. last_name varchar(100),
    4. full_name varchar(100) as (concat(first_name, '·', last_name))
    5. );
    6. INSERT INTO t1 (first_name, last_name) values('Tom', 'Lee'), ('Peter', 'Bush');

    然后查询表中的结果得到如下所示信息:

    1. select * from t1;
    2. +-----------------+---------------+----------------+
    3. | first_name | last_name | full_name |
    4. +-----------------+---------------+----------------+
    5. | Tom | Lee | Tom·Lee |
    6. | Peter | Bush | Peter·Bush |
    7. +-----------------+---------------+----------------+

    生成列的定义如下:

    1. col_name [data_type] [GENERATED ALWAYS] AS (expression)
    2. [VIRTUAL | STORED] [UNIQUE [KEY]] [COMMENT comment]
    3. [[NOT] NULL] [[PRIMARY] KEY]

    AS (expression)表示该列是一个生成列,并且expression被用来计算生成列的值,GENERATED ALWAYS关键字可以不用指定,也可以指定该关键字,使得生成列的创建语句变得更加清晰自然。

    VIRTUAL or STORED关键字用来指定生成列的值在表中是如何存储的,不同的存储方式可以应用于不同的生成列使用场景中:

    • VIRTUAL:生成列的值不会被存储,而是在生成列被查询访问到的时候进行计算,虚拟列不占用存储空间。

    • STORED:生成列的值在insert或者updated时被计算,并且会物化到存储中,除了生成列的值是利用表达式计算出来的外,其它的特性和普通的列并没什么区别。

    如果在创建生成列的时候没有指定VIRTUAL或者STORED关键字,那么OB默认创建VIRTUAL形式的生成列,其它的关键字用来指定列的其它属性,例如NULL属性,KEY属性,在OB目前并不支持VIRTUAL生成列作为主键。

    表达式的计算可能会依赖当前session中一些变量信息,例如常量字符串的参与运算需要依赖session中的charset和collationtype,timestamp类型计算需要依赖当前的timezone信息,生成列表达式的计算所依赖的session中变量信息为创建生成列时所依赖的session变量信息。

    除此之外,生成列的定义还要遵循以下规则的约束:

    • 生成列表达式(包括操作符以及函数)的结果必须是确定值,确定值的定义是在给定的charset以及collation type或者timezone信息下,一个表达式多次执行的结果是相同的,例如这些表达式就不满足这样的约定:random(), now()

    • 生成列表达式中不能包含子查询,变量或者系统参数以及存储过程函数

    • 生成列的定义能够依赖其它生成列,但必须是前面已经定义过的生成列

    如果生成列在INSERT、REPLACE、UPDATE语句中现实指定了对应的值,那么只能是DEFAULT,其它的常量或者表达式将报错:

    1. OceanBase (root@test)> create table t1(a int primary key, b int, c int as (a+b));
    2. Query OK, 0 rows affected (0.23 sec)
    3. OceanBase (root@test)> insert into t1 values(1, 1, default);
    4. Query OK, 1 row affected (0.02 sec);
    5. OceanBase (root@test)> update t1 set a=2, c=default;
    6. Query OK, 1 row affected (0.02 sec)
    7. Rows matched: 1 Changed: 1 Warnings: 0
    8. OceanBase (root@test)> select * from t1;
    9. +---+---------+--------+
    10. | a | b | c |
    11. +---+---------+--------+
    12. | 2 | 1 | 3 |
    13. +---+---------+--------+
    14. 1 row in set (0.01 sec)
    15. OceanBase (root@test)> insert into t1 values(1, 1, 1);
    16. ERROR 3105 (HY000): The value specified for generated column 'c' in table 't1' is not allowed
    17. OceanBase (root@test)> update t1 set a=2, c=3;
    18. ERROR 3105 (HY000): The value specified for generated column 'c' in table 't1' is not allowed

    为了跟 mysql 兼容,我们允许生成列的创建语法有 NOT NULL 约束,但是生成列上的 NOT NULL 约束并不生效,我们允许为生成列定义数据类型,如果生成列的表达式的结果类型和生成列的数据类型不相同,将发生表达式的值向列类型的转换。如果生成列没有指定数据类型,那么我们会使用表达式的推导类型作为生成列的数据类型,因此我们推荐不为生成列指定数据类型。