我正在创建一个通用的自动化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标志?
执行日志。
函数的主体是一个引用的文字。元引号,但都是一样的。的手动。
变量插值将不会在引号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
更聪明一些,只在有区别的地方加上双引号。这避免了函数定义中的噪音。参见: