CREATE TABLE

2023-10-31 11:17:11  Updated

Purpose

You can use this statement to create a table in the database.

Syntax

CREATE [TEMPORARY] TABLE [IF NOT EXISTS] table_name
      (table_definition_list) [table_option_list] [partition_option] [AS] select;

CREATE [TEMPORARY] TABLE [IF NOT EXISTS] table_name
      LIKE table_name;

table_definition_list:
    table_definition [, table_definition ...]

table_definition:
      column_definition
    | [CONSTRAINT [constraint_name]] PRIMARY KEY index_desc
    | [CONSTRAINT [constraint_name]] UNIQUE {INDEX | KEY}
            [index_name] index_desc
    | [CONSTRAINT [constraint_name]] FOREIGN KEY
            [index_name] index_desc
            REFERENCES reference_definition
            [match_action][opt_reference_option_list]
    | {INDEX | KEY} [index_name] [index_type] (key_part,...)
      [index_option_list]
    | [CONSTRAINT [constraint_name]] CHECK(expression) constranit_state

column_definition_list:
    column_definition [, column_definition ...]

column_definition:
     column_name data_type
         [DEFAULT const_value] [AUTO_INCREMENT]
         [NULL | NOT NULL] [[PRIMARY] KEY] [UNIQUE [KEY]] comment
   | column_name data_type
         [GENERATED ALWAYS] AS (expr) [VIRTUAL | STORED]
         [opt_generated_column_attribute]

index_desc:
   (column_desc_list) [index_type] [index_option_list]

match_action:
   MATCH {SIMPLE | FULL | PARTIAL}

opt_reference_option_list:
   reference_option [,reference_option ...]

reference_option:
   ON {DELETE | UPDATE} {RESTRICT | CASCADE | SET NULL | NO ACTION | SET DEFAULT}


key_part:
    {index_col_name [(length)] | (expr)} [ASC | DESC]

index_type:
    USING BTREE

index_option_list:
    index_option [ index_option ...]

index_option:
      [GLOBAL | LOCAL]
    | block_size
    | compression
    | STORING(column_name_list)
    | comment

table_option_list:
    table_option [ table_option ...]

table_option:
      [DEFAULT] {CHARSET | CHARACTER SET} [=] charset_name
    | [DEFAULT] COLLATE [=] collation_name
    | table_tablegroup
    | block_size
    | compression
    | AUTO_INCREMENT [=] INT_VALUE
    | comment
    | ROW_FORMAT [=] REDUNDANT|COMPACT|DYNAMIC|COMPRESSED|DEFAULT
    | PCTFREE [=] num
    | parallel_clause
    | DUPLICATE_SCOPE [=] 'none|cluster'

parallel_clause:
    {NOPARALLEL | PARALLEL integer}

partition_option:
      PARTITION BY HASH(expression)
      [subpartition_option] PARTITIONS partition_count
    | PARTITION BY KEY([column_name_list])
      [subpartition_option] PARTITIONS partition_count
    | PARTITION BY RANGE {(expression) | COLUMNS (column_name_list)}
      [subpartition_option] (range_partition_list)
    | PARTITION BY LIST {(expression) | COLUMNS (column_name_list)}
      [subpartition_option] PARTITIONS partition_count

subpartition_option:
      SUBPARTITION BY HASH(expression)
      SUBPARTITIONS subpartition_count
    | SUBPARTITION BY KEY(column_name_list)
      SUBPARTITIONS subpartition_count
    | SUBPARTITION BY RANGE {(expression) | COLUMNS (column_name_list)}
      (range_subpartition_list)
    | SUBPARTITION BY LIST(expression)

range_partition_list:
    range_partition [, range_partition ...]

range_partition:
    PARTITION partition_name
    VALUES LESS THAN {(expression_list) | MAXVALUE}

range_subpartition_list:
    range_subpartition [, range_subpartition ...]

range_subpartition:
    SUBPARTITION subpartition_name
    VALUES LESS THAN {(expression_list) | MAXVALUE}

expression_list:
    expression [, expression ...]

column_name_list:
    column_name [, column_name ...]

partition_name_list:
    partition_name [, partition_name ...]

partition_count | subpartition_count:
    INT_VALUE

Parameters

Parameter Description
TEMPORARY Creates the table as a temporary table.
PRIMARY KEY The primary key of the created table. If this parameter is not specified, a hidden primary key is used. OceanBase Database does not allow you to modify the primary key of a table or use the ALTER TABLE statement to add a primary key to a table. Therefore, we recommend that you specify a primary key when you create a table.
FOREIGN KEY The foreign key of the created table. If you do not specify the name of the foreign key, it will be named in the format of table name + OBFK+ time when the foreign key was created. For example, the foreign key created for table t1 at 00:00:00 on August 1, 2021 is named as t1_OBFK_1627747200000000.
KEY | INDEX The key or index of the created table. If you do not specify the name of the index, the name of the first column referenced by the index is used as the index name. If duplicate index names exist, the index will be named in the format of underscore (_) + sequence number. For example, if the name of the index created based on column c1 conflicts with an existing index name, the index will be named as c1_2. You can execute the SHOW INDEX statement to query the indexes of a table.
key_part Creates a normal or function-based index.
index_col_name The column name of the index. You can add ASC (ascending order) to the end of each column name. DESC (descending order) is not supported. By default, the columns are sorted in ascending order. Index-based sorting method: Data is first sorted by the values in the first column of index_col_name and by the values in the next column for the records with the same values in the first column.
expr A valid function-based index expression. A Boolean expression, such as c1=c1, is allowed.

Notice

Currently, you cannot create function-based indexes on generated columns in OceanBase Database.

ROW_FORMAT Specifies whether to enable the encoding storage format.
  • redundant: indicates that the encoding storage format is not enabled.
  • compact: indicates that the encoding storage format is not enabled.
  • dynamic: an encoding storage format.
  • compressed: an encoding storage format.
  • default: This value is equivalent to dynamic.
[GENERATED ALWAYS] AS (expr) [VIRTUAL | STORED] Creates a generated column. expr specifies the expression used to calculate the column value.
  • VIRTUAL: indicates that column values are not stored, but are immediately calculated after any BEFORE trigger when a row is read. Virtual columns do not occupy storage space.
  • STORED: evaluates and stores column values when you insert or update a row. Stored columns occupy storage space and can be indexed.
BLOCK_SIZE The microblock size for the table.
COMPRESSION The compression algorithm for the table. Valid values:
  • none: indicates that no compression algorithm is used.
  • lz4_1.0: indicates that the lz4 compression algorithm is used.
  • zstd_1.0: indicates that the zstd compression algorithm is used.
  • snappy_1.0: indicates that the snappy compression algorithm is used.
CHARSET | CHARACTER SET The default character set for columns in the table. Valid values:
  • utf8
  • utf8mb4
  • gbk
  • utf16
  • gb18030
COLLATE The default collation for columns in the table. Valid values:
  • utf8_bin
  • utf8_general_ci
  • utf8_unicode_ci
  • gbk_bin
  • gbk_chinese_ci
  • utf8mb4_general_ci
  • utf8mb4__general_cs
  • utf8mb4_bin
  • utf8mb4_unicode_ci
  • utf16_general_ci
  • utf16_bin
  • utf16_unicode_ci
  • gb18030_chinese_ci
  • gb18030_bin
table_tablegroup The table group to which the table belongs.
AUTO_INCREMENT The start value of an auto-increment column in the table. OceanBase Database allows you to use auto-increment columns as the partitioning key.
comment The comment.
PCTFREE The percentage of space reserved for macroblocks.
parallel_clause The degree of parallelism (DOP) at the table level.
  • NOPARALLEL: sets the DOP to 1, which is the default value.
  • PARALLEL integer: sets the DOP to an integer greater than or equal to 1.
DUPLICATE_SCOPE The replica table attribute. Valid values:
  • none: specifies that the table is a normal table. This is the default value.
  • cluster: specifies that the table is a replica table. The leader needs to replicate transactions to all full-featured replicas and read-only replicas of the current tenant.
Currently, OceanBase Database supports only cluster-level replica tables.
CHECK Specifies to restrict the range of values in the column.
  • If you define a CHECK constraint on a single column, you can write this column-level constraint in the column definition and specify a name for this constraint.
  • If you define a CHECK constraint on a table, this constraint is applied to multiple columns in the table and can appear before a column definition. When you drop the table, the CHECK constraint on the table is also dropped.
You can view constraint information in the following ways:
  • Use the SHOW CREATE TABLE statement.
  • Query the information_schema.TABLE_CONSTRAINTS view.
  • Query the information_schema.CHECK_CONSTRAINTS view.
  • constraint_name The name of the constraint, which contains at most 64 characters.
    • Spaces are allowed at the beginning, in the middle, and at the end of a constraint name. However, the beginning and end of the constraint name must be identified with a backtick (`).
    • A constraint name can contain the dollar sign character ($).
    • If a constraint name is a reserved word, it must be identified with a backtick (`). Otherwise, an error is returned.
    • CHECK constraint names must be unique in the same database.
    expression The expression of the constraint.
    • expression cannot be empty.
    • The result of expression must be of the Boolean data type.
    • expression cannot contain a column that does not exist.

    Examples

    • Create a database table.

      obclient> CREATE TABLE tbl1 (c1 INT PRIMARY KEY, c2 VARCHAR(50));
      Query OK, 0 rows affected
      
    • Create an indexed table.

      obclient> CREATE TABLE tbl2 (c1 INT PRIMARY KEY, c2 INT, c3 INT, INDEX i1 (c2));
      Query OK, 0 rows affected
      
    • Create a table named tbl3 with a function-based index.

      obclient> CREATE TABLE tbl3 (c1 INT, c2 INT, INDEX i1 ((c1+1)), UNIQUE KEY ((c1+c2)));
      Query OK, 0 rows affected
      
      obclient> SHOW CREATE TABLE tbl3;
      +-------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
      | Table | Create Table                                                                                                                                                                                                                                                                                                                                                                     |
      +-------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
      | tbl3    | CREATE TABLE `tbl3` (
      `c1` int(11) DEFAULT NULL,
      `c2` int(11) DEFAULT NULL,
      UNIQUE KEY `functional_index` ((`c1` + `c2`)) BLOCK_SIZE 16384 LOCAL,
      KEY `i1` ((`c1` + 1)) BLOCK_SIZE 16384 LOCAL
      ) DEFAULT CHARSET = utf8mb4 ROW_FORMAT = DYNAMIC COMPRESSION = 'zstd_1.3.8' REPLICA_NUM = 2 BLOCK_SIZE = 16384 USE_BLOOM_FILTER = FALSE TABLET_SIZE = 134217728 PCTFREE = 0 |
      +-------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
      
    • Create a HASH-partitioned table with eight partitions.

      obclient> CREATE TABLE tbl4 (c1 INT PRIMARY KEY, c2 INT) PARTITION BY HASH(c1) PARTITIONS 8;
      Query OK, 0 rows affected
      
    • Create a RANGE-KEY-subpartitioned table.

      obclient> CREATE TABLE tbl5 (c1 INT, c2 INT, c3 INT) PARTITION BY RANGE(c1)
           SUBPARTITION BY KEY(c2, c3) SUBPARTITIONS 5
           (PARTITION p0 VALUES LESS THAN(0), PARTITION p1 VALUES LESS THAN(100));
      Query OK, 0 rows affected
      
    • Create a table that uses gbk for one column and utf8 for the other column.

      obclient> CREATE TABLE tbl6 (c1 VARCHAR(10),
                       c2 VARCHAR(10) CHARSET GBK COLLATE gbk_bin)
                   DEFAULT CHARSET utf8 COLLATE utf8mb4_general_ci;
      Query OK, 0 rows affected
      
    • Enable encoding and use zstd compression for the table, and reserve 5% of space for macroblocks.

      obclient> CREATE TABLE tbl7 (c1 INT, c2 INT, c3 VARCHAR(64))
            COMPRESSION 'zstd_1.0'
            ROW_FORMAT DYNAMIC
            PCTFREE 5;
      Query OK, 0 rows affected
      
    • Create a table named tbl8 and set the DOP to 3.

      obclient> CREATE TABLE tbl8(c1 INT PRIMARY KEY, c2 INT) PARALLEL 3;
      Query OK, 0 rows affected
      
    • Use an auto-increment column as the partitioning key.

      obclient> CREATE TABLE tbl9(inv_id BIGINT NOT NULL AUTO_INCREMENT,c1 BIGINT,
      PRIMARY KEY (inv_id) ) PARTITION BY HASH(inv_id) PARTITIONS 8;
      Query OK, 0 rows affected
      
    • Create a table named tbl10 with the CHECK constraint and view the constraint information.

      obclient> CREATE TABLE tbl10 (col1 INT, col2 INT, col3 INT, CONSTRAINT equal_check1 CHECK(col1 = col3 * 2));
      Query OK, 0 rows affected
      
      obclient> SHOW CREATE TABLE tbl10;
      +-------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
      | Table | Create Table                                                                                                                                                                                                                                                                                                                                               |
      +-------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
      | tbl10  | CREATE TABLE `tbl10` (
        `col1` int(11) DEFAULT NULL,
        `col2` int(11) DEFAULT NULL,
        `col3` int(11) DEFAULT NULL,
        CONSTRAINT `equal_check1` CHECK ((`col1` = (`col3` * 2)))
      ) DEFAULT CHARSET = utf8mb4 ROW_FORMAT = DYNAMIC COMPRESSION = 'zstd_1.3.8' REPLICA_NUM = 1 BLOCK_SIZE = 16384 USE_BLOOM_FILTER = FALSE TABLET_SIZE = 134217728 PCTFREE = 0 |
      +-------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
      1 row in set
      
    • Create a table named tbl11 based on the tbl10 table and view the table information.

      obclient> CREATE TABLE tbl11 LIKE tbl10;
      Query OK, 0 rows affected
      
      obclient> SHOW CREATE TABLE tbl11;
      +-------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
      | Table | Create Table                                                                                                                                                                                                                                                                                                                                                                |
      +-------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
      | tbl11  | CREATE TABLE `tbl11` (
        `col1` int(11) DEFAULT NULL,
        `col2` int(11) DEFAULT NULL,
        `col3` int(11) DEFAULT NULL,
        CONSTRAINT `tbl11_OBCHECK_1650793233327894` CHECK ((`col1` = (`col3` * 2)))
      ) DEFAULT CHARSET = utf8mb4 ROW_FORMAT = DYNAMIC COMPRESSION = 'zstd_1.3.8' REPLICA_NUM = 1 BLOCK_SIZE = 16384 USE_BLOOM_FILTER = FALSE TABLET_SIZE = 134217728 PCTFREE = 0 |
      +-------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
      1 row in set
      
    • Create a cluster-level replica table named dup_t1.

      1. Log on to the sys tenant and create a unit.

        obclient> CREATE RESOURCE UNIT IF NOT EXISTS 2c5g MAX_CPU 2, MEMORY_SIZE '5G';
        Query OK, 0 rows affected
        
      2. Create a resource pool and set UNIT_NUM to 2.

        obclient> CREATE RESOURCE POOL tenant_pool UNIT = '2c5g', UNIT_NUM = 2, ZONE_LIST = ('z1', 'z2', 'z3');
        Query OK, 0 rows affected
        
      3. Create a user tenant named obmysql and specify the locality.

        obclient> CREATE TENANT obmysql resource_pool_list=('tenant_pool'), LOCALITY = "F@z1, F@z2, R@z3", PRIMARY_ZONE = "z1" SET ob_tcp_invited_nodes='%';
        Query OK, 0 rows affected
        
      4. Log on to the obmysql user tenant created in step 3 and create a replica table.

        obclient> USE test;
        Database changed
        obclient> CREATE TABLE dup_t1(c1 INT) DUPLICATE_SCOPE = 'cluster';
        Query OK, 0 rows affected
        
      5. (Optional) View the broadcast log stream. The replica table is created on this log stream.

        obclient> SELECT * FROM oceanbase.DBA_OB_LS WHERE FLAG LIKE "%DUPLICATE%";
        +-------+--------+--------------+---------------+-------------+---------------------+----------+---------------------+---------------------+-----------+
        | LS_ID | STATUS | PRIMARY_ZONE | UNIT_GROUP_ID | LS_GROUP_ID | CREATE_SCN          | DROP_SCN | SYNC_SCN            | READABLE_SCN        | FLAG      |
        +-------+--------+--------------+---------------+-------------+---------------------+----------+---------------------+---------------------+-----------+
        |  1003 | NORMAL | z1;z2        |             0 |           0 | 1683267390195713284 |     NULL | 1683337744205408139 | 1683337744205408139 | DUPLICATE |
        +-------+--------+--------------+---------------+-------------+---------------------+----------+---------------------+---------------------+-----------+
        1 row in set
        
        
        
        
      6. (Optional) View the replica distribution of the replica table in the sys tenant. The REPLICA_TYPE field indicates the replica type.

        obclient> SELECT * FROM oceanbase.CDB_OB_TABLE_LOCATIONS WHERE TABLE_NAME = "dup_t1";
        +-----------+---------------+------------+----------+------------+----------------+-------------------+------------+---------------+-----------+-------+------+----------------+----------+----------+--------------+-----------------+
        | TENANT_ID | DATABASE_NAME | TABLE_NAME | TABLE_ID | TABLE_TYPE | PARTITION_NAME | SUBPARTITION_NAME | INDEX_NAME | DATA_TABLE_ID | TABLET_ID | LS_ID | ZONE | SVR_IP         | SVR_PORT | ROLE     | REPLICA_TYPE | DUPLICATE_SCOPE |
        +-----------+---------------+------------+----------+------------+----------------+-------------------+------------+---------------+-----------+-------+------+----------------+----------+----------+--------------+-----------------+
        |      1002 | test          | dup_t1     |   500002 | USER TABLE | NULL           | NULL              | NULL       |          NULL |    200001 |  1003 | z1   | 11.xxx.xxx.xxx |    36125 | LEADER   | FULL         | CLUSTER         |
        |      1002 | test          | dup_t1     |   500002 | USER TABLE | NULL           | NULL              | NULL       |          NULL |    200001 |  1003 | z1   | 11.xxx.xxx.xxx  |    36124 | FOLLOWER | READONLY     | CLUSTER         |
        |      1002 | test          | dup_t1     |   500002 | USER TABLE | NULL           | NULL              | NULL       |          NULL |    200001 |  1003 | z2   | 11.xxx.xxx.xxx |    36127 | FOLLOWER | FULL         | CLUSTER         |
        |      1002 | test          | dup_t1     |   500002 | USER TABLE | NULL           | NULL              | NULL       |          NULL |    200001 |  1003 | z2   | 11.xxx.xxx.xxx |    36126 | FOLLOWER | READONLY     | CLUSTER         |
        |      1002 | test          | dup_t1     |   500002 | USER TABLE | NULL           | NULL              | NULL       |          NULL |    200001 |  1003 | z3   | 11.xxx.xxx.xxx |    36128 | FOLLOWER | READONLY     | CLUSTER         |
        |      1002 | test          | dup_t1     |   500002 | USER TABLE | NULL           | NULL              | NULL       |          NULL |    200001 |  1003 | z3   | 11.xxx.xxx.xxx  |    36129 | FOLLOWER | READONLY     | CLUSTER         |
        +-----------+---------------+------------+----------+------------+----------------+-------------------+------------+---------------+-----------+-------+------+----------------+----------+----------+--------------+-----------------+
        6 rows in set
        
      7. Insert data into, read data from, and write data to the replica table. If you connect to the database by using an OceanBase Database Proxy (ODP), the read request may be routed to any OBServer node. If you directly connect to an OBServer node, the read request is executed on the connected OBServer node as long as the local replica is readable.

        obclient> INSERT INTO dup_t1 VALUES(1);
        Query OK, 1 row affected
        
        obclient> SELECT * FROM dup_t1;
        +------+
        | c1   |
        +------+
        |    1 |
        +------+
        1 row in set
        

    Limitations on private temporary tables in MySQL mode

    Currently, private temporary tables are not used for business in the MySQL mode of OceanBase Database. Considering the high risks, we recommend that you do not use private temporary tables.

    Performance and stability

    • In MySQL mode, temporary tables have the same performance as normal tables.
    • In MySQL mode, the use of temporary tables involves table creation. When temporary tables are concurrently created in multiple sessions, RootService will be overloaded or even crash, resulting in stability issues.

    Temporary table creation

    To allow temporary tables with the same name to be created in different sessions, OceanBase Database in MySQL mode maintains the session_id column in the dictionary table. If two temporary tables have the same name but different session IDs, they can coexist in the database.

    When a temporary table is created in a session in MySQL mode, the session ID of the session is entered in the session_id column of the dictionary table.

    Routing for temporary tables

    In MySQL mode, after the current session accesses its temporary table, subsequent SQL requests can be sent only to the current session. This is the same as that in Oracle mode.

    Data cleanup for temporary tables

    When a session is disconnected, the temporary table created in the session is automatically dropped.

    Known issues

    If the table following SELECT in the CREATE TABLE AS SELECT statement is a temporary table, this statement may create an empty table.

    Contact Us