【问题标题】:COPY with dynamic file name使用动态文件名复制
【发布时间】:2013-04-07 19:44:59
【问题描述】:

我正在尝试编写一个函数来将 csv 数据加载到表中。我希望输入参数是文件的路径。

CREATE OR REPLACE FUNCTION public.loaddata(filepathname varchar)
  RETURNS void AS
$BODY$
BEGIN
COPY climatedata(
    climatestationid, 
    date,
    prcp,
    prcpqflag,
    prcpmflag,
    prcpsflag,
    tmax,
    tmaxqflag,
    tmaxmflag,
    tmaxsflag,
    tmin,
    tminqflag,
    tminmflag,
    tminsflag)
  FROM $1
  WITH csv header;
END;
$BODY$
  LANGUAGE plpgsql VOLATILE
  COST 100;
ALTER FUNCTION public.filltmaxa(character varying)
  OWNER TO postgres;

当我尝试创建这个函数时,我得到了

$1 的语法错误

这有什么问题?

【问题讨论】:

  • 什么版本的 Postgres?
  • 你知道postgresql的copy命令内置了CSV解析吧?

标签: sql postgresql plpgsql dynamic-sql postgresql-copy


【解决方案1】:

您需要动态 SQL:

CREATE OR REPLACE FUNCTION loaddata(filepathname text)
  RETURNS void AS
$func$
BEGIN
   EXECUTE format ('
   COPY climatedata(
         climatestationid
       , date
         ... -- more columns 
       , tminsflag)
   FROM %L (FORMAT CSV, HEADER)'  -- current syntax
           -- WITH CSV HEADER'    -- tolerated legacy syntax
   , $1);  -- pass function parameter filepathname to format() 
END
$func$ LANGUAGE plpgsql;

format() 需要 PostgreSQL 9.1+。
传递文件名而不需要额外的(转义)单引号:

SELECT loaddata('/absolute/path/to/my/file.csv')

format() 和 %L 安全地转义文件名。如果没有它,将很容易受到 SQL 注入 的影响。


除了,你有一个函数名不匹配:

CREATE OR REPLACE FUNCTION public.loaddata(filepathname varchar)
...
ALTER FUNCTION public.filltmaxa(character varying)

【讨论】:

  • 效果很好!我正在运行 PostgreSQL 9.2,因此 format() 函数可用。我相信你可以告诉我,我对 Postgres 还是很陌生,并且在学习过程中学到了很多东西。我非常感谢您花时间解决这个问题。谢谢!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-03-03
  • 2020-05-29
  • 2017-02-17
  • 1970-01-01
相关资源
最近更新 更多