在psql中访问Postgres函数体的set变量。

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

我正在创建一个通用的自动化Postgres脚本,其中包括DDL、DML、函数和触发器。我已经实现了对模式名称的参数化,用了 \set 在psql中的大部分操作中,但在以下情况下却无法使用。职能机构. 我找了很久,找到了关于... ... 动态SQL 但这似乎也不行。

脚本.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标志?有什么方法可以在函数中访问全局变量或psql的-v标志?

执行日志。

Execution Logs

postgresql plpgsql psql stored-functions citus
1个回答
2
投票

函数的主体是一个引用的文字。元引号,但都是一样的。的手动。

变量插值将不会在引号SQL字面和标识符中进行。

有多种方法可以解决这个问题。由于你是在psql中运行脚本,我建议你让Postgres为你做连接,用 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

详解。

旁白1:一个(触发器)函数就是 一个程序。相关内容。

旁白2:由于模式名是一个标识符,所以你可能想使用双引号,psql支持这一点。

CREATE table :"schema_name".leaves

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

format()%I 更聪明一些,只在有区别的地方加上双引号。这避免了函数定义中的噪音。参见:

© www.soinside.com 2019 - 2024. All rights reserved.