sql >> データベース >  >> RDS >> PostgreSQL

Javaを使用してPostgreSQLデータベースの既存のデータベースから新しいXMLファイルを作成するにはどうすればよいですか?

    すべてを実行する実装が機能しています。 追加のライブラリなしでPostgreSQL内。

    補助解析機能

    CREATE OR REPLACE FUNCTION f_xml_extract_val(text, xml)
      RETURNS text AS
    $func$
    SELECT CASE
            WHEN $1 ~ '@[[:alnum:]_]+$' THEN
               (xpath($1, $2))[1]
            WHEN $1 ~* '/text()$' THEN
               (xpath($1, $2))[1]
            WHEN $1 LIKE '%/' THEN
               (xpath($1 || 'text()', $2))[1]
            ELSE
               (xpath($1 || '/text()', $2))[1]
           END;
    $func$  LANGUAGE sql IMMUTABLE;
    

    複数のを処理する

    上記の実装は複数の属性を処理しません 1つのxpathで。これは、f_xml_extract_val()のオーバーロードされたバージョンです。 そのために。 3番目のパラメーターを使用すると、oneを選択できます。 (最初の)、all またはdist (個別の)値。複数の値がカンマ区切りの文字列に集約されます。

    CREATE OR REPLACE FUNCTION f_xml_extract_val(_path text, _node xml, _mode text)
      RETURNS text AS
    $func$
    DECLARE
       _xpath text := CASE
                       WHEN $1 ~~ '%/'              THEN $1 || 'text()'
                       WHEN lower($1) ~~ '%/text()' THEN $1
                       WHEN $1 ~ '@\w+$'            THEN $1
                       ELSE                              $1 || '/text()'
                      END;
    BEGIN
       -- fetch one, all or distinct values
       CASE $3
           WHEN 'one'  THEN RETURN (xpath(_xpath, $2))[1]::text;
           WHEN 'all'  THEN RETURN array_to_string(xpath(_xpath, $2), ', ');
           WHEN 'dist' THEN RETURN array_to_string(ARRAY(
                SELECT DISTINCT unnest(xpath(_xpath, $2))::text ORDER BY 1), ', ');
           ELSE RAISE EXCEPTION
              'Invalid $3: >>%<<', $3;
       END CASE;
    END
    $func$  LANGUAGE plpgsql;
    
    COMMENT ON FUNCTION f_xml_extract_val(text, xml, text) IS '
    Extract element of an xpath from XML document
    Overloaded function to f_xml_extract_val(..)
    $3 .. mode is one of: one | all | dist'
    

    電話:

    SELECT f_xml_extract_val('//city', x, 'dist');
    

    主要部分

    ターゲットテーブルの名前:tbl;堅苦しい。キー:id

    CREATE OR REPLACE FUNCTION f_sync_from_xml()
      RETURNS boolean AS
    $func$
    DECLARE
       datafile text := 'path/to/my_file.xml';  -- only relative path in db dir
       myxml    xml  := pg_read_file(datafile, 0, 100000000); -- arbitrary 100 MB
    BEGIN
       -- demonstrating 4 variants of how to fetch values for educational purposes
       CREATE TEMP TABLE tmp ON COMMIT DROP AS
       SELECT (xpath('//some_id/text()', x))[1]::text AS id   -- id is unique  
            , f_xml_extract_val('//col1', x)          AS col1 -- one value
            , f_xml_extract_val('//col2/', x, 'all')  AS col2 -- all values incl. dupes
            , f_xml_extract_val('//col3/', x, 'dist') AS col3 -- distinct values
       FROM   unnest(xpath('/xml/path/to/datum', myxml)) x;
    
       -- 1.) DELETE?
    
       -- 2.) UPDATE
       UPDATE tbl t
       SET   (  col_1,   col2,   col3) =
             (i.col_1, i.col2, i.col3)
       FROM   tmp i
       WHERE  t.id = i.id
       AND   (t.col_1, t.col2, t.col3) IS DISTINCT FROM
             (i.col_1, i.col2, i.col3);
    
       -- 3.) INSERT NEW
       INSERT INTO tbl
       SELECT i.*
       FROM   tmp i
       WHERE  NOT EXISTS (SELECT 1 FROM tbl WHERE id = i.id);
    END
    $func$  LANGUAGE plpgsql;
    

    重要な注意事項

    • この実装は、挿入された行がすでに存在するかどうかを主キーでチェックし、更新 この場合。新しい行のみが挿入されます。

    • 手順をスピードアップするために、一時的なステージングテーブルを使用します。

    • Postgres 8.4でテスト済み 、 9.0 および9.1

    • XMLは整形式である必要があります。

    • pg_read_file() それに制限があります。マニュアル:

      これらの機能の使用はスーパーユーザーに制限されています。

      そして:

      データベースクラスタディレクトリとlog_directory内のファイルのみ アクセスできます。

    したがって、ソースファイルをそこに配置するか、実際のファイル/ディレクトリへのシンボリックリンクを作成する必要があります。

    または あなたの場合、Javaを介してファイルを提供することができます(私はすべてPostgres内で行いました)。

    または 一時テーブルの1行の1列にデータをインポートし、そこから取得できます。

    または lo_importを使用できます dba.SEのこの関連する回答で示されているように。

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

    スコットベイリーによるこのブログ投稿は私を助けてくれました。



    1. ユーザーがアクセスできないSQLデータベースを非表示にする方法

    2. PythonからのSQLServerストアドプロシージャの使用(pyodbc)

    3. データベースの削除中にエラーが発生しました(rmdir'.test \'ができません、errno:17)

    4. PHPでSQLインジェクションを防ぐにはどうすればよいですか?