sql - COPY 动态文件名

标签 sql postgresql plpgsql dynamic-sql postgresql-copy

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

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

syntax error at $1

这是怎么回事?

最佳答案

COPY 不允许变量替换。只有核心 DML 命令 SELECTINSERTUPDATEDELETE 才有可能做到这一点。见:

您需要带有 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 注入(inject)的影响。

关于sql - COPY 动态文件名,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16019508/

相关文章:

sql - 检查 postgresql jsonb 列中是否存在 key

php - 如何使用 php 和 html 在我的博客上显示两个 sql 表的信息

SQL '08: How to count all sku' 在一个表中找不到另一个表

ruby-on-rails - rails yaml fixture - 指定 NULL 值

ruby-on-rails - Postgres pg_hba.conf

postgresql - PL/pgSQL "for loop"+ 选择基本示例 ("hello world")

sql - 插入冲突时回滚触发器

sql - 在 SQL Server 中向上舍入到最接近的 500 或 1000

ruby-on-rails - rails : An efficient method to match subdomains in the database?

postgresql - pl/pgsql 与针对 SQL 注入(inject)攻击的准备语句