---
title: "创建表 - OceanBase 数据库 V4.2.4 | OceanBase 文档中心"
description: 创建表 您可以使用 CREATE TABLE 语句来创建表。 本节主要介绍非分区表的创建，分区表的创建及使用请参见 创建分区表 。 创建非分区表 创建非分区表是指创建只有一个分区的表。 创建非分区表的示例语句如下： obclient&gt; CREATE TABLE table_name1(w_id int, w_ytd …
---
切换语言

- 中文站 - 简体中文
- International - English
- 日本站 - 日本語

文档反馈![](https://mdn.alipayobjects.com/huamei_22khvb/afts/img/A*P8CuR4UJ_FkAAAAAAAAAAAAADiGDAQ/original) OceanBase 数据库分布式版 - V 4.2.4

# 创建表

更新时间：2024-12-02 16:46:22

[编辑](https://github.com/oceanbase/oceanbase-doc/edit/V4.2.4/zh-CN/700.reference/300.database-object-management/200.manage-object-of-oracle-mode/100.manage-tables-of-oracle-mode/200.create-a-table-for-oracle-tenant-of-oracle-mode.md)  

您可以使用 `CREATE TABLE` 语句来创建表。

本节主要介绍非分区表的创建，分区表的创建及使用请参见 [创建分区表](https://www.oceanbase.com/docs/common-oceanbase-database-cn-1000000001035404)。

## 创建非分区表

创建非分区表是指创建只有一个分区的表。

创建非分区表的示例语句如下：

```sql
obclient> CREATE TABLE table_name1(w_id int,
w_ytd decimal(12,2),
w_tax decimal(4,4),
w_name varchar(10),
w_street_1 varchar(20),
w_street_2 varchar(20),
w_city varchar(20),
w_state char(2),
w_zip char(9),
unique(w_name, w_city),
primary key(w_id)
);

```

```sql
obclient> CREATE TABLE table_name2 (c_w_id int NOT NULL,
c_d_id int NOT null,
c_id int NOT null,
c_discount decimal(4, 4),
c_credit char(2),
c_last varchar(16),
c_first varchar(16),
c_middle char(2),
c_balance decimal(12, 2),
c_ytd_payment decimal(12, 2),
c_payment_cnt int,
c_credit_lim decimal(12, 2),
c_street_1 varchar(20),
c_street_2 varchar(20),
c_city varchar(20),
c_state char(2),
c_zip char(9),
c_phone char(16),
c_since date,
c_delivery_cnt int,
c_data varchar(500),
FOREIGN KEY (c_w_id) REFERENCES table_name1(w_id),
primary key (c_w_id, c_d_id, c_id)
);

```

示例中创建了 2 个表，并同时对表中的列定义了一些约束信息，包括在不同列上创建的主键和外键等。更多主键、外键等的介绍，请参见 [定义列的约束类型](https://www.oceanbase.com/docs/common-oceanbase-database-cn-1000000001035385)。

创建表的列时请选择正确的数据类型，有关 SQL 数据类型的详细描述，请参见 [数据类型](https://www.oceanbase.com/docs/common-oceanbase-database-cn-1000000001037556)。

#### 说明

基于性能和后期维护的需要，建议建表时为表设计主键或者唯一键。如果没有合适的字段作为主键，可以为表增加一个数值列作为主键，并使用 Oracle 租户的序列为该列填充值。有关序列的介绍请参见 [管理序列](https://www.oceanbase.com/docs/common-oceanbase-database-cn-1000000001033714)。

## 创建复制表

复制表是 OceanBase 数据库中的一种特殊表结构，支持在任意一个副本读取数据的最新修改，适合于对写入频率要求较低，读延时和读负载均衡要求较高的场景。

在创建复制表之后，该表的副本会分布在租户下的所有 OBServer 节点上。这些副本中，有一个被选为 Leader，可以接受读写请求，而其他副本只能接受读请求。

复制表功能在 OceanBase 数据库 V3.x 版本上就已经存在，而对于 V4.x 版本，由于 OceanBase 数据库的架构有了比较大的变化，V4.x 复制表为了适应单机日志流的新架构，构建了基于分区的可读版本号校验以及基于日志流的 Lease 授予机制，用于保证强一致性读的正确性。

另外，V4.x 版本的复制表功能完善了切主不 Kill 事务的能力，在用户或负载均衡发起 Leader 切换时，未提交的复制表事务不会像 V3.x 版本一样无法继续，而是可以在切主后继续执行。对比 V3.x 版本，V4.x 的复制表功能也有着更好的写事务性能和更强的容灾能力，副本宕机对于读操作的影响更低。

### 复制表使用限制

- 复制表：

     - 创建复制表限制：sys 租户、meta 租户没有广播日志流，不支持创建复制表。
     - 写入性能受节点数影响：因为复制表写，需要同步到所有副本，所以节点数量越大，对写入性能影响越大。

           - 规避方式：尽量避免复制表的写跟读在同一个事务，复制表事务的纯写或者纯读都没问题。
     - 属性转换：

           - 复制表与 TableGroup 互斥，修改复制表的 TableGroup 属性会报错；普通表转为复制表时，如果普通表属于某个 TableGroup，属性变更命令将报错。
           - 复制表转换依赖负载均衡及 transfer，需要保证相关配置项是打开状态。
     - 路由：

           - 事务中有复制表的写操作，之后查询复制表，如果随机路由到 follower，会遇到副本不可读的问题，observer 内部二次转发到复制表的 Leader，影响查询性能。

                   - ODP V4.3.3 已调整路由策略，如果有复制表的写操作，后续查询路由到复制表的 Leader。
           - 复制表 `JOIN` 普通表的查询操作，会按照复制表去随机路由（对 `JOIN` 查询，ODP 是按照第一张表路由），此时可能会路由到普通表的非 Leader 节点，导致出现远程计划。
           - 普通表属性变更为复制表，ODP 无法感知，不能按照复制表路由分摊压力。
     - 事务内，有复制表做过变更，后续的查询操作：查询复制表时，生成的执行计划会选择本地副本，但是因为做过变更，会报副本不可读的错误，SQL 重试选择 Leader 副本，此时 plan cache 无法命中，导致查询性能差。
 - 广播日志流：

     - 每个用户租户最多只能有一个广播日志流。
     - 不支持广播日志流和普通日志流之间的属性转换。
     - 不支持手动删除广播日志流，目前随着租户删除而删除。

### 创建复制表语法

创建复制表的语法是在 `CREATE TABLE` 语句后增加 `DUPLICATE_SCOPE` 选项，仅用户租户可以创建复制表，`sys` 租户无法创建复制表。创建复制表的 SQL 语句如下：

```sql
CREATE TABLE table_name column_definition DUPLICATE_SCOPE='none | cluster';

```

其中，`DUPLICATE_SCOPE` 参数用来指定复制表的属性，取值如下：

- `none`：表示该表是一个普通表。
 - `cluster`：表示该表是一个复制表，Leader 需要将事务复制到当前租户的所有 F 副本及 R 副本。

创建表时，如果不指定 `DUPLICATE_SCOPE`，则默认值为 `none`。

```sql
CREATE TABLE dup_t1 (c1 NUMBER,c2 NUMBER) DUPLICATE_SCOPE= 'cluster';

```

当某个租户的第一个复制表被创建时，系统会同时创建一个特殊的日志流——广播日志流。之后新建的复制表都会创建到广播日志流上。广播日志流与普通日志流的不同之处在于，广播日志流会自动地在租户内的每个 OBServer 节点上都部署一个副本，保证在理想情况下，复制表可以在任意一个 OBServer 节点上提供强一致性读。您可以通过以下 SQL 查看租户的复制表所在的广播日志流：

```sql
SELECT * FROM SYS.DBA_OB_LS WHERE flag LIKE "%DUPLICATE%";

```

查询结果的示例如下。

```shell
+-------+--------+--------------+---------------+-------------+---------------------+----------+---------------------+---------------------+-----------+
| 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 | 1684982852976428261 |     NULL | 1684983282912048623 | 1684983282912048623 | DUPLICATE |
+-------+--------+--------------+---------------+-------------+---------------------+----------+---------------------+---------------------+-----------+
1 rows in set

```

示例中，`LS_ID` 为 `1003` 的日志流即为广播日志流，当前租户的所有复制表都创建在该日志流上。有关广播日志流的更多介绍，请参见 [副本介绍](https://www.oceanbase.com/docs/common-oceanbase-database-cn-1000000001033197)。

复制表创建成功后，可以与普通表一样进行插入和读写操作。不同的是，如果使用 Proxy 连接数据库，则读请求会路由到任意一个 OBServer 节点执行，而普通表只能将读请求路由到 Leader 节点执行。如果是通过直连方式连接数据库，则只要本地副本可读，系统就会在直连的 OBServer 节点上执行读请求。更多关于 Proxy 路由规则的介绍，请参见 [连强读分区表路由](https://www.oceanbase.com/docs/common-odp-doc-cn-1000000000517777)。

## 复制已有表的数据创建新表

通过 `CREATE TABLE AS SELECT` 语句复制表的基本数据类型和数据，但不包含约束、索引和非空等属性。

示例语句如下：

```sql
CREATE TABLE t2_copy AS SELECT * FROM t2;

```

不支持使用 `CREATE TABLE LIKE` 语句复制表结构。

 上一篇 下一篇 ![有帮助](https://gw.alipayobjects.com/mdn/ob_asset/afts/img/A*y6ocSqN8cqsAAAAAAAAAAAAAARQnAQ)![无帮助](https://gw.alipayobjects.com/mdn/ob_asset/afts/img/A*BG9IQJyLHF8AAAAAAAAAAAAAARQnAQ)![反馈](https://gw.alipayobjects.com/mdn/ob_asset/afts/img/A*eTWdQKCRKHwAAAAAAAAAAAAAARQnAQ)[AI](https://www.oceanbase.com/obi) 咨询热线
