КОПИЯ с динамическим именем файла

Я пытаюсь написать функцию для загрузки данных 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 $

Что с этим не так?

1 ответ

Решение

Во-первых, у вас есть несоответствие имени функции:

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

Но это дополнительная проблема.

Ответ

Вам нужен динамический SQL:

CREATE OR REPLACE FUNCTION loaddata(filepathname text)
  RETURNS void AS
$func$
BEGIN

EXECUTE format ('
COPY climatedata(
      climatestationid
     ,date
     ,prcp
     ,prcpqflag
     ,prcpmflag
     ,prcpsflag
     ,tmax
     ,tmaxqflag
     ,tmaxmflag
     ,tmaxsflag
     ,tmin
     ,tminqflag
     ,tminmflag
     ,tminsflag)
FROM %L
(FORMAT CSV, HEADER)', $1);  -- current syntax
--- WITH CSV HEADER', $1);   -- tolerated legacy syntax

END
$func$ LANGUAGE plpgsql;

format()требуется PostgreSQL 9.1+.
Таким образом, мы можем предоставить имя файла без дополнительного набора (экранированных) одинарных кавычек. Вызов:

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

Это очень восприимчиво к инъекции SQL. Для защиты от этого я использую format() с %L санировать имя файла. Это также заботится о необходимых одинарных кавычках.

Другие вопросы по тегам