Ben*_*ack 8 sql postgresql dynamic-sql plpgsql 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 VOLATILE
COST 100;
ALTER FUNCTION public.filltmaxa(character varying)
OWNER TO postgres;
Run Code Online (Sandbox Code Playgroud)
当我尝试创建此功能时,我得到了
$ 1的语法错误
它出什么问题了?
Erw*_*ter 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;
Run Code Online (Sandbox Code Playgroud)
format()需要PostgreSQL 9.1+.
这样,我们可以提供文件名而无需额外的一组(转义)单引号.呼叫:
SELECT loaddata('/absolute/path/to/my/file.csv')
Run Code Online (Sandbox Code Playgroud)
这非常容易受到SQL注入的影响.为了防范它,我使用format()它%L来清理文件名.这也包括必要的封闭单引号.