postgresql 使用动态文件名复制

olmpazwi  于 2023-03-17  发布在  PostgreSQL
关注(0)|答案(1)|浏览(129)

我正在尝试写一个函数来加载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;

当我尝试创建这个函数时,我得到:
$1处语法错误
有什么不对吗?

pvcm50d1

pvcm50d11#

COPY不允许变量替换。只有使用核心DML命令SELECTINSERTUPDATEDELETE时才允许变量替换。请参阅:

  • 使用plpgsql变量设置n_distinct时出错

您需要使用EXECUTE动态SQL

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

format()需要PostgreSQL 9.1以上版本。
传递文件名,不使用额外的(转义的)单引号:

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

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

相关问题