1

从 postgres 的存储函数中运行外部 sql 脚本的最佳方法是什么?

这个问题 解释了如何从在 psql 中运行的脚本中调用外部脚本,但是我需要在调用周围包装逻辑,所以它必须在存储的函数中完成。

例如。

/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

4 回答 4

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
);

然后你可以选择一个变量并执行。当然要注意安全......

于 2012-09-11T06:40:55.297 回答
1

\i 不起作用的原因是因为 \i 是 PSQL 命令而不是 Postgresql 命令,因此您不能在函数中使用 \i,因为该函数由服务器评估。

您的解决方案:

  1. 在函数中写Sql
  2. 在表中写sql并使用EVAL函数
  3. 您建议的 plsql(但您应该使用 psql)。
于 2013-02-13T16:37:01.270 回答
0

我发现我在 Fedora 上安装的 rpm 版本的 Postgres 没有 perl 或 sh 语言扩展(如 plperlu),因此该选项已失效。但是,安全地执行此操作的关键是带有 TO PROGRAM 选项的 COPY 函数将执行命令并将 stdin 传递给它。

  1. 创建 bash shell 脚本以运行预期的外部函数。确保脚本中的第一行格式为“#!/bin/sh”或“#!/bin/bash”(您在此处的偏好,这是将使用的 shell);

2)将shell脚本名称更改为单个单词。IOW,没有尾随“.sh” 将权限设置为:chmod u+x

3) 查看您的路径 (echo $PATH),然后选择一个系统目录来将此脚本文件复制到其中。

4)您的脚本现在将像任何其他脚本一样成为“命令”。您可以使用带有 TO PROGRAM(commandnamehere) 函数的 COPY 函数来执行它。

参考:

将脚本变成命令 https://docs.fedoraproject.org/ro/Fedora_Draft_Documentation/0.1/html/RPM_Guide/ch14s04s04.html

于 2016-02-12T15:45:03.537 回答
-1

您可以使用命令:

psql -d myDataBase -a -f /tmp/scripts/create_db.sql;

在你的 Else 块内

于 2012-11-26T08:12:40.980 回答