3

ここでpostgresをいじっているかもしれませんが、基本的に、私がやりたいことは、文字列変数を取り、それをpsqlのみを使用してsqlコマンド(この場合はCOPY)に渡すことです。

これが私が思いついたものです。他の状況で mydb_functions を使用できるようにするため、コマンドは 2 つのファイルに分割されています。

ファイル 1: mydb_functions--1.0.sql (share/extension で、mydb_functions.control を使用して、マニュアルに記載されているようにセットアップも行います。ファイル名を指定すると、完全なファイルパスが返されます。これは、以下の add_data.sql で COPY ステートメントを作成するためだけに行われます。 、きれいに。

CREATE OR REPLACE FUNCTION fpn(filename text) RETURNS TEXT as '
  DECLARE 
    mypath text := ''/path/to/my/directory/'';
  BEGIN
    RETURN mypath || filename;
  END
' LANGUAGE plpgsql;

ファイル 2: add_data.sql 。これは、コマンド ラインで psql を使用して既存の postgres テーブルにデータをコピーするためだけに存在します。注: CREATE EXTENSION コマンドのため、スーパーユーザー権限で psql を実行する必要があります。

CREATE EXTENSION IF NOT EXISTS mydb_functions;
-- haven't figured out how to create a function without arguments yet.
CREATE OR REPLACE FUNCTION test (dummyvar text) RETURNS text as '     
  DECLARE 
    filepath RECORD;
  BEGIN 
    SELECT * INTO filepath from fpn(''mydatafile.data'');
    COPY tablename (columnname) FROM filepath;
  END
' LANGUAGE plpgsql;

私が立ち往生している部分は、ファイルパスレコードからテキストを抽出して COPY コマンドで使用する方法です。これを達成するためのより簡単な方法に関するヒントも大歓迎です。変数を格納するためのテーブルを作成することは、これよりもはるかに簡単だと思います。しかし、私は最後のステップを完了したいと思います。

4

1 に答える 1

0

問題がCOPY動的ターゲット パスで実行されている場合は、 ted SQL クエリEXECUTEを実行するために使用します。format

CREATE OR REPLACE FUNCTION test () RETURNS text as $$ 
  DECLARE 
    filepath RECORD;
  BEGIN 
    SELECT * INTO filepath from fpn('mydatafile.data');
    EXECUTE format('COPY tablename (columnname) FROM %L', filepath);
  END
$$ LANGUAGE plpgsql;

ほら、これは失敗します:

DO
$$
DECLARE
    somevar text;
BEGIN
    somevar := '/tmp/somepath.csv';
    COPY tablename(columnname) FROM somevar;
END;
$$;

しかし、これは機能します:

DO
$$
DECLARE
    somevar text;
BEGIN
    somevar := '/tmp/somepath.csv';
    EXECUTE format('COPY tablename(columnname) FROM %L', somevar);
END;
$$;

見る:

format()%L指定子はリテラルを自動引用します。%I識別子についても同じことを行います。


私が最初に考えたようにpsql、外部からデータを取得することについて話している場合、psql変数と変数補間が役立つ場合があります。

$ psql -v filepath=/path/to/my/directory/mydatafile.data regress
regress=> SELECT :'filepath';
               ?column?                
---------------------------------------
 /path/to/my/directory/mydatafile.data
(1 row)

コロンは引用符で囲まれておらず、次に変数名が引用符で囲まれていることに注意してください。奇妙な構文、私は知っています。これはでのみ機能しpsqlます。(たとえば)PgAdmin-IIIでは機能しません。

別の方法として、ヒアドキュメント (UNIX に似たシェル固有のもので、Windows では機能cmd.exeしません) を使用して、引用されたテキストの補間を行うことができます。

$ FILEPATH=/path/to/my/directory/mydatafile.data
$ psql regress <<__END__
SELECT '$FILEPATH';
__END__

               ?column?                
---------------------------------------
 /path/to/my/directory/mydatafile.data
(1 row)

これらはどちらも、変数をシェル レベルから に挿入する方法を示していますpsql。そこから、それを関数で使用するだけです。このように、次のように言います-v filename=myfilename.csv:

CREATE OR REPLACE FUNCTION test() RETURNS text as $$
  DECLARE 
    filepath RECORD;
  BEGIN 
    SELECT * INTO filepath from fpn(:'filename');
    COPY tablename (columnname) FROM filepath;
  END
$$ LANGUAGE plpgsql;

またはこれだけで-v filepath=/full/path/to/myfilename.csv

$ psql -v filepath=/path/to/my/directory/mydatafile.data regress
regress=> COPY tablename (columnname) FROM :'filepath';
于 2012-11-06T10:56:12.690 に答える