1

有什么方法可以让我从 postgres 表创建一个 json 文件

正如我使用

 copy to

但是当我在要调度的 postgres 函数中创建时,它无法将参数捕获为文件名

copy  v_originaltext to '/var/lib/postgresql/sftp/smrptesting1.json';
4

1 回答 1

1

您可能会通过几种不同的方式完成您想要做的事情,尽管这两种方式都需要您将pg_write_server_files和/或pg_execute_server_program的组合授予执行角色/用户。

方法 1:使用动态 SQL(使用pg_write_server_files

在这里,您将推断使用 COPY 命令的初始计划,更改

COPY v_originaltext to '/var/lib/postgresql/sftp/smrptesting1.json';

改为在您要执行的功能块中声明一个 SQL 字符串变量 (v_sql),即类似于

CREATE OR REPLACE FUNCTION json_putter(_parameters TEXT)
RETURNS VOID
LANGUAGE plpgsql
AS $function$
DECLARE
    v_sql TEXT DEFAULT NULL;
    v_originaltext JSONB;
    v_filename TEXT;
BEGIN
    -- < ... code to populate v_originaltext here ... >
    v_filename := '/var/lib/postgresql/sftp/' || _parameters || '.json';
    v_sql := 'COPY $1 TO $2';
    
    EXECUTE v_sql USING v_originaltext, v_filename;

-- 或者,或者,使用文字单引号:

    v_sql := 'COPY (SELECT v_originaltext) TO ' || CHR(39) || v_filename || CHR(39);
    EXECUTE v_sql;
END
$function$

这将构建 COPY 语句,就像您从客户端手动运行一样。

方法 2:使用服务器端 psql 命令(使用pg_execute_server_program

您可以直接从 psql 命令输出 json,并将标准输出重定向到您从参数生成的文件描述符。

为了实现这一点,为简单起见,您可能需要创建两个原子函数:

  • 一个充当包装器以生成 v_originaltext [例如 fx_originaltext(_parameters => text)] 的值
  • 一个将使用 COPY ... FROM PROGRAM 实用程序通过 psql 运行通用命令并使用临时表或类似的标准输出:

--

CREATE OR REPLACE FUNCTION psql_runner(_function TEXT, _parameters TEXT)

RETURNS VOID
LANGUAGE plpgsql
AS $function$
DECLARE
    v_filename TEXT;
BEGIN
    v_filename := '/var/lib/postgresql/sftp/' || _parameters || '.json';
    CREATE TEMP TABLE _out ( stdout text );
    COPY _out FROM PROGRAM ('psql -tq -c "SELECT ' || _function || '(_parameters :=' || quote_literal(_parameters) || ') " > ' || v_filename);
END
$function$

值得注意的是,第二种方法需要更大范围的权限,并且根据您使用的 postgres 版本,可能需要像第一种方法一样将 COPY 作为动态 SQL 执行。

于 2021-09-12T15:27:36.933 回答