postgresql从函数内部运行外部sql脚本

时间:2012-09-11 06:24:14

标签: postgresql plpgsql

在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脚本可以执行任何您想要的操作,但是您无法访问数据库'因此这可能无法正常工作。

注意,我无法复制/粘贴这些代码段,因此可能存在拼写错误。

4 个答案:

答案 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,因为该函数由服务器评估。

您的解决方案:

  1. 在函数
  2. 中编写Sql
  3. 在表中编写sql并使用EVAL函数
  4. 您建议的plsql(但您应该使用psql)。

答案 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传递给它。

  1. 创建bash shell脚本以运行预期的外部函数。确保脚本中的第一行格式为"#!/ bin / sh"或"#!/ bin / bash" (你的偏好在这里,这是将要使用的shell);
  2. 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