---
title: 无主键表的 ROWID 和隐藏主键 __pk_increment-OceanBase数据库使用指南
description: 了解OceanBase数据库在实际应用中关于无主键表的 ROWID 和隐藏主键 __pk_increment相关的常见问题和使用技巧，帮助您快速解决无主键表的 ROWID 和隐藏主键 __pk_increment的难题。
---
切换语言

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

划线反馈

# 无主键表的 ROWID 和隐藏主键 __pk_increment

更新时间：2026-05-21 01:56

适用版本： V2.1.x、V2.2.x、V3.1.x、V3.2.x、V4.0.x、V4.1.x、V4.2.x 内容类型：TechNote  

无主键表是指用户在创建时没有指定主键的表，此时 OceanBase MySQL 模式和 Oracle 模式的数据库均会采用一个自增的列作为隐藏主键。隐藏主键的数据类型为 BIGINT，最大值为 2^64 。

对于 OceanBase Oracle 模式的数据库，跟原生 Oracle 对齐，每个表都有一个名为 ROWID 的伪列。OceanBase Oracle 数据库使用 ROWID 数据类型来存储数据库中每一行的地址。本文主要介绍 OceanBase 各个版本中这两个对象的特点、二者之间的关系，以及如何使用 select 语句来查询 ROWID 和隐藏主键。

## 详细说明

### ROWID

在 OceanBase Oracle 数据库中，每个表都有一个名为 ROWID 的伪列。 伪列的行为类似一个表的普通列，但实际上并没有存储在表中。可以通过伪列执行 SELECT 操作，但不能对它们的值执行 `INSERT`、`UPDATE`、`DELETE` 操作。伪列也类似于没有参数的 SQL 函数。不带参数的函数通常为结果集中的每一行返回相同的值，而伪列通常为每一行返回不同的值。 ROWID 伪列的值是每行数据的 Key（对于有主键表是 Primary Key，对于无主键表是系统自动生成的序列），通过 Base64 编码转换而成。可以通过使用保留字 ROWID 作为列名的 SQL 来访问每一行的 ROWID。 在 OceanBase 数据库 V2.x/V3.x 版本中无主键表的 ROWID 会编码分区键的信息（OceanBase 数据库 V2.x/V3.x 版本中无主键表的 ROWID 是按照 **自增列+分区键** 编码转换的），长度不固定。如果分区键字段内容很长的话，ROWID 就会很长；而在 OceanBase 数据库 V4.x 版本中无主键表的 ROWID 为固定长度 16 字节，彻底解决了 ROWID 超长问题。

### 隐藏主键

OceanBase 数据库的无主键表采用自增列作为隐藏主键。无主键表利用了自增列的多分区全局唯一的原则，以此保证无主键表隐藏键的唯一性。

**备注：OceanBase 数据库 V4.x 版本中不同于 OceanBase 数据库 V3.x 版本，对于 V4.x 版本中的无主键分区表，隐藏列在表级别不唯一，在分区级别唯一**。

- ROWID 长度调整前（OceanBase 数据库 V2.x/V3.x 版本）。

  无主键表隐藏主键的格式如下：

  ```shell
  create table t1(c1 int); -- 隐藏主键为__pk_increment

  ```

  ```shell
  create table t1(c1 int, c2 int) partition by hash(c2); -- 隐藏主键为(c2, __pk_increment)

  ```

可以看出无主键表的隐藏主键里面会包含分区键，这使得 OceanBase 的无主键表 ROWID 的长度是不固定的，最长可能会到 16K 。

- ROWID长度调整后（OceanBase 数据库 V4.x 版本）。

  无主键表的隐藏主键格式变为如下：

  ```

  ```shell
  create table t1(c1 int, c2 int) partition by hash(c2); -- 隐藏主键为(__pk_increment)

  ```

  可以看出在 OceanBase 数据库 V4.x 版本中无主键分区表自动创建的隐藏主键不再包含分区键了。

## 二者关系及如何查看

OceanBase 数据库 Oracle 模式中的 ROWID 是基于 `__pk_increment` 和其它信息（OceanBase 数据库 V2.x/3.x 版本中为分区键，V4.x 版本中为 tablet id）一起编码产生的一个伪列，但不等同于 `__pk_increment` 。

示例如下：

1. 查看表 t2 的表结构。

   ```shell
   obclient [SYS]> desc t2;

   ```

   输出结果如下：

   ```shell
   +-------+---------------+------+------+---------+-------+
   | FIELD | TYPE          | NULL | KEY  | DEFAULT | EXTRA |
   +-------+---------------+------+------+---------+-------+
   | ID    | NUMBER(38)    | YES  | UNI  | NULL    | NULL  |
   | NAME  | VARCHAR2(100) | YES  | NULL | NULL    | NULL  |
   +-------+---------------+------+------+---------+-------+
   2 rows in set (0.004 sec)

   ```
 2. 查询表 t2 的完整结构。

   ```shell
   obclient [SYS]> show create table t2;

   ```

   输出结果如下：

   ```shell
   +-------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
   | TABLE | CREATE TABLE                                                                                                                                                                                           |
   +-------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
   | T2    | CREATE TABLE "T2" (
   "ID" NUMBER(*,0),
   "NAME" VARCHAR2(100),
   UNIQUE ("ID")
   ) COMPRESS FOR ARCHIVE REPLICA_NUM = 1 BLOCK_SIZE = 16384 USE_BLOOM_FILTER = FALSE TABLET_SIZE = 134217728 PCTFREE = 0 |
   +-------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
   1 row in set (0.005 sec)

   ```
 3. 查询表 t2 的内容。

   ```shell
   obclient [SYS]> select * from t2;

   ```

   输出结果如下：

   ```shell
   +------+------+
   | ID   | NAME |
   +------+------+
   |    1 | a    |
   |    2 | b    |
   | NULL | c    |
   +------+------+
   3 rows in set (0.001 sec)

   ```
 4. 在查询表 t2 语句中添加 hint 打开隐藏列可见，获取 `__pk_increment` 值。

   ```shell
   obclient [SYS]> select /*+ opt_param('hidden_column_visible','true') */ id,"__pk_increment" from t2;   -- OceanBase 数据库 V4.x 版本 Oracle 模式中需要使用双引号，如果使用反引号``的话会报错的

   ```

   输出结果如下：

   ```shell
   +------+----------------+
   | ID   | __pk_increment |
   +------+----------------+
   |    1 |              1 |
   |    2 |              4 |
   | NULL |              6 |
   +------+----------------+
   3 rows in set (0.001 sec)

   ```
 5. 在查询表 t1 语句中添加 hint 打开隐藏列可见，获取 `__pk_increment` 值。

   ```shell
   MySQL [test]> select /*+ opt_param('hidden_column_visible','true') */ id,`__pk_increment` from t1; -- OceanBase 数据库 MySQL 模式中需要使用反引号``，或者不加任何引号

   +------+----------------+
   | id   | __pk_increment |
   +------+----------------+
   |    1 |              1 |
   |    2 |              2 |
   | NULL |              3 |
   +------+----------------+
   3 rows in set (0.001 sec)

   MySQL [test]> select /*+ opt_param('hidden_column_visible','true') */ id,__pk_increment from t1;
   +------+----------------+
   | id   | __pk_increment |
   +------+----------------+
   |    1 |              1 |
   |    2 |              2 |
   | NULL |              3 |
   +------+----------------+
   3 rows in set (0.003 sec)

   ```
 6. 在查询表 t2 语句中添加 hint 打开隐藏列可见，获取 `__pk_increment` 和 `ROWID` 值。

   ```shell
   obclient [SYS]> select /*+ opt_param('hidden_column_visible','true') */ id,"__pk_increment",rowid from t2;

   ```

   输出结果如下：

   ```shell
   +------+----------------+------------------+
   | ID   | __pk_increment | ROWID            |
   +------+----------------+------------------+
   |    1 |              1 | gAADDVQAAAAAAQ== |
   |    2 |              4 | gAADDVQAAAAABA== |
   | NULL |              6 | gAADDVQAAAAABg== |
   +------+----------------+------------------+
   3 rows in set (0.003 sec)

   ```
 7. 在查询表 t2 语句中添加 hint 打开隐藏列可见，获取 `__pk_increment` 值和 `ROWID` 的长度值。

   ```shell
   obclient [SYS]> select /*+ opt_param('hidden_column_visible','true') */ id,"__pk_increment",length(rowid) from t2;

   ```

   输出结果如下：

   ```shell
   +------+----------------+---------------+
   | ID   | __pk_increment | LENGTH(ROWID) |
   +------+----------------+---------------+
   |    1 |              1 |            16 |
   |    2 |              4 |            16 |
   | NULL |              6 |            16 |
   +------+----------------+---------------+
   3 rows in set (0.001 sec)

   ```

## 总结

- `hidden_column_visible` 的 sql hint 是在 OceanBase 数据库 V4.x 版本中才引入的，而在 V3.x 版本中无此 hint，因此在 OceanBase 数据库 V3.x 版本中 Oracle 模式下目前暂不支持直接查询隐藏主键 `__pk_increment` 。
 - 对于 OceanBase 数据库 V2.x/V3.x/V4.x MySQL 模式租户，还可以使用内部用户 `__oceanbase_inner_drc_user` 去查询隐藏主键，具体参见：[OceanBase 数据库中如何访问隐藏自增列的值](https://www.oceanbase.com/knowledge-base/oceanbase-database-1000000000207715)。

## 适用版本

OceanBase 数据库 V2.x、V3.x、V4.x 版本。

上一篇

[如何确认 Oracle 租户的 row movement 属性是否开启](https://www.oceanbase.com/knowledge-base/oceanbase-database-1000000000207753)

下一篇

[如何把 queuing 表转回普通表](https://www.oceanbase.com/knowledge-base/oceanbase-database-1000000000207716) ![有帮助](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) 咨询热线
