在postgres中的存储函数中运行外部sql脚本的最佳方法是什么?
this question 解释了如何从在psql中运行的脚本中调用外部脚本,但是我需要围绕调用包装逻辑,因此必须在存储的函数中完成。
EG。
/tmp/scripts$ cat create_db.sql
CREATE TABLE dbVersion (
versionNum VARCHAR(10) NOT NULL,
applied TIMESTAMP
PRIMARY KEY (versionNum)
);
/tmp/scripts$ cat upgrade_db.sql
CREATE OR REPLACE FUNCTION UpgradeDB (dbName VARCHAR)
RETURN void AS $$
DECLARE
BEGIN
IF EXISTS (SELECT datname from pg_database WHERE datname = dbName) THEN
--Do upgrade code
ELSE
--Install Fresh
\i /tmp/scripts/create_db.sql;
END IF;
END;
$$ language plpgsql;
SELECT UpgradeDB('foo');
这(不出所料)给出了错误
错误:“\”
处或附近的语法错误我可以使用plsh来调用,这是(未经测试的)......
CREATE FUNCTION callSQLScript(scriptPath text)
RETURNS void AS $$
#!/bin/sh
plsql -f scriptPath
$$ LANGUAGE plsh;
SELECT callSQLScript('/tmp/scripts/create_db.sql');
但这看起来非常糟糕。
只是用于plsh的RTFM并且它声明'shell脚本可以执行任何您想要的操作,但是您无法访问数据库'因此这可能无法正常工作。
注意,我无法复制/粘贴这些代码段,因此可能存在拼写错误。
答案 0 :(得分:1)
我认为你的plsh脚本可以解决psql
错误。它不访问数据库。它正在呼吁另一个程序来做到这一点。作为一个重要的警告,这意味着脚本将在单独的事务中运行,甚至是单独的会话,这可能不是您想要的。
如果我这样做,我会创建一个表:
CREATE TABLE sql_jobs (
job_id serial not null unique, -- machine key
job_name text primary key,
sql_to_execute text not null
);
然后你可以选择变量并执行。当然要小心安全......
答案 1 :(得分:1)
我不工作的原因是因为\ i是PSQL命令而不是Postgresql命令,因此您不能在函数内使用\ i,因为该函数由服务器评估。
您的解决方案:
答案 2 :(得分:0)
您可以使用命令:
psql -d myDataBase -a -f /tmp/scripts/create_db.sql;
在你的Else区块内
答案 3 :(得分:0)
我发现我在Fedora上安装的rpm版本的Postgres没有perl或sh语言扩展(如plperlu),因此选项已经用完了。但是,安全执行此操作的关键是带有TO PROGRAM选项的COPY函数将执行命令并将stdin传递给它。
2)将shell脚本名称更改为单个单词。 IOW,没有尾随" .sh"将权限设置为:chmod u + x
3)查看您的路径(echo $ PATH),然后选择一个系统目录以将此脚本文件复制到。
4)您的脚本现在将成为"命令"像其他任何一样。您可以使用带有TO PROGRAM(命令名称)功能的COPY功能执行它。
参考:
将脚本转换为命令 https://docs.fedoraproject.org/ro/Fedora_Draft_Documentation/0.1/html/RPM_Guide/ch14s04s04.html