每个表都有几个系统字段,这些字段是由系统 隐含定义的。因此,这些名字不能用于用户定义的字段名。 (请注意这些限制与这个名字是否关键字无关;把名字用引号 括起来并不能让你逃离这些限制。)你实际上不需要注意这些字段, 只要知道它们存在就可以了。
一行的对象标识符(对象 ID)。这是一个序列号,是由 PostgreSQL 给所有表的行自动追加的 (除非建表的时候用了 WITHOUT OIDS,这种情况下 就不会出现这个字段)。这个字段的类型是 oid (和字段同名);参阅 Section 8.11 获取有关这种 类型的更多信息。
包含本行的表的 OID。这个字段对那些从继承层次中选取的查询特别有用, 因为如果没有它的话,我们就很难说明一行来自哪个独立的表。 tableoid 可以和 pg_class 的 oid 字段连接起来获取表名字。
插入该行版本的事务的标识(事务 ID)。(注意:在这个环境里, 一个行版本是一行的一个状态;一行的每次更新都为同一个逻辑行创建一个新的行版本。)
在插入事务内部的命令标识(从零开始)。
删除事务的标识(事务ID),如果不是被删除的行版本,那么是零。 在一个可见行版本里,这个字段有可能是零:这通常意味着删除事务还没有提交, 或者是一个删除的企图被回滚掉了。
在删除事务内部的命令标识符,或者是零。
一个行版本在它所处的表内的物理位置。请注意,尽管 ctid 可以用于非常快速地定位行版本,但每次 VACUUM FULL 之后, 一个行的 ctid 都会被更新或者移动。 因此 ctid 是不能作为长期的行标识符的。 应该使用OID,或者更好是用户定义的序列号,来标识一个逻辑行。
OID 是 32 位的量,是在同一个集群内通用的计数器上赋值的。 对于一个大型或者长时间使用的数据库,这个计数器是有可能重叠的。 因此,假设 OID 是唯一的是非常错误的,除非你自己采取了措施来保证这个唯一。 在使用 OID 作为行的标识符的时候,我们建议采用的措施是在使用 OID 的每个表的 OID 字段创建一个唯一约束。绝对不要假设 OID 是跨表唯一的;如果你需要全数据库 范围内的标识,请使用 tableoid 和行的 OID 的组合。 (将来的 PostgreSQL 版本很可能为每个表使用独立的 OID 计数器,这样 tableoid 就必须包含在全局唯一 标识的实现里面。)
事务标识符也是 32 位的量。在长时间运转的数据库里,它也可能会重叠。 只要我们采取一些合适的维护步骤,这并不是很要命的问题; 参阅 Chapter 21 获取细节。不过,在长时间运行的 环境里(超过十亿次事务)依赖事务 ID 的唯一性并非明智的做法。
命令标识符也是 32 位的量。这样就在一个事务里有232(四十亿) 条 SQL 命令的硬限制。在现实里这个限制应该不是 什么问题 --- 注意这个限制是 SQL 命令的条数, 而不是处理的行版本的条数。