2025年9月25日: PostgreSQL 18 发布!
支持的版本:当前 (18) / 17 / 16 / 15 / 14 / 13
开发版本:devel
不受支持的版本:12 / 11 / 10 / 9.6 / 9.5 / 9.4 / 9.3 / 9.2 / 9.1 / 9.0 / 8.4 / 8.3 / 8.2 / 8.1 / 8.0 / 7.4 / 7.3

8.19. 对象标识符类型 #

对象标识符(OID)在 PostgreSQL 内部用作各种系统表的primary key。类型 oid 代表一个对象标识符。此外,还有几种 oid 的别名类型,每种都命名为 regsomething表 8.26 概览。

类型 oid 目前实现为一个无符号四字节整数。因此,它不足以在大型数据库中提供跨数据库的唯一性,甚至在大型单个表中也不够。

类型 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 的表,则需要一个更复杂的子查询来选择正确的 OID。 regclass 输入转换器会根据模式路径设置处理表查找,因此它会自动执行“正确的事情”。类似地,将表的 OID 强制转换为 regclass 对于数字 OID 的符号显示非常方便。

表 8.26. 对象标识符类型

名称 参考文献 描述 示例值
oid 任意 数字对象标识符 564182
regclass pg_class 关系名称 pg_type
regcollation pg_collation 排序规则名称 "POSIX"
regconfig pg_ts_config 文本搜索配置 english
regdictionary pg_ts_dict 文本搜索字典 simple
regnamespace pg_namespace 命名空间名称 pg_catalog
regoper pg_operator 运算符名称 +
regoperator pg_operator 带参数类型的运算符 *(integer,​integer)-(NONE,​integer)
regproc pg_proc 函数名称 sum
regprocedure pg_proc 带参数类型的函数 sum(int4)
regrole pg_authid 角色名称 smithee
regtype pg_type 数据类型名称 integer

对于按命名空间分组的对象,大多数 OID 别名类型都接受模式限定的名称,并且在输出时如果对象在当前搜索路径中无法通过非限定名称找到,则会显示模式限定的名称。例如,myschema.mytableregclass 可接受的输入(如果存在这样的表)。该值可能输出为 myschema.mytable,或仅输出 mytable,具体取决于当前搜索路径。 regprocregoper 别名类型仅接受唯一的输入名称(非重载),因此它们的用途有限;对于大多数用途,regprocedureregoperator 更合适。对于 regoperator,一元运算符通过将未使用的操作数写为 NONE 来标识。

这些类型的输入函数允许标记之间的空格,并将大写字母折叠为小写,除非在双引号内;这是为了使语法规则与 SQL 中书写对象名称的方式相似。反之,输出函数将在需要时使用双引号,以使输出成为有效的 SQL 标识符。例如,一个名为 Foo(首字母 F 大写)且接受两个整数参数的函数的 OID 可以输入为 ' "Foo" ( int, integer ) '::regprocedure。输出将类似于 "Foo"(integer,integer)。函数名和参数类型名称都可以被模式限定。

许多内置的 PostgreSQL 函数接受表的 OID 或其他类型的数据库对象,并且为了方便起见,它们被声明为接受 regclass(或相应的 OID 别名类型)。这意味着您不必手动查找对象的 OID,而可以直接将其名称作为字符串文字输入。例如,nextval(regclass) 函数接受序列关系的 OID,因此您可以这样调用它:

nextval('foo')              operates on sequence foo
nextval('FOO')              same as above
nextval('"Foo"')            operates on sequence Foo
nextval('myschema.foo')     operates on myschema.foo
nextval('"myschema".foo')   same as above
nextval('foo')              searches search path for foo

注意

当您将此类函数的参数写为未加修饰的文字字符串时,它将成为 regclass 类型(或相应的类型)的常量。由于这实际上只是一个 OID,因此它会跟踪原始标识的对象,即使后来重命名、模式重新分配等。这种“早期绑定”行为通常对于列默认值和视图中的对象引用是可取的。但有时您可能想要“延迟绑定”,即在运行时解析对象引用。要获得延迟绑定行为,请强制将常量存储为 text 常量而不是 regclass

nextval('foo'::text)      foo is looked up at runtime

to_regclass() 函数及其同类函数也可用于执行运行时查找。请参阅 表 9.76

另一个 regclass 的实际应用示例是查找 information_schema 视图中列出的表的 OID,这些视图不直接提供此类 OID。例如,您可能希望调用 pg_relation_size() 函数,该函数需要表的 OID。考虑到上述规则,正确的做法是:

SELECT table_schema, table_name,
       pg_relation_size((quote_ident(table_schema) || '.' ||
                         quote_ident(table_name))::regclass)
FROM information_schema.tables
WHERE ...

quote_ident() 函数将负责在需要时对标识符进行双重引用。看似更简单的

SELECT pg_relation_size(table_name)
FROM information_schema.tables
WHERE ...

不推荐的,因为它将对不在您的搜索路径中的表或名称需要引用的表失败。

大多数 OID 别名类型的附加属性是创建依赖关系。如果这些类型之一的常量出现在存储的表达式中(例如列默认表达式或视图),它将创建对被引用对象的依赖关系。例如,如果一个列具有默认表达式 nextval('my_seq'::regclass)PostgreSQL 会理解该默认表达式依赖于序列 my_seq,因此系统在删除默认表达式之前不会允许删除该序列。 nextval('my_seq'::text) 的替代方法不会创建依赖关系。(regrole 是此属性的一个例外。不允许在此类常量中使用该类型的常量。)

系统使用的另一种标识符类型是 xid,即事务(缩写为 xact)标识符。这是系统列 xminxmax 的数据类型。事务标识符是 32 位数量。在某些上下文中,使用 64 位变体 xid8。与 xid 值不同,xid8 值严格单调递增,并且在数据库集群的生命周期内不会被重用。有关更多详细信息,请参阅 第 67.1 节

系统使用的第三种标识符类型是 cid,即命令标识符。这是系统列 cmincmax 的数据类型。命令标识符也是 32 位数量。

系统使用的最后一种标识符类型是 tid,即元组标识符(行标识符)。这是系统列 ctid 的数据类型。元组 ID 是一个对(块编号,块内元组索引),它标识了行在表内的物理位置。

(系统列在 第 5.6 节 中有更详细的解释。)

提交更正

如果您在文档中看到任何不正确、与您在使用特定功能时的经验不符或需要进一步澄清的内容,请使用此表单报告文档问题。