【问题标题】:What does regclass mean in Postgresqlregclass 在 Postgresql 中是什么意思
【发布时间】:2012-10-28 15:40:54
【问题描述】:

我在 CREATE TABLE 语句中有以下行:

field1_id bigint DEFAULT nextval('table1_field1_id_seq'::regclass) NOT NULL,

上面的regclass是什么意思?加::regclass是绝对必要的吗?

注意:我看过 Postgresql 文档 link,它讲述了 regclass,但无法理解。

【问题讨论】:

    标签: postgresql create-table


    【解决方案1】:

    根据我对文档的理解,oid 按类型细分。 regclass 是表示关系的数据库对象(因此它们属于元数据表 pg_class)。

    它表示序列和DEFAULT 表达式之间的依赖关系(例如,如果在 INSERT 查询中没有提供显式值,则生成默认值的过程),因此如果在序列,查询不会通过,除非它被级联(通过写DROP SEQUENCE table1_field1_id_seq CASCADE)。

    【讨论】:

    • 那么,如果我级联DROP SEQUENCE,我使用此序列作为DEFAULT 的列(字段)将删除该默认值?
    • 我想是的。这是我从文档中了解到的,但我没有测试它。
    • 我认为强制转换为那种类型的 oid 会强制表达式和序列之间的依赖关系,因此从定义中删除它会删除 de 依赖关系,并让您在没有级联的情况下删除序列,但你应该再次测试以确认。
    • @Craig Ringer 说当类型不显式时,类型转换在查询执行时解析,然后推断关系 from 默认表达式 序列,但我认为引擎不会动态检查表达式是否与序列相关(关系序列另一个对象) ,并且拥有 regclass 会告诉引擎存在关系。
    【解决方案2】:

    不,当调用像nextval 这样接受regclass 参数的函数时,您不需要转换为regclass,因为从textregclass 存在隐式转换。在某些其他情况下,可能需要显式转换为 regclass

    说明:

    ::regclass 是一个演员表,如::integer

    regclass 是一种“魔法”数据类型;它实际上是oid 或“对象标识符”的别名。请参阅文档中的Object identifier types。转换为regclass 是说“这是一个关系的名称,请将其转换为该关系的 oid”的快捷方式。转换为regclass 知道search_path,这与直接查询pg_class 的关系的oid 不同,因此转换为regclass 并不完全等同于子查询pg_class

    表是关系。序列和视图也是如此。因此,您也可以通过强制转换为 regclass 来获得视图或序列的 oid。

    textregclass 定义了隐式转换,因此如果您省略显式转换并且调用接受regclass 的函数,转换会自动完成。所以你确实不需要nextval调用中需要它。

    还有其他地方可以。例如,您不能直接将textoid 进行比较;所以你可以这样做:

    regress=> select * from pg_class where oid = 'table1'::regclass;
    

    但不是这个:

    regress=> select * from pg_class where oid = 'table1';
    ERROR:  invalid input syntax for type oid: "table1"
    LINE 1: select * from pg_class where oid = 'table1';
    

    只是为了好玩,我尝试编写一个查询来执行转换为regclass 的等效操作。不要使用它,它主要是为了好玩,并试图演示实际发生的事情。除非你真的对 Pg 的工作原理感兴趣,否则你可以停止阅读这里。

    据我了解,'sequence_name'::regclass::oid 大致相当于以下查询:

    WITH sp(sp_ord, sp_schema) AS (
      SELECT 
        generate_series(1, array_length(current_schemas('t'),1)),
        unnest(current_schemas('t'))
    )
    SELECT c.oid
    FROM pg_class c INNER JOIN pg_namespace n ON (c.relnamespace = n.oid)
    INNER JOIN sp ON (n.nspname = sp.sp_schema)
    WHERE c.relname = 'sequence_name'
    ORDER BY sp.sp_ord
    LIMIT 1;
    

    除了它更短且更快。 current_schemas(...)的定义见System information functions

    换句话说:

    • 获取一个 ab 数组,列出我们可以访问的所有模式,并将每个条目与其在数组中的位置的序数配对
    • pg_class 中搜索与匹配名称的关系并将每个关系与其命名空间(架构)相关联
    • 按照架构在search_path 中出现的顺序对剩余关系列表进行排序
    • 并选择第一个匹配项

    【讨论】:

    • 所以我的查询行本质上会被解释为nextval(oid1),其中oid1table1_field1_id_seqoid。我说的对吗?
    • @saji89 正确,但请注意,转换为 oid 是在执行查询时解决的,而不是在定义表时解决的。这很重要,因为如果您要删除并重新创建序列,它将有一个新的 oid,但名称相同。转换为 oid 将找到新的 oid。
    • 所以即使我删除了一个序列,该序列的 oid 仍然存在于系统中?
    • @saji89 抱歉,应该解释一下。虽然regclass 内部是一个oid,但它仍然显示psql 输出中的表名等。如果要显示实际的oid,可以转换为oid,这就是'sequence_name'::regclass::oid 所做的;转换为regclass,然后将其转换为oid,因此不再格式化为显示。正如我所说,regclass 是一种神奇的类型。
    • 作为奖励,您还可以将 from 转换为数字 oid,即 select 1234::regclass,如果您想知道特定的 pg_toast_ 是什么表,这将很有用表关联。
    猜你喜欢
    • 2019-12-10
    • 2015-09-25
    • 1970-01-01
    • 2011-08-12
    • 2017-06-11
    • 2018-03-05
    • 2023-03-27
    • 2018-08-19
    • 2016-08-17
    相关资源
    最近更新 更多