我正在尝试编写一个函数来将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的语法错误
它出了什么问题?
答案 0 :(得分:10)
首先,您的功能名称不匹配:
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
来清理文件名。这也包括必要的封闭单引号。