【问题标题】:How to delimit PostgreSQL trigger procedure name?如何分隔 PostgreSQL 触发器过程名称?
【发布时间】:2015-12-26 00:49:16
【问题描述】:

例如,在 Perl 中,您可以像这样分隔变量:

${foo}_bar

我在 PostgreSQL 中有一个从 here 借来的触发器,我正在尝试使其通用以处理多个表。这是我的代码:

CREATE OR REPLACE FUNCTION update_parent_path() RETURNS TRIGGER AS $$
DECLARE
    PATH ltree;
BEGIN
    IF NEW.parent_id IS NULL THEN
        NEW.parent_path = 'root'::ltree;
    ELSEIF TG_OP = 'INSERT' OR OLD.parent_id IS NULL OR OLD.parent_id != NEW.parent_id THEN
        SELECT parent_path || TG_TABLE_NAME_id::text FROM TG_TABLE_NAME WHERE TG_TABLE_NAME_id = NEW.parent_id INTO PATH;
        IF PATH IS NULL THEN
            RAISE EXCEPTION 'Invalid parent_id %', NEW.parent_id;
        END IF;
        NEW.parent_path = PATH;
    END IF;
    RETURN NEW;
END;
$$ LANGUAGE plpgsql;

我使用此触发器的每个表都有一个主键,如 table_id(例如,skill_id、level_id 等)。我想做的是说WHERE skill_id = NEW.parent_id(对于它被调用的任何表),这就是我说WHERE TG_TABLE_NAME_id = NEW.parent_id的原因。我想知道如何将 TG_TABLE_NAME(触发过程)与 _id 分隔?

或者,有没有更好的方法来做到这一点?也许我只是把这一切都搞错了。

【问题讨论】:

    标签: postgresql triggers plpgsql dynamic-sql


    【解决方案1】:

    PLpgSQL 有一个基本规则 - plpgsql 变量不能用作嵌入式 SQL 中的表名或列名。但是有一个动态的SQL——下一个方式,如何执行SQL查询。动态 SQL 是在运行时从字符串(或字符串表达式)生成的查询。 PLpgSQL 变量可以在任何地方使用。所以你的查询片段:

    SELECT TG_TABLE_NAME_id::text FROM TG_TABLE_NAME ...
    

    在更多方面是错误的,并且永远不会起作用。但是动态查询(PLpgSQL 语句EXECUTE)应该可以工作

    EXECUTE format('SELECT %I FROM %I ...', 
                    TG_TABLE_NAME || '_id', TG_TABLE_NAME) INTO path;
    

    相关文档:http://www.postgresql.org/docs/9.4/static/plpgsql-statements.html#PLPGSQL-STATEMENTS-EXECUTING-DYN

    【讨论】:

      猜你喜欢
      • 2011-12-19
      • 1970-01-01
      • 2018-07-05
      • 1970-01-01
      • 2013-01-11
      • 1970-01-01
      • 2011-05-02
      • 2021-09-22
      • 2020-01-02
      相关资源
      最近更新 更多