8.19 对象标识符类型#
PostgreSQL内部将对象标识符 (OID) 用作各种系统表的唯一键。类型oid
表示一个对象标识符。此外,oid
还有几个别名类型,每个都命名为reg*
something*
。表 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 | any | 数字对象标识符 | 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.mytable
是regclass
(如果存在这样的表)的可接受输入。该值可能会输出为myschema.mytable
或仅输出为mytable
,具体取决于当前搜索路径。regproc
和regoper
别名类型仅接受唯一的(不重载的)输入名称,因此它们的使用受到限制;对于大多数用途,regprocedure
或regoperator
更为合适。对于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
还可以使用to_regclass()
函数及其同级函数来执行运行时查找。请参见表 9.72。
使用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)标识符。这是系统列xmin
和xmax
的数据类型。事务标识符为 32 位量。在某些上下文中,使用 64 位变体xid8
。与xid
值不同,xid8
值严格单调递增,并且在数据库集群的生命周期内不能重复使用。有关更多详细信息,请参见第 74.1 节。
系统使用的第三个标识符类型是cid
,或命令标识符。这是系统列cmin
和cmax
的数据类型。命令标识符也是 32 位量。
系统使用的最后一个标识符类型是tid
,或元组标识符(行标识符)。这是系统列ctid
的数据类型。元组 ID 是一个对(块号、块内的元组索引),用于标识表内行的物理位置。
(系统列在第 5.5 节中进一步说明。)