8.12. 对象标识符类型

PostgreSQL 在内部使用对象标识符(OID)作为各种系统表的主键。 同时,系统还给用户创建的表增加一个 OID 系统字段(除非在建表时声明了 WITHOUT OIDS 或者是配置参数 default_with_oids 设置成了假)。 类型 oid 代表一个对象标识符。除此以外还有几个 oid 的别名: regprocregprocedureregoperregoperatorregclass,和 regtypeTable 8-19 显示了概要。

目前 oid 类型是用一个无符号的四字节整数实现的。 因此,它是不够用于提供大数据库范围内的唯一性保证的, 甚至在单个的大表中也不行。因此,我们不鼓励在用户创建的表中使用 OID 字段做主键。OID 最好只是用于引用系统表。

注意: PostgreSQL 8.0.0 里,用户创建的表缺省时有 OID。 不过,这个行为在将来的 PostgreSQL 版本里很有可能改变。 最后,用户创建的表将不包括 OID 系统字段,除非在创建表的时候声明了 WITH OIDS, 或者配置参数 default_with_oids 设置为真。如果你的应用要求表里面有一个系统字段 OID, 那么应该在创建表的时候声明 WITH OIDS,以保证与将来的 PostgreSQL 版本兼容。

oid 类型本身除了比较之外还有几个操作。 不过,它可以转换为整数,然后用标准的整数操作符操作。(如果你这么干, 那么请注意可能的有符号和无符号之间的混淆。)

OID 别名类型没有自己的操作,除指明的输入和输出过程之外。 这些过程可以为系统对象接受和显示符号名,而不仅仅是类型 oid 将要使用的行数值。别名类型允许我们简化为对象查找 OID 值的过程。 比如,检查和一个表 mytable 相关的pg_attribute 行, 我们可以写

SELECT * FROM pg_attribute WHERE attrelid = 'mytable'::regclass;

而不用

SELECT * FROM pg_attribute
  WHERE attrelid = (SELECT oid FROM pg_class WHERE relname = 'mytable');

虽然看上去不坏,但是这个例子还是简化了好多,如果在不同的模式里有好多叫 mytable 的表,那么我们需要写一个更复杂的子查询。 regclass 的输入转换器处理根据模式路径设置的表检索工作,所以它自动干了"正确的事情"。 类似的还有,把一个表的 OID 转换成 regclass 是查找一个 OID 对应的符号名称的最简单方法。

Table 8-19. 对象标识类型

名字引用描述数值例子
oid任意数字的对象标识符564182
regprocpg_proc函数名字sum
regprocedurepg_proc带参数类型的函数sum(int4)
regoperpg_operator操作符名+
regoperatorpg_operator带参数类型的操作符*(integer,integer)或者-(NONE,integer)
regclasspg_class关系名pg_type
regtypepg_type数据类型名integer

所有 OID 别名类型都接受有模式修饰的名字,并且如果在当前 搜索路径中,在不增加修饰的情况下无法找到该对象,那么在输出 时将显示有模式修饰的名字。regprocregoper 别名类型将只接受唯一的输入名字(不能重载),因此它们的用途有限; 对于大多数应用,regprocedureregoperat或者 更合适。对于 regoperat或者,单目操作符是通过在那些未用的操作数 上写NONE来标识的。

系统使用的另外一个标识符类型是 xid,或者说是事务(缩写xact) 标识符。它是系统字段 xminxmax 的 数据类型。事务标识符是 32 位的量。

系统需要的第三种标识符类型是 cid,或者命令标识符。 它是系统字段 cmincmax 的数据类型。 命令标识符也是 32 位的量。

系统使用的最后的标识符类型是 tid,或者说是元组标识符。 它是系统表字段 ctid 的数据类型。元组 ID 是一对儿数值 (块号,块内的元组索引),它标识该元组在其所在表内的物理位置。

(系统字段在 Section 5.2 里有更多解释。)