ファイルからPostgreSQLデータベースにXMLを読み込むSQL


12

XMLファイルを読み込んでPostgreSQLのXML値にするには、どうすればSQLを記述できますか?

PostgreSQLには、テキスト文字列をその型に解析する機能を備えたネイティブXMLデータ型がありXMLPARSEます。また、ファイルシステムからデータを読み取る方法もあります。特にCOPY声明。

しかし、ネイティブのPostgreSQL SQLステートメントを記述して、ファイルシステムエントリからコンテンツを読み取り、それを使用してXML値を設定する方法は見当たりません。これどうやってするの?

回答:


10

前の質問へのこの回答と同様で、制限がpg_read_file()必要ない場合(要するにpg_read_file、データベースディレクトリ外のファイルを読み取れず、現在のセッションの文字エンコーディングでテキストを読み取ります)。

この関数はどのパスでも機能しますが、スーパーユーザーとして作成する必要があります。

create or replace function stack.bytea_import(p_path text, p_result out bytea) 
                   language plpgsql as $$
declare
  l_oid oid;
begin
  select lo_import(p_path) into l_oid;
  select lo_get(l_oid) INTO p_result;
  perform lo_unlink(l_oid);
end;$$;

lo_get 9.4で導入されたため、古いバージョンでは次が必要になります。

create or replace function stack.bytea_import(p_path text, p_result out bytea) 
                   language plpgsql as $$
declare
  l_oid oid;
  r record;
begin
  p_result := '';
  select lo_import(p_path) into l_oid;
  for r in ( select data 
             from pg_largeobject 
             where loid = l_oid 
             order by pageno ) loop
    p_result = p_result || r.data;
  end loop;
  perform lo_unlink(l_oid);
end;$$;

その後:

select convert_from(stack.bytea_import('/tmp/test.xml'), 'utf8')::xml;

1
+1、ファイル読み取り機能には制限があることを指摘してくれてありがとう。
bignose

1
回避する素敵なトリック+1 pg_read_file()。同じことは、一時テーブルでも実現できます。またCOPY、1行の1列のみを設定します。
アーウィンブランドステッター

4

pg_read_binary_fileこの関数はこれを行うことができます。

制限があります:PostgreSQL 9.1以降の新機能。データベースのスーパーユーザーが所有するセッションである必要があります。データベースディレクトリ以下のファイルを読み取る必要があります。これらは私のユースケースで受け入れられます。

そのため、以下はXMLファイルからネイティブ値を作成するために機能します。

-- PostgreSQL 9.1 or later.
SELECT
    XMLPARSE(DOCUMENT convert_from(
        pg_read_binary_file('foo.xml'), 'UTF8'));

PostgreSQL 8.3 – 9.0では、pg_read_file関数を使用できますが、ファイル固有のエンコードを指定できないという追加の制限があります(現在のセッションのエンコードでテキストとしてファイルを読み取ります)。

-- PostgreSQL earlier than 9.1.
SELECT
    XMLPARSE(DOCUMENT pg_read_file('foo.xml'));

3

SOに関する最近の回答で、あなたが求めているものの完全な実装を投稿しました。

主な機能は、xpath()関数pg_read_file()、配列処理、plpgsql関数です。


この場合に必要なものとはかなり異なる(そしてより重い)。しかし、良い方向性のために+1、ありがとう。
bignose

そうではありませんことをヘビー級、私の例では、構文バリアントを実証するための冗長な要素を持つだけで非常に完了です。
アーウィンブランドステッター
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.