【问题标题】:How do you pass a parameter to a pgsql command within a function?如何将参数传递给函数中的 pgsql 命令?
【发布时间】:2012-02-11 03:28:10
【问题描述】:

我经常在 postgresql 中使用复制功能,我想我会创建一个函数来使用它。 所以假设我有下表

create table users
(
   userid serial primary key,
   prefix varchar(10) not null,
   firstname varchar(255) not null,
   lastname varchar(255) not null,
   email varchar(500) not null,
   password varchar(255) not null,
   created timestamp not null,
   modified timestamp not null
);

还有下面的函数

create function getUsersCSV(  )
RETURNS void AS
$BODY$
  BEGIN
    COPY (select * from users) 
    TO 'c:\temp\users.csv' 
    WITH HEADER 
    CSV QUOTE '"' DELIMITER ',';
  END
$BODY$
LANGUAGE PLPGSQL;

函数有效,但如果我将函数更改为

create function getUsersCSV( filepath varchar )
RETURNS void AS
$BODY$
  BEGIN
    COPY (select * from users) 
    TO filepath 
    WITH HEADER 
    CSV QUOTE '"' DELIMITER ',';
  END
$BODY$
LANGUAGE PLPGSQL;

它会引发以下语法错误 错误:“文件路径”处或附近的语法错误 SQL 状态:42601

是否有参数化复制命令的目标值?

【问题讨论】:

标签: function postgresql plpgsql


【解决方案1】:

您可以使用execute

create function get_users_csv(filepath text) returns void as $$
declare
    cp_cmd text;
begin
    cp_cmd := 'copy (select * from users) to '
           || quote_literal(filepath)
           || ' with header csv quote ''"'' delimiter '',''';
    execute cp_cmd;
end;
$$ language plpgsql;

不要忘记在您的filepath 上使用quote_literal,以防万一。如果您不喜欢所有双引号,也可以使用美元引号:

create function get_users_csv(filepath text) returns void as $$
declare
    cp_cmd text;
begin
    cp_cmd := $q$copy (select * from users) to $q$
           || quote_literal(filepath)
           || $q$ with header csv quote '"' delimiter ','$q$;
    execute cp_cmd;
end;
$$ language plpgsql;

但我发现美元报价对于文本块以外的任何内容都相当丑陋。

【讨论】:

  • +1 用于美元引用,如果您需要在字符串中包含单引号,这是一种祝福。 (因此,查询字符串的第一部分不需要。)将 (select * from users) 简化为 users
  • 在这种情况下,您必须是超级用户,因此您必须使用可能的安全定义器功能。有必要检查路径,因为如果不进行精确检查,有人可能会破坏您的数据
猜你喜欢
  • 2012-08-13
  • 2013-12-23
  • 1970-01-01
  • 2015-04-17
  • 2014-07-22
  • 2013-03-18
  • 1970-01-01
  • 2021-05-20
  • 1970-01-01
相关资源
最近更新 更多