КОПИЯ с динамическим именем файла
Я пытаюсь написать функцию для загрузки данных 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
санировать имя файла. Это также заботится о необходимых одинарных кавычках.