Purpose
This statement is used to create a new table in the database.
Syntax
CREATE [hint_options] [GLOBAL TEMPORARY] TABLE table_name
(table_definition_list) [table_option_list] [partition_option] [on_commit_option]
CREATE [GLOBAL TEMPORARY] TABLE table_name
(table_definition_list) [table_option_list] [partition_option] [table_column_group_option] [AS] select;
table_definition_list:
table_definition [, table_definition ...]
table_definition:
column_definition
| [,
| [CONSTRAINT [constraint_name]] { PRIMARY KEY|UNIQUE } (column_name) //Add a constraint after all columns are created
| [CONSTRAINT [constraint_name]] FOREIGN KEY (column_name, column_name ...) references_clause constraint_state
| [CONSTRAINT [constraint_name]] CHECK(expression) constraint_state
]
column_definition_list:
column_definition [, column_definition ...]
column_definition:
column_name data_type
[VISIBLE | INVISIBLE] [GENERATED BY DEFAULT AS IDENTITY | GENERATED ALWAYS AS IDENTITY]
{
[DEFAULT expression]
[NULL | NOT NULL]
[CONSTRAINT [constraint_name]] [ PRIMARY KEY|UNIQUE ] //Add a constraint when creating a column
[CONSTRAINT [constraint_name] CHECK(expression) constraint_state]
[CONSTRAINT [constraint_name] references_clause]
|
[GENERATED ALWAYS] AS (expression) [VIRTUAL]
[NULL | NOT NULL] [UNIQUE KEY] [[PRIMARY] KEY] [UNIQUE LOWER_KEY] [SKIP_INDEX(skip_index_option_list)]
}
skip_index_option_list:
skip_index_option [,skip_index_option ...]
skip_index_option:
MIN_MAX
| SUM
references_clause:
REFERENCES table_name [ (column_name, column_name ...) ] [ON DELETE {SET NULL | CASCADE}]
constraint_state:
[RELY | NORELY] [USING INDEX index_option_list] [ENABLE | DISABLE] [VALIDATE | NOVALIDATE]
index_option_list:
index_option [ index_option ...]
index_option:
[GLOBAL | LOCAL]
| block_size
| compression
| STORING(column_name_list)
table_option_list:
table_option [ table_option ...]
table_option:
TABLEGROUP = tablegroup_name
| block_size
| compression
| ENABLE ROW MOVEMENT
| DISABLE ROW MOVEMENT
| physical_attribute
| parallel_clause
| DUPLICATE_SCOPE [=] 'none|cluster'
| TABLE_MODE [=] 'table_mode_value'
| enable_macro_block_bloom_filter [=] {True | False}
| DYNAMIC_PARTITION_POLICY [=] (dynamic_partition_policy_list)
| MICRO_BLOCK_FORMAT_VERSION [=] {1|2}
| COLUMN_NAME_CASE_SENSITIVE [=] {True | False}
| MERGE_ENGINE = {delete_insert | partial_update | append_only}
| TTL [=]col_name + INTERVAL interval_num ttl_unit BY COMPACTION
| DELTA_FORMAT [=] 'flat | encoding'
| SKIP_INDEX_LEVEL [=] {1 | 0}
physical_attribute_list:
physical_attribute [physical_attribute]
physical_attribute:
PCTFREE [=] num
| PCTUSED num
| INITRANS num
| MAXTRANS num
| STORAGE(storage_option [storage_option] ...)
| TABLESPACE tablespace
parallel_clause:
{NOPARALLEL | PARALLEL integer}
table_mode_value:
NORMAL
| QUEUING
| MODERATE
| SUPER
| EXTREME
dynamic_partition_policy_list:
dynamic_partition_policy_option [, dynamic_partition_policy_option ...]
dynamic_partition_policy_option:
ENABLE = {true | false}
| TIME_UNIT = {'hour' | 'day' | 'week' | 'month' | 'year'}
| PRECREATE_TIME = {'-1' | '0' | 'n {hour | day | week | month | year}'}
| EXPIRE_TIME = {'-1' | '0' | 'n {hour | day | week | month | year}'}
| TIME_ZONE = {'default' | 'time_zone'}
| BIGINT_PRECISION = {'none' | 'us' | 'ms' | 's'}
compression:
NOCOMPRESS
| COMPRESS { BASIC | FOR OLTP | FOR QUERY [LOW | HIGH] | FOR ARCHIVE [LOW | HIGH]}
storage_option:
INITIAL num [K|M|G|T|P|E]
| NEXT num [K|M|G|T|P|E]
| MINEXTENTS num [K|M|G|T|P|E]
| MAXEXTENTS num [K|M|G|T|P|E]
partition_option:
PARTITION BY HASH(column_name_list)
[subpartition_option] hash_partition_define
| PARTITION BY RANGE (column_name_list)
[subpartition_option] (range_partition_list)
| PARTITION BY LIST (column_name_list)
[subpartition_option] (list_partition_list)
| PARTITION BY RANGE([column_name_list]) [SIZE('size_value')] [range_partition_list]
| PARTITION BY RANGE (column_name) INTERVAL (expr)
[subpartition_option]
(range_partition)
/*Template subpartitioning*/
subpartition_option:
SUBPARTITION BY HASH (column_name_list) hash_subpartition_define
| SUBPARTITION BY RANGE (column_name_list) SUBPARTITION TEMPLATE
(range_subpartition_list)
| SUBPARTITION BY LIST (column_name_list) SUBPARTITION TEMPLATE
(list_subpartition_list)
/*Non-template subpartitioning*/
subpartition_option:
SUBPARTITION BY HASH (column_name_list)
| SUBPARTITION BY RANGE (column_name_list)
| SUBPARTITION BY LIST (column_name_list)
subpartition_list:
(hash_subpartition_list)
| (range_subpartition_list)
| (list_subpartition_list)
hash_partition_define:
PARTITIONS partition_count [TABLESPACE tablespace] [compression]
| (hash_partition_list)
hash_partition_list:
hash_partition [, hash_partition ...]
hash_partition:
partition [partition_name] [subpartition_list/*Only applicable for non-template subpartitioning*/]
hash_subpartition_define:
SUBPARTITIONS subpartition_count
| SUBPARTITION TEMPLATE (hash_subpartition_list)
hash_subpartition_list:
hash_subpartition [, hash_subpartition ...]
hash_subpartition:
subpartition [subpartition_name]
range_partition_list:
range_partition [, range_partition ...]
range_partition:
PARTITION [partition_name]
VALUES LESS THAN {(expression_list) | (MAXVALUE)}
[subpartition_list/*Only applicable for non-template subpartitioning*/]
[ID = num] [physical_attribute_list] [compression]
range_subpartition_list:
range_subpartition [, range_subpartition ...]
range_subpartition:
SUBPARTITION subpartition_name
VALUES LESS THAN {(expression_list) | MAXVALUE} [physical_attribute_list]
list_partition_list:
list_partition [, list_partition] ...
list_partition:
PARTITION [partition_name]
VALUES (DEFAULT | expression_list)
[subpartition_list /*Only applicable for non-template subpartitioning*/]
[ID num] [physical_attribute_list] [compression]
list_subpartition_list:
list_subpartition [, list_subpartition] ...
list_subpartition:
SUBPARTITION [partition_name] VALUES (DEFAULT | expression_list) [physical_attribute_list]
expression_list:
expression [, expression ...]
column_name_list:
column_name [, column_name ...]
partition_name_list:
partition_name [, partition_name ...]
partition_count | subpartition_count:
INT_VALUE
on_commit_option:
ON COMMIT DELETE ROWS
| ON COMMIT PRESERVE ROWS
table_column_group_option:
WITH COLUMN GROUP(all columns)
| WITH COLUMN GROUP(each column)
| WITH COLUMN GROUP(all columns, each column)
Parameters
| Parameter | Description |
|---|---|
| hint_options | Optional. Specifies the hint options. You can manually specify the bypass import hint, including APPEND, DIRECT, and NO_DIRECT. The corresponding hint format is /+ [APPEND | DIRECT(need_sort,max_error,load_type)] parallel(N)| NO_DIRECT/. For more information about bypass importing data by using the CREATE TABLE AS SELECT statement, see the Use CREATE TABLE AS SELECT to bypass import data section in Full bypass import. |
| GLOBAL TEMPORARY | Creates the table as a temporary table. |
| DEFAULT expression | Specifies the default value of a column. expression supports a function expression that contains a sequence.
NoticeAuto-increment columns cannot have default values. |
| BLOCK_SIZE | Specifies the microblock size of the table. |
| COMPRESSION | Specifies the storage format (Flat/Encoding) and compression method. Valid values:
|
| tablegroup_name | Specifies the table group to which the table belongs. |
| FOREIGN KEY | Specifies the foreign key of the created table. If you do not specify the foreign key name, the system will use the table name + OBFK + creation time as the foreign key name. (For example, the foreign key name created on August 1, 2021, 00:00:00 for the t1 table is t1_OBFK_1627747200000000.) A foreign key allows cross-referencing data across tables. When the DELETE operation affects the key values in the parent table that match the rows in the child table, the result depends on the ON DELETE clause of the reference action:
|
| VISIBLE | Indicates that the column is visible. This is the default column state. |
| INVISIBLE | Indicates that the column is invisible. After a column is set to INVISIBLE, it will not be displayed by default in queries. |
| GENERATED BY DEFAULT AS IDENTITY | GENERATED ALWAYS AS IDENTITY | Optional. Specifies a column as an auto-increment column. Valid values:
NoticeThe data type of this column must be a numeric type. |
| physical_attribute | PCTFREE: specifies the percentage of space reserved in a macroblock. Other attributes such as STORAGE and TABLESPACE are only for syntax compatibility and do not take effect. |
| ENABLE/DISABLE ROW MOVEMENT | Specifies whether to allow row movement between partitions for partition key updates. |
| ON COMMIT DELETE ROWS | Specifies a transaction-level temporary table. Data is deleted upon transaction commit. |
| ON COMMIT PRESERVE ROWS | Specifies a session-level temporary table. Data is deleted upon session end. |
| parallel_clause | Specifies the parallelism at the table level:
NoticeWhen specifying the parallelism, the priority is as follows: the parallelism specified by the hint > the parallelism specified by |
| DUPLICATE_SCOPE | Specifies the replication attribute of the table. Valid values:
cluster: the table is a replicated table. The leader needs to replicate transactions to all F (full-featured) and R (read-only) replicas of the current tenant.
cluster-level replication tables. |
| table_column_group_option | Specifies the table column storage option. Valid values:
|
| SKIP_INDEX | Specifies the Skip Index attribute of the column. Valid values:
Notice
|
| TABLE_MODE | Optional. Specifies the merge trigger threshold and merge strategy, which control the behavior after data is dumped. For more information about the values, see table_mode_value. |
| enable_macro_block_bloom_filter [=] {True | False} | Specifies whether to persist the bloom filter at the macroblock level. Valid values:
|
| DYNAMIC_PARTITION_POLICY [=] $dynamic_partition_policy_list$ | Specifies the dynamic partition management attribute of the table, enabling automatic creation and deletion of partitions. dynamic_partition_policy_list specifies the configurable parameters of the dynamic partition strategy. Parameters are separated by commas. For more information, see dynamic_partition_policy_option. |
| MICRO_BLOCK_FORMAT_VERSION | Optional. Specifies the version number of the microblock storage format of the table. Valid values: [1, +∞)
NoteThis parameter was introduced in V4.4.1. |
| COLUMN_NAME_CASE_SENSITIVE [=] {True | False} | Specifies whether to enable case-sensitive column names for generated columns.
|
| MERGE_ENGINE = {delete_insert | partial_update | append_only} | Optional. Specifies the update model of the table. Valid values:
MERGE_ENGINE option, the value of this option is the same as the value of the default_table_merge_engine parameter.
NoteThe value of the |
| TTL [=] col_name + INTERVAL interval_num ttl_unit BY COMPACTION | Modifies the TTL strategy of the table. When you create a TTL table, the update mode MERGE_ENGINE can only be append_only or delete_insert. For more information, see the following explanation:
|
| DELTA_FORMAT [=] 'flat | encoding' | Specifies the storage format of incremental data. Valid values:
default_delta_format parameter to change the default incremental data storage format of the table. You do not need to specify this parameter when you create a table. For more information, see default_delta_format. |
| SKIP_INDEX_LEVEL [=] {1 | 0} | Specifies whether to generate skip index aggregation information for incremental SSTables based on the behavior of the baseline. Valid values:
SKIP_INDEX_LEVEL parameter, the system uses the value of the tenant-level parameter default_skip_index_level to determine the default value of SKIP_INDEX_LEVEL. For more information, see default_skip_index_level. |
| PARTITION BY RANGE([column_name_list]) [SIZE('size_value')] [range_partition_list] | Specifies the creation of an automatic partitioned table. For more information, see Automatic partition splitting in the syntax for creating tables. |
| PARTITION BY RANGE (column_name) INTERVAL (expr) [subpartition_option] (range_partition) | Specifies the creation of an interval-partitioned table. For more information, see Create an interval-partitioned table. |
table_mode_value
Note
Except for the NORMAL mode, all other listed TABLE_MODE modes represent QUEUING tables. The QUEUING table is the most basic table type, and the other modes listed below (except for the NORMAL mode) represent more aggressive compaction strategies.
NORMAL: The default value, indicating normal mode. In this mode, the probability of triggering a major compaction after a data dump is very low.QUEUING: In this mode, the probability of triggering a major compaction after a data dump is low.MODERATE: Indicates moderate mode. In this mode, the probability of triggering a major compaction after a data dump is moderate.SUPER: Indicates super mode. In this mode, the probability of triggering a major compaction after a data dump is high.EXTREME: Indicates extreme mode. In this mode, the probability of triggering a major compaction after a data dump is high.
For more information about major compactions, see Adaptive major compaction.
dynamic_partition_policy_option
ENABLE = {true | false}: An optional parameter indicating whether to enable dynamic partition management. It can be modified. Valid values:true: The default value, indicating that dynamic partition management is enabled.false: Indicates that dynamic partition management is disabled.
TIME_UNIT = {'hour' | 'day' | 'week' | 'month' | 'year'}: A required parameter indicating the time unit for partitioning, i.e., the interval for automatically creating partition boundaries. It cannot be modified. Valid values:hour: Partitions are created by hour.day: Partitions are created by day.week: Partitions are created by week.month: Partitions are created by month.year: Partitions are created by year.
PRECREATE_TIME = {'-1' | '0' | 'n {hour | day | week | month | year}'}: An optional parameter indicating the precreation time. When dynamic partition management is scheduled, partitions are precreated so that max_partition_upper_bound > now() + precreate_time. It can be modified. Valid values:-1: The default value, indicating that no partitions are precreated.0: Indicates that only the current partition is precreated.n {hour | day | week | month | year}: Indicates the time span for precreating partitions. For example,3 hourindicates that partitions are precreated for the last 3 hours.
Note
- When multiple partitions are to be precreated, the partition boundary interval is specified by
TIME_UNIT. - The boundary of the first precreated partition is the ceiling of the existing maximum partition boundary based on
TIME_UNIT.
EXPIRE_TIME = {'-1' | '0' | 'n {hour | day | week | month | year}'}: An optional parameter indicating the partition expiration time. When dynamic partition management is scheduled, all partitions with upper bounds < now() - expire_time are deleted. It can be modified. Valid values:-1: The default value, indicating that partitions never expire.0: Indicates that all partitions except the current one are expired.n {hour | day | week | month | year}: Indicates the partition expiration time. For example,1 dayindicates that the partition expiration time is 1 day.
TIME_ZONE = {'default' | 'time_zone'}: An optional parameter indicating the timezone information used to determine the current time and the size of the partition key of thedateandtimestamptypes. It cannot be modified. Valid values:default: The default value, indicating that no timezone is configured and the tenant's timezone is used. For types other thandateandtimestamp, thetime_zonefield must bedefault.time_zone: Indicates a custom timezone offset. For example,+8:00is a timezone offset.
BIGINT_PRECISION = {'none' | 'us' | 'ms' | 's'}: An optional parameter indicating the timestamp precision of thenumbertype partition key. It cannot be modified. Valid values:none: The default value, indicating no precision (the partition key is not of thenumbertype).us: Indicates microsecond precision.ms: Indicates millisecond precision.s: Indicates second precision.
For more information about creating a dynamic partition table, see Create a dynamic partition table.
Here is an example:
CREATE TABLE tbl2 (col1 INT, col2 TIMESTAMP)
DYNAMIC_PARTITION_POLICY(
ENABLE = true,
TIME_UNIT = 'hour',
PRECREATE_TIME = '3 hour',
EXPIRE_TIME = '1 day',
TIME_ZONE = '+8:00',
BIGINT_PRECISION = 'none')
PARTITION BY RANGE (col2)(
PARTITION P0 VALUES LESS THAN (TIMESTAMP '2024-11-11 13:30:00')
);
Examples
Create a table
TEST_TBL1.obclient> CREATE TABLE TEST_TBL1 (col1 INT PRIMARY KEY, col2 VARCHAR(50));Create a table
TEST_TBL2and create eight partitions of the hash type.obclient> CREATE TABLE TEST_TBL2 (col1 INT PRIMARY KEY, col2 INT) PARTITION BY HASH(col1) PARTITIONS 8;Create a table
TEST_TBL3with a range partitioned partition set and hash partitioned subpartitions.obclient> CREATE TABLE TEST_TBL3 (col1 INT, col2 INT, col3 INT) PARTITION BY RANGE(col1) SUBPARTITION BY HASH(col2) SUBPARTITIONS 5 (PARTITION p0 VALUES LESS THAN(0), PARTITION p1 VALUES LESS THAN(100));Create a table
TEST_TBL4with zstd compression and 5% macroblock reserve space.obclient> CREATE TABLE tbl6 (col1 INT, col2 INT, col3 VARCHAR(64)) COMPRESS FOR ARCHIVE PCTFREE 5;Create a transaction-level temporary table
TEST_TBL5.obclient> CREATE GLOBAL TEMPORARY TABLE TEST_TBL5(col1 INT) ON COMMIT DELETE ROWS;Create a table
TEST_TBL6with constraints.obclient> CREATE TABLE TEST_TBL6 (col1 INT, col2 INT, col3 INT,CONSTRAINT equal_check1 CHECK(col2 = col3 * 2) ENABLE VALIDATE);Specify a foreign key for table
REF_T2. When theDELETEoperation affects key values in the parent table that correspond to matching rows in the child table, execute theSET NULLoperation.obclient> CREATE TABLE REF_T1(c1 INT PRIMARY KEY,C2 INT);obclient> CREATE TABLE REF_T2(c1 INT PRIMARY KEY,C2 INT,FOREIGN KEY(c2) REFERENCES ref_t1(c1) ON DELETE SET NULL);Create a non-templated range + range subpartitioned table
TEST_TBL7.obclient> CREATE TABLE TEST_TBL7 (col1 INT, col2 INT, col3 INT) PARTITION BY RANGE(col1) SUBPARTITION BY RANGE(col2) ( PARTITION p0 VALUES LESS THAN(100) ( SUBPARTITION p0_r1 VALUES LESS THAN(2019), SUBPARTITION p0_r2 VALUES LESS THAN(2020), SUBPARTITION p0_r3 VALUES LESS THAN(2021) ), PARTITION p1 VALUES LESS THAN(200) ( SUBPARTITION p1_r1 VALUES LESS THAN(2019), SUBPARTITION p1_r2 VALUES LESS THAN(2020), SUBPARTITION p1_r3 VALUES LESS THAN(2021) ), PARTITION p2 VALUES LESS THAN(300) ( SUBPARTITION p2_r1 VALUES LESS THAN(2019), SUBPARTITION p2_r2 VALUES LESS THAN(2020), SUBPARTITION p2_r3 VALUES LESS THAN(2021) ) );Specify a parallelism degree of 3 for table
TEST_TBL8.obclient> CREATE TABLE TEST_TBL8(col1 INT PRIMARY KEY, col2 INT) PARALLEL 3;Use the function to specify the default value of a column.
obclient> CREATE SEQUENCE SEQ_PERSONIPTVSEQ START WITH 1 MINVALUE 1 MAXVALUE 10 INCREMENT BY 2 NOCYCLE NOORDER CACHE 30;obclient> SELECT LPAD(SEQ_PERSONIPTVSEQ.NEXTVAL,18,TO_CHAR(SYSDATE,'YYYY-MM-DD HH24:MI:SS')) FROM DUAL;The following result is returned:
+----------------------------------------------------------------------------+ | LPAD(SEQ_PERSONIPTVSEQ.NEXTVAL,18,TO_CHAR(SYSDATE,'YYYY-MM-DDHH24:MI:SS')) | +----------------------------------------------------------------------------+ | 2025-04-08 19:35:1 | +----------------------------------------------------------------------------+obclient> CREATE TABLE FUNC_DEFAULT_TEST ( OID NUMBER(20,0) DEFAULT LPAD(SEQ_PERSONIPTVSEQ.NEXTVAL,18,TO_CHAR(SYSDATE,'YYYY-MM-DD HH24:MI:SS')) NOT NULL);Create a replicated table
DUP_T1at theclusterlevel. You can insert and read and write data from a replicated table, as you do from a regular table. If you use a Proxy to submit a read request, the request may be routed to any OBServer node. If you directly connect to an OBServer node and its local replica is readable, the request is processed on the connected node.obclient> CREATE TABLE DUP_T1(c1 int) DUPLICATE_SCOPE = 'cluster';obclient> INSERT INTO DUP_T1 VALUES(1);obclient> SELECT * FROM DUP_T1;The following result is returned:
+------+ | C1 | +------+ | 1 | +------+Create a columnstore table
TBL_CG.obclient> CREATE TABLE tbl1_cg (col1 NUMBER PRIMARY KEY, col2 VARCHAR2(50)) WITH COLUMN GROUP(each column);Specify the Skip Index attribute for a column during table creation.
obclient> CREATE TABLE TEST_INDEX( col1 NUMBER SKIP_INDEX(MIN_MAX, SUM), col2 FLOAT SKIP_INDEX(MIN_MAX), col3 VARCHAR2(1024) SKIP_INDEX(MIN_MAX), col4 CHAR(10) );Create a table
TEST_TBL9with a columncol1of the integer type. Specify that 5 parallel tasks be used for this operation and specify that the contents of the new tableTEST_TBL8will be sourced from the query results of tableTEST_TBL8.obclient> CREATE /*+ parallel(5) */ TABLE TEST_TBL9 (col1 NUMBER) AS SELECT col1 FROM TEST_TBL8;Create a table
TEST_TBL10with a columncol1as an auto-incrementing column and specified as a primary key.obclient> CREATE TABLE TEST_TBL10 ( col1 INT GENERATED BY DEFAULT AS IDENTITY, col2 VARCHAR2(50), PRIMARY KEY (col1) );Create a table
tbwith a persistent macroblock-level bloom filter enabled.obclient> CREATE TABLE tb(c1 INT PRIMARY KEY, c2 INT) enable_macro_block_bloom_filter = True;Create a table
tbwith the new flat row-based storage format (version 2).obclient> CREATE TABLE tb(c1 INT PRIMARY KEY, c2 INT) micro_block_format_version = 2;Create a table with a data expiration time of 7 days.
obclient(SYS@oracle001)[SYS]> CREATE TABLE TTL_TBL1( ID INT PRIMARY KEY, VAL VARCHER2(100) ) MERGE_ENGINE = append_only TTL ora_rowscn + INTERVAL 7 DAY BY COMPACTION;Create a table
tbl_eand specify the incremental data format as the new encoding-based incremental data format.obclient> CREATE TABLE tbl_e(col1 INT PRIMARY KEY, col2 INT) DELTA_FORMAT = 'encoding';
Limitations of global temporary tables in Oracle compatibility mode
- Temporary tables in Oracle compatibility mode are widely used in various business scenarios and provide basic correctness and functionality guarantees.
- The primary purpose of using temporary tables is to ensure compatibility and reduce the need for business modifications. They can be used in limited scenarios where performance requirements are not high. If the business scenario can be converted to a regular table, it is better to do so.
Performance and stability
- The SQL execution efficiency of temporary tables is generally similar to that of regular tables, with no significant advantages.
- Temporary tables require additional work to clean up data when transactions end or sessions are disconnected, which incurs additional overhead.
- The checks and cleanup actions performed on temporary tables during login may put pressure on the login thread, leading to longer login times, and in severe cases, login failures.
Creating temporary tables
When creating a temporary table, the system automatically modifies the create table statement:
- Adds a new
SYS_SESSION_IDcolumn as the primary key. - Adds a new
SYS_SESS_CREATE_TIMEcolumn. - Creates a hash-partitioned table with
SYS_SESSION_IDas the partitioning key, with a fixed number of 16 partitions.
For example:
obclient> CREATE GLOBAL TEMPORARY TABLE TEST_TBL11(
c1 INT,
c2 INT,
PRIMARY KEY(c1)
);
is rewritten to the following form:
obclient> CREATE GLOBAL TEMPORARY TABLE TEST_TBL11(
SYS_SESSION_ID INT,
SYS_SESS_CREATE_TIME INT,
c1 INT,
c2 INT,
PRIMARY KEY(SYS_SESSION_ID, c1)
)
PARTITION BY HASH(SYS_SESSION_ID) PARTITIONS 16;
DML and query statements on temporary tables
When executing an INSERT statement, the system automatically inserts the current session's session ID and session creation time into the SYS_SESSION_ID and SYS_SESS_CREATE_TIME columns, respectively.
When executing UPDATE, DELETE, or SELECT statements, the system automatically adds a filter condition to the statement containing the temporary table: "SYS_SESSION_ID = current session session_id". This allows the SQL optimizer to perform partition pruning and query range extraction.
Data cleanup for temporary tables
- For temporary tables with the
ON COMMIT DELETE ROWSoption (transactional temporary tables, which is the default option), a new transaction is started at the end of the transaction to delete the temporary table data using anDELETEstatement. - For temporary tables with the
ON COMMIT PRESERVE ROWSoption (session temporary tables), a new transaction is started when the session is disconnected to delete the temporary table data using anDELETEstatement. - Due to the possibility of session ID reuse, OceanBase Database V3.2.4 BP4 and earlier versions will check the data for the current session ID upon login. If additional cleanup is needed, it will be performed.
- The login checks and cleanup operations performed due to non-unique session IDs may lead to failures (such as cluster login failures).
Routing for temporary tables
Transactional temporary tables (
ON COMMIT DELETE ROWS) Temporary table access within a transaction can only be routed to the node where the transaction was initiated.Session temporary tables (
ON COMMIT PRESERVE ROWS) After a session accesses a temporary table, the OBServer node notifies the Proxy, which then routes subsequent requests to the current session.
Dropping temporary tables
Like regular tables, you can successfully execute DROP statements while executing DML operations. All data in the temporary table will be deleted. This behavior differs from Oracle, where you must wait until all sessions no longer hold temporary table resources before you can execute DROP.
Support for cross-functional features
| Feature | Supported in V3.2.4 BP4 and earlier versions | Supported in V3.2.4 BP5 and V3.2.x later versions | Supported in V4.2.0 |
|---|---|---|---|
| Plan sharing across sessions | No | No | Yes |
| Login without triggering checks and cleanup | No | Yes | Yes |
MERGE INTO statement |
No | No | Yes |
Workarounds for critical issues
Login failure
- Stop the business related to temporary tables, delete the temporary tables, or perform a major compaction. This usually resolves the issue. If the issue persists, proceed to step 2.
- Restart the machine that cannot log in.
PL Cache expansion due to plan reuse failure
For example, consider a PL/SQL block that includes a temporary table:
obclient> CREATE OR REPLACE PROCEDURE PRO_1
AS
var1 VARCHAR2(100);
BEGIN
-- Use dynamic SQL to create a temporary table
EXECUTE IMMEDIATE 'CREATE GLOBAL TEMPORARY TABLE temp_table (
col1 VARCHAR2(100)
) ON COMMIT DROP';
-- Dynamically insert data
EXECUTE IMMEDIATE 'INSERT INTO temp_table VALUES (''xxx'')';
-- Dynamically query
EXECUTE IMMEDIATE 'SELECT col1 FROM temp_table WHERE ROWNUM = 1' INTO var1;
DBMS_OUTPUT.PUT_LINE(var1);
END PRO_1;
/
Since plans cannot be shared across sessions for temporary tables, each session must compile the PRO_1 procedure to generate a corresponding cache, which may lead to stability issues. Changing the temporary table SQL to use dynamic SQL can resolve this issue.
Data not cleaned up during failures
Failures may result in data residue, but this generally does not affect usage. If excessive residual data remains, you can drop the temporary table and recreate it.
Read-only and read/write tables in an Oracle tenant
In an Oracle tenant, you can use the CREATE TABLE statement to create READ ONLY and READ WRITE tables. You can also use the ALTER TABLE statement to change the read/write attribute of a table.
Notice
Users with the SUPER privilege cannot successfully execute the related operations. We recommend that you use a regular user.
Procedure:
Create a regular user:
CREATE USER test1 IDENTIFIED BY "12345";Grant the user the CONNECT and CREATE TABLE privileges:
GRANT CREATE SESSION TO test1; GRANT CREATE TABLE TO test1;Connect to OceanBase Database as the regular user:
obclient -hxxx.xx.xxx.xxx -P2881 -utest1@oracle001 -ACreate a read-only table:
CREATE TABLE tb_readonly1(id INT) READ ONLY;Attempt to insert data into the read-only table (expected to fail):
INSERT INTO tb_readonly1 VALUES (1); -- Expected error: ORA-00600: internal error code, arguments: -5235, The table 'TEST1.TB_READONLY1' is read only so it cannot execute this statementCreate a read/write table:
CREATE TABLE tb_readwrite1(id INT) READ WRITE;Insert data into the read/write table (expected to succeed):
INSERT INTO tb_readwrite1 VALUES (99),(98); -- Expected result: Query OK, 2 rows affected (0.002 sec) -- Records: 2 Duplicates: 0 Warnings: 0Convert the read/write table to a read-only table:
ALTER TABLE tb_readwrite1 READ ONLY;Attempt to insert data into the converted read-only table (expected to fail):
INSERT INTO tb_readwrite1 VALUES (96),(97); -- Expected error: ORA-00600: internal error code, arguments: -5235, The table 'TEST1.TB_READWRITE1' is read only so it cannot execute this statement
