Postgres 函数 - 使用 table 映射更新值

Postgres function - using table mapping to update value

我有一个一般性问题。我有一个创建文件的功能。但是,目前在该函数中,我正在根据参数输入对文件名模式进行硬编码。现在我已经到了需要多个文件名模式的地步。我设计了一种使用另一个 table 作为文件名映射的方法,如果用户输入该文件名模式 ID,该函数可以简单地调用该文件名映射。这是我的示例,以帮助更好地说明我的观点:

下面是table的创建和数据插入,供参考:

    create table some_schema.file_mapper(
        mapper_id integer not null,
        file_name_template varchar);

    insert into some_schema.file_mapper (mapper_id, file_name_template)
    values
    (1, '||v_first_name||''_''||v_last_name||')
    (2, '||v_last_name||''_''||v_first_name||')
    (3, '||v_last_name||''_''||v_last_name||');

现在函数本身

create or replace function some_schema.some_function(integer)

returns varchar as

$body$

Declare

v_filename_config_id alias for ;
v_filename           varchar;
v_first_name         varchar;
v_last_name          varchar;
cmd                  text;

Begin

v_first_name :='Joe';
v_last_name  :='Shmoe';

cmd := 'select file_name_template
        from some_schema.file_mapper
        where mapper_id = '||v_filename_config||'';
execute cmd into v_filename;

raise notice 'checking "%"',v_filename;

return 'done';
end;
$body$
LANGUAGE plpgsql;

现在我有了这个。我希望能够混合和匹配文件名模式。因此,例如我想使用 mapper_id 3,如果我执行脚本,我希望得到 returned 的 "Shmoe_Shmoe.csv" 文件:

select from some_schema.some_function(2)

问题是,每当我让它读取 "v_filename" 变量时,它不会计算 return 函数变量的值。最初,我认为这是一个引用问题(现在可能仍然是)。在弄乱了引用之后,我得到了以下错误:

ERROR:  syntax error at or near "_"
LINE 4: ...s/dir/someplace/||v_last_name||'_'||v_firs...
                                                         ^
QUERY:  copy(
             select * 
             from some_schema.some_table)
             to '/dir/someplace/||v_last_name||'_'||v_first_name||.csv/;
             DELIMITER,
             csv HEADER;
CONTEXT:  PL/pgSQL function some_schema.some_function(integer) line 27 at EXECUTE statement

如您所知,这几乎是在告诉我这是一个引用问题。有没有办法让函数正确评估变量和 return 正确的文件名?如果我不清楚并需要详细说明,请告诉我。

这或多或少说明了format()的用法。 (略微减少了原始问题):

CREATE TABLE file_mapper
        ( mapper_id INTEGER NOT NULL PRIMARY KEY
        ,  file_name_template TEXT
        );
INSERT INTO file_mapper(mapper_id, file_name_template) VALUES (1,'one'), (2, 'two');


CREATE OR REPLACE FUNCTION dump_the_shit(INTEGER)
RETURNS VARCHAR AS
$body$

DECLARE

v_filename_config_id alias for ;
v_filename           VARCHAR;
name_cmd                  TEXT;
copy_cmd                  TEXT;

BEGIN

name_cmd := format( e'select file_name_template
        from file_mapper
        where mapper_id = %L;', v_filename_config_id );

EXECUTE name_cmd into v_filename;
RAISE NOTICE 'V_filename := %', v_filename;

copy_cmd := format( e'copy(
             select * 
             from %I)
             to \'/tmp/%s.csv\'
             csv HEADER;' , 'file_mapper' , v_filename);

EXECUTE copy_cmd;

RETURN copy_cmd;
END;
$body$
LANGUAGE plpgsql;

SELECT dump_the_shit(1);

format function description

总结:

  • 使用 %I 作为标识符(表名和列名)[FROM %I]
  • 将 %L 用于查询常量等文字 [WHERE the_date = %L]
  • 对普通字符串使用 %s [to \'/tmp/%s.csv\']