PostgreSQL
 sql >> Cơ Sở Dữ Liệu >  >> RDS >> PostgreSQL

làm cách nào để tạo tệp XML mới từ cơ sở dữ liệu hiện có trong cơ sở dữ liệu PostgreSQL bằng java

Tôi có một triển khai đang hoạt động, nơi tôi thực hiện mọi thứ bên trong PostgreSQL mà không có thư viện bổ sung.

Chức năng phân tích cú pháp phụ trợ

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;

Xử lý nhiều giá trị

Việc triển khai ở trên không xử lý nhiều thuộc tính tại một xpath. Đây là phiên bản quá tải của f_xml_extract_val() cho điều đó. Với tham số thứ 3, bạn có thể chọn one (đầu tiên), all hoặc dist (khác biệt) giá trị. Nhiều giá trị được tổng hợp thành một chuỗi được phân tách bằng dấu phẩy.

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'

Gọi:

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

Phần chính

Tên của bảng mục tiêu:tbl; nghiêm trang. khóa: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;

Các lưu ý quan trọng

  • Việc triển khai này kiểm tra khóa chính nếu hàng được chèn đã tồn tại và cập nhật trong trường hợp này. Chỉ các hàng mới được chèn.

  • Tôi sử dụng bảng tạm thời để tăng tốc quy trình.

  • Đã kiểm tra với Postgres 8.4 , 9.0 9.1 .

  • XML phải được định dạng tốt.

  • pg_read_file() có những hạn chế đối với nó. Hướng dẫn sử dụng:

    Việc sử dụng các chức năng này bị hạn chế đối với người dùng siêu cấp.

    Và:

    Chỉ các tệp trong thư mục cụm cơ sở dữ liệu và log_directory có thể được truy cập.

Vì vậy, bạn phải đặt tệp nguồn của mình ở đó - hoặc tạo một liên kết tượng trưng đến tệp / thư mục thực của bạn.

Hoặc bạn có thể cung cấp tệp qua Java trong trường hợp của mình (tôi đã làm tất cả trong Postgres).

Hoặc bạn có thể nhập dữ liệu vào 1 cột trong 1 hàng của bảng tạm thời và lấy dữ liệu từ đó.

Hoặc bạn có thể sử dụng lo_import như được trình bày trong câu trả lời liên quan này trên dba.SE.

  • SQL để đọc XML từ tệp vào cơ sở dữ liệu PostgreSQL

Bài đăng trên blog này của Scott Bailey đã giúp tôi.



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Khi nào tên cột hoặc bảng Postgres cần dấu ngoặc kép và khi nào thì không?

  2. Lưu đầu ra PL / pgSQL từ PostgreSQL vào tệp CSV

  3. rake db:tạo cơ sở dữ liệu ném không tồn tại lỗi với postgresql

  4. Cột động trong postgres câu lệnh SELECT

  5. PostgreSQL không thể bắt đầu / kết thúc giao dịch trong PL / pgSQL