13

我正在尝试编写一个函数来将 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 处的语法错误

它出什么问题了?

4

1 回答 1

16

您需要动态 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()with%L安全地转义文件名。如果没有它,将容易受到SQL 注入的影响。


另外,你有一个函数名不匹配:

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

于 2013-04-15T18:04:11.523 回答