为Postgres函数体在psql中访问\ set变量

问题描述 投票:3回答:1

我正在创建一个通用的自动化Postgres脚本,其中包括DDL,DML,函数和触发器。在大多数操作中,我已经在psql中使用\set参数化了架构名称,但是在function body的情况下,它不起作用。我经过艰苦的搜索,发现了关于[[dynamic SQL的信息,但这似乎也不起作用。

script.sql

\set schema_name myschema CREATE SCHEMA IF NOT EXISTS :schema_name; CREATE table :schema_name.employee ( id serial, name text , dob timestamp, leaves_count int, CONSTRAINT employee_pk PRIMARY KEY (id) ); SELECT create_distributed_table(concat(:'schema_name', '.employee'), 'id'); CREATE table :schema_name.leaves ( id serial, reason text, ts timestamp, employee_id int, CONSTRAINT leaves_pk PRIMARY KEY (id) ); -- STORED PROCEDURE CREATE OR REPLACE FUNCTION :schema_name.deduct_leave_count() RETURNS TRIGGER AS $BODY$ BEGIN UPDATE :schema_name.employee s SET leaves_count = s.leaves_count - 1 WHERE s.id = NEW.employee_id; RETURN NEW; END $BODY$ LANGUAGE plpgsql; -- TRIGGER CREATE TRIGGER trigger_deduct_leave_count BEFORE INSERT ON :schema_name.leaves FOR EACH ROW EXECUTE PROCEDURE :schema_name.deduct_leave_count();
psql -p 5432 -f script.sql

我在函数中出错,因为它无法全局读取变量集。有什么方法可以访问函数内部的psql的全局变量或-v标志?

执行日志:

Execution Logs
postgresql plpgsql psql stored-functions citus
1个回答
2
投票
函数的主体是带引号的文字。用美元报价,但都一样。 The manual:

在引用的SQL中不会执行变量插值文字和标识符。

有多种解决方法。由于您正在psql中运行脚本,因此建议您让Postgres用format()为您串联,然后用format()执行:

\gexec

详细说明:

    -- TRIGGER FUNCTION SELECT format($$ CREATE OR REPLACE FUNCTION %1$I.deduct_leave_count() RETURNS trigger LANGUAGE plpgsql AS $func$ BEGIN UPDATE %1$I.employee s SET leaves_count = s.leaves_count - 1 WHERE s.id = NEW.employee_id; RETURN NEW; END $func$ $$, :'schema_name')\gexec
  • side 1 :(触发)功能是

    not一个过程。相关:

  • 除2:由于架构名称是标识符,因此您可能需要使用双引号。 psql支持:

    How to get result set from PostgreSQL stored procedure?

    保留给定的字符串(包括大写字母,并防止SQL注入。

    CREATE table :"schema_name".leaves format()一起使用会更聪明,并且仅在双引号引起不同的地方添加双引号。这避免了函数定义中的干扰。参见:

      %I
  • Are PostgreSQL column names case-sensitive?
  • © www.soinside.com 2019 - 2024. All rights reserved.