13

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 の構文エラー

どうしたの?

4

1 に答える 1

16

動的 SQLが必要です:

CREATE OR REPLACE FUNCTION loaddata(filepathname text)
  RETURNS void AS
$func$
BEGIN
   EXECUTE format ('
   COPY climatedata(
         climatestationid
       , date
         ... -- more columns 
       , tminsflag)
   FROM %L (FORMAT CSV, HEADER)'  -- current syntax
           -- WITH CSV HEADER'    -- tolerated legacy syntax
   , $1);  -- pass function parameter filepathname to format() 
END
$func$ LANGUAGE plpgsql;

format()PostgreSQL 9.1+ が必要です。
(エスケープされた) 一重引用符の余分なセットなしでファイル名を渡します。

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

format()with%Lはファイル名を安全にエスケープします。これがないと、 SQL インジェクションの影響を受けやすくなります。


さておき、関数名の不一致があります:

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

于 2013-04-15T18:04:11.523 に答える