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

时间:2016-05-11 00:15:38

标签: postgresql function plpgsql

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

以下是用于参考目的的表创建和数据插入:

    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 $1;
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,如果我执行脚本,我希望返回“Shmoe_Shmoe.csv”文件:

select from some_schema.some_function(2)

问题是每当我得到它来读取“v_filename”变量时它就不会评估它并从函数的变量中返回值。最初,我认为这是一个引用问题(它可能仍然是)。在搞乱引用之后,我已经得到了以下错误:

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

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

1 个答案:

答案 0 :(得分:0)

这或多或少说明了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 $1;
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\']