Xuất các hàng cụ thể từ bảng PostgreSQL dưới dạng tập lệnh SQL INSERT


196

Tôi có một lược đồ cơ sở dữ liệu có tên: nyummyvà một bảng có tên cimory:

create table nyummy.cimory (
  id numeric(10,0) not null,
  name character varying(60) not null,
  city character varying(50) not null,
  CONSTRAINT cimory_pkey PRIMARY KEY (id)
);

Tôi muốn xuất cimorydữ liệu của bảng dưới dạng chèn tệp tập lệnh SQL. Tuy nhiên, tôi chỉ muốn xuất các bản ghi / dữ liệu trong đó thành phố bằng 'tokyo' (giả sử dữ liệu thành phố đều là chữ thường).

Làm thế nào để làm nó?

Không có vấn đề gì cho dù giải pháp là trong các công cụ GUI hoặc dòng lệnh miễn phí (mặc dù giải pháp công cụ GUI tốt hơn). Tôi đã thử pgAdmin III, nhưng tôi không thể tìm thấy tùy chọn nào để làm điều này.


2
bạn có thể bỏ qua các câu lệnh INSERT và chỉ sao chép bằng cách sử dụng trực tiếp giữa các cơ sở dữ liệu. albertech.blogspot.com/2016/11/ trên
jar

PostgreSQL không thể chọn trên cơ sở dữ liệu. Ít nhất, các phiên bản cũ hơn không thể và Greenplum cũng không thể biết về 9.x.
PhilHibbs 17/2/2017

Tôi nhận ra điều này là cũ, nhưng tôi chỉ muốn đề cập rằng nó tốt để chọn trên cơ sở dữ liệu sử dụng dblink , mà đã có sẵn từ ít nhất v8.3. Nó sử dụng các máy chủ nước ngoài và trình bao bọc dữ liệu nước ngoài để kết nối với cơ sở dữ liệu "từ xa". Điều này hoạt động cho dù các cơ sở dữ liệu đó tồn tại trên cùng một thể hiện hoặc các máy chủ hoàn toàn khác nhau. Tôi đã sử dụng nó khá rộng rãi để tạo các khung nhìn cụ thể hóa vào các cơ sở dữ liệu khác để tạo điều kiện cho báo cáo nhất định và như vậy và nó hoạt động rất tốt.
G_Hosa_Phat

Câu trả lời:


280

Tạo một bảng với tập hợp bạn muốn xuất và sau đó sử dụng tiện ích dòng lệnh pg_dump để xuất thành tệp:

create table export_table as 
select id, name, city
from nyummy.cimory
where city = 'tokyo'
$ pg_dump --table=export_table --data-only --column-inserts my_database > data.sql

--column-inserts sẽ kết xuất dưới dạng các lệnh chèn với tên cột.

--data-only không đổ lược đồ.

Như đã nhận xét bên dưới, việc tạo chế độ xem thay vì bảng sẽ làm cản trở việc tạo bảng bất cứ khi nào cần xuất mới.


3
Được rồi, cho đến nay giải pháp của bạn hoạt động. Một điều bị bỏ lỡ là tôi cần thêm "-U user_name". Tôi cũng gần như thành công với công cụ ToraSQL, chỉ là nó có lỗi trong dữ liệu thời gian trong kết quả tập lệnh. Nếu không ai có thể đưa ra giải pháp công cụ GUI trong 2 ngày, câu trả lời của bạn sẽ được chấp nhận
null

2
Chỉ muốn chia sẻ với người khác, bạn cũng có thể sử dụng công cụ GUI miễn phí này: SQL Workbench / J (với trình điều khiển jdbc4 postgreQuery), để làm điều tương tự.
null

1
Điều này sẽ tốt hơn nhiều create view export_view..., vì chế độ xem sẽ được cập nhật với các thay đổi đối với bảng cơ sở. Các tài liệu nói --table=table: Dump only tables (or **views**...như vậy tôi đã có một số hy vọng điều này sẽ hoạt động, nhưng bỏ đi một quan điểm đáng buồn không mang lại dữ liệu. : P
lâu nhất là

@poshest Nó hoạt động với tôi trong 9.5. Chính xác thì bạn đã thử gì?
Clodoaldo Neto

@ClodoaldoNeto oh, OK tuyệt vời! Tôi hy vọng tôi cũng có thể làm cho nó hoạt động. Tôi đã sử dụng pg_dump --table=my_schema.my_view --data-only --inserts my_db > data.sql, phiên bản 9.5.3 và createtuyên bố của tôi giống với phiên bản của bạn ngoại trừ create view.... Tất cả tôi nhận được trong đầu ra là các nhận xét và SETtuyên bố pg_dump thông thường . Không chắc chắn tôi sẽ đi sai ở đâu.
mạnh nhất vào

176

Đối với việc sử dụng chỉ xuất dữ liệuCOPY .
Bạn nhận được một tệp có một hàng trong mỗi dòng dưới dạng văn bản thuần túy (không phải INSERTlệnh), nó nhỏ hơn và nhanh hơn:

COPY (SELECT * FROM nyummy.cimory WHERE city = 'tokio') TO '/path/to/file.csv';

Nhập cùng một bảng khác có cùng cấu trúc ở bất cứ đâu với:

COPY other_tbl FROM '/path/to/file.csv';

COPYghi và đọc tệp cục bộ vào máy chủ , không giống như các chương trình máy khách như pg_dumphoặc psqlđọc và ghi tệp cục bộ cho máy khách . Nếu cả hai chạy trên cùng một máy, điều đó không thành vấn đề, nhưng đối với các kết nối từ xa.

Ngoài ra còn có \copylệnh của psql rằng:

Thực hiện một bản sao frontend (client). Đây là một hoạt động chạy một lệnh SQL COPY, nhưng thay vì máy chủ đọc hoặc ghi tệp được chỉ định, psql đọc hoặc ghi tệp và định tuyến dữ liệu giữa máy chủ và hệ thống tệp cục bộ. Điều này có nghĩa là khả năng truy cập và đặc quyền của tệp là của người dùng cục bộ, không phải máy chủ và không yêu cầu đặc quyền siêu người dùng SQL.


10
OP gọi đặc biệt cho dữ liệu dưới dạng tệp tập lệnh sql chèn . Tôi đoán anh ấy đang nói về insertcác lệnh, phải không?
Clodoaldo Neto

1
@Clodoaldo: Bạn có thể đúng, trong trường hợp đó câu trả lời của bạn sẽ phù hợp hơn. Người ta cũng có thể sao chép tập lệnh CREATE trong pgAdmin một cách riêng biệt (như OP đề cập đến GUI).
Erwin Brandstetter

3
STDINSTDOUTcó thể được sử dụng thay cho đường dẫn tệp, hữu ích cho xuất dữ liệu nhỏ.
Amir Ali Akbari

1
Nếu không có những --column-insertslá cờ, pg_dump sử dụng một COPYtừ STDIN cho mỗi bảng trong các mã SQL nó tạo ra.
Randall

2
Cẩn thận rằng thứ tự của các cột bạn CHỌN khớp với thứ tự của các cột trong cơ sở dữ liệu đích. Nếu không, điều này có thể thất bại, hoặc tệ hơn, thành công nhưng chèn dữ liệu xấu.
Nathan Wallace

32

Đây là một cách dễ dàng và nhanh chóng để xuất bảng thành tập lệnh với pgAdmin theo cách thủ công mà không cần cài đặt thêm :

  1. Nhấp chuột phải vào bảng đích và chọn "Sao lưu".
  2. Chọn một đường dẫn tệp để lưu trữ bản sao lưu. Như Định dạng, chọn "Đồng bằng".
  3. Mở tab "Tùy chọn kết xuất số 2" ở dưới cùng và kiểm tra "Sử dụng chèn cột".
  4. Nhấp vào nút Sao lưu.
  5. Nếu bạn mở tệp kết quả bằng trình đọc văn bản (ví dụ notepad ++), bạn sẽ nhận được một tập lệnh để tạo toàn bộ bảng. Từ đó, bạn có thể chỉ cần sao chép các Báo cáo INSERT được tạo.

Phương pháp này cũng hoạt động với kỹ thuật tạo export_table như được thể hiện trong câu trả lời của @Clodoaldo Neto.

Nhấp chuột phải vào bảng đích và chọn "Sao lưu"

Chọn một đường dẫn đích và thay đổi định dạng thành "Plain"

Mở tab "Tùy chọn kết xuất số 2" ở dưới cùng và kiểm tra "Sử dụng chèn cột"

Bạn có thể sao chép Báo cáo INSERT từ đó.


Khi tôi làm điều này, không có tùy chọn "Bakckup". Đây là pgAdmin III v1.18.1 kết nối với Greenplum 4.3.4.1 (dựa trên PostgreQuery 8.2.15).
PhilHibbs

Tôi đã cài đặt pgAdmin III v1.18.1 và có được sự lựa chọn "backup". Tôi đã kết nối với PostgreQuery 9.5. Vì vậy, vấn đề có lẽ là giữa pgAdmin và Greenplum.
Andi R

Hoạt động như dự định trong pgAdmin4
Nikhil

9

SQL Workbench có một tính năng như vậy.

Sau khi chạy truy vấn, nhấp chuột phải vào kết quả truy vấn và chọn "Sao chép dữ liệu dưới dạng SQL> Chèn SQL"


1
Nó hoạt động rất tốt. Khi bạn chọn 'postgres' làm 'trình điều khiển', có thể bạn sẽ phải tự tải xuống trình điều khiển JDBC: jdbc.postgresql.org/doad.html (đó là tệp .jar - java nhị phân) và thêm nó dưới dạng 'trình điều khiển' của kết nối postgresql. Chuỗi kết nối (hoặc URL như trong giao diện) sẽ trông như thế: jdbc: postgresql: //127.0.0.1: 5432 / db_name
mrmuggles

DBVisualizer có một tính năng tương tự và tuyệt vời có thể sao chép vào một tệp hoặc vào thẳng bảng tạm.
Noumenon

8

Đối với trường hợp sử dụng của tôi, tôi có thể chỉ cần chuyển sang grep.

pg_dump -U user_name --data-only --column-inserts -t nyummy.cimory | grep "tokyo" > tokyo.sql

2
Người ta phải xem xét về việc có "tokyo" trong lĩnh vực khác.
Buyut Joko Rivai

@BuyutJokoRivai vì đó là bàn chỉ đổ trong hầu hết các trường hợp nên nó vẫn ổn
Ismail Iqbal

Cách thông minh nhất trong số những người khác về vụ án <3
Nam G VU

Mặc dù với bảng lớn, bạn sẽ kết xuất tất cả các hàng cho grep, đây là trường hợp đáng tiếc cho giải pháp của bạn. Sau đó, cách chúng tôi truy vấn và lưu trữ kết quả vào một bảng để kết xuất như ở đây stackoverflow.com/a/12816187/248616 phù hợp hơn
Nam G VU

5

Tôi đã cố gắng viết một quy trình thực hiện điều đó, dựa trên mã @PhilHibbs, theo một cách khác. Xin hãy xem và kiểm tra.

 CREATE OR REPLACE FUNCTION dump(IN p_schema text, IN p_table text, IN p_where text)
   RETURNS setof text AS
 $BODY$
 DECLARE
     dumpquery_0 text;
     dumpquery_1 text;
     selquery text;
     selvalue text;
     valrec record;
     colrec record;
 BEGIN

     -- ------ --
     -- GLOBAL --
     --   build base INSERT
     --   build SELECT array[ ... ]
     dumpquery_0 := 'INSERT INTO ' ||  quote_ident(p_schema) || '.' || quote_ident(p_table) || '(';
     selquery    := 'SELECT array[';

     <<label0>>
     FOR colrec IN SELECT table_schema, table_name, column_name, data_type
                   FROM information_schema.columns
                   WHERE table_name = p_table and table_schema = p_schema
                   ORDER BY ordinal_position
     LOOP
         dumpquery_0 := dumpquery_0 || quote_ident(colrec.column_name) || ',';
         selquery    := selquery    || 'CAST(' || quote_ident(colrec.column_name) || ' AS TEXT),';
     END LOOP label0;

     dumpquery_0 := substring(dumpquery_0 ,1,length(dumpquery_0)-1) || ')';
     dumpquery_0 := dumpquery_0 || ' VALUES (';
     selquery    := substring(selquery    ,1,length(selquery)-1)    || '] AS MYARRAY';
     selquery    := selquery    || ' FROM ' ||quote_ident(p_schema)||'.'||quote_ident(p_table);
     selquery    := selquery    || ' WHERE '||p_where;
     -- GLOBAL --
     -- ------ --

     -- ----------- --
     -- SELECT LOOP --
     --   execute SELECT built and loop on each row
     <<label1>>
     FOR valrec IN  EXECUTE  selquery
     LOOP
         dumpquery_1 := '';
         IF not found THEN
             EXIT ;
         END IF;

         -- ----------- --
         -- LOOP ARRAY (EACH FIELDS) --
         <<label2>>
         FOREACH selvalue in ARRAY valrec.MYARRAY
         LOOP
             IF selvalue IS NULL
             THEN selvalue := 'NULL';
             ELSE selvalue := quote_literal(selvalue);
             END IF;
             dumpquery_1 := dumpquery_1 || selvalue || ',';
         END LOOP label2;
         dumpquery_1 := substring(dumpquery_1 ,1,length(dumpquery_1)-1) || ');';
         -- LOOP ARRAY (EACH FIELD) --
         -- ----------- --

         -- debug: RETURN NEXT dumpquery_0 || dumpquery_1 || ' --' || selquery;
         -- debug: RETURN NEXT selquery;
         RETURN NEXT dumpquery_0 || dumpquery_1;

     END LOOP label1 ;
     -- SELECT LOOP --
     -- ----------- --

 RETURN ;
 END
 $BODY$
   LANGUAGE plpgsql VOLATILE;

Và sau đó :

-- for a range
SELECT dump('public', 'my_table','my_id between 123456 and 123459'); 
-- for the entire table
SELECT dump('public', 'my_table','true');

đã thử nghiệm trên postgres 9.1 của tôi, với một bảng có kiểu dữ liệu trường hỗn hợp (văn bản, double, int, dấu thời gian không có múi giờ, v.v.).

Đó là lý do tại sao CAST trong loại văn bản là cần thiết. Thử nghiệm của tôi chạy chính xác cho khoảng 9 triệu dòng, có vẻ như nó bị lỗi ngay trước 18 phút chạy.

ps: Tôi đã tìm thấy một tương đương cho mysql trên WEB.


3

Bạn có thể tạo chế độ xem bảng với các bản ghi cụ thể và sau đó kết xuất tệp sql

CREATE VIEW foo AS
SELECT id,name,city FROM nyummy.cimory WHERE city = 'tokyo'

3
Tôi đã thử nó trong pgAdmin III, nhưng đối với View object, không có tùy chọn nào để bán phá giá.
null

Hãy thử điều hướng. Tôi đang sử dụng nó và nó có tùy chọn xuất khẩu sql script
Giorgi Peikrishvili

@Giorgi: có phiên bản phần mềm miễn phí không?
null

Không thể sử dụng Postgres 9.1
HCarrasko

2

Tôi chỉ cần gõ một thủ tục nhanh chóng để làm điều này. Nó chỉ hoạt động cho một hàng duy nhất, vì vậy tôi tạo một chế độ xem tạm thời chỉ chọn hàng tôi muốn và sau đó thay thế pg_temp.temp_view bằng bảng thực tế mà tôi muốn chèn vào.

CREATE OR REPLACE FUNCTION dv_util.gen_insert_statement(IN p_schema text, IN p_table text)
  RETURNS text AS
$BODY$
DECLARE
    selquery text; 
    valquery text; 
    selvalue text; 
    colvalue text; 
    colrec record;
BEGIN

    selquery := 'INSERT INTO ' ||  quote_ident(p_schema) || '.' || quote_ident(p_table);

    selquery := selquery || '(';

    valquery := ' VALUES (';
    FOR colrec IN SELECT table_schema, table_name, column_name, data_type
                  FROM information_schema.columns 
                  WHERE table_name = p_table and table_schema = p_schema 
                  ORDER BY ordinal_position 
    LOOP
      selquery := selquery || quote_ident(colrec.column_name) || ',';

      selvalue := 
        'SELECT CASE WHEN ' || quote_ident(colrec.column_name) || ' IS NULL' || 
                   ' THEN ''NULL''' || 
                   ' ELSE '''' || quote_literal('|| quote_ident(colrec.column_name) || ')::text || ''''' || 
                   ' END' || 
        ' FROM '||quote_ident(p_schema)||'.'||quote_ident(p_table);
      EXECUTE selvalue INTO colvalue;
      valquery := valquery || colvalue || ',';
    END LOOP;
    -- Replace the last , with a )
    selquery := substring(selquery,1,length(selquery)-1) || ')';
    valquery := substring(valquery,1,length(valquery)-1) || ')';

    selquery := selquery || valquery;

RETURN selquery;
END
$BODY$
  LANGUAGE plpgsql VOLATILE;

Được viện dẫn như vậy:

SELECT distinct dv_util.gen_insert_statement('pg_temp_' || sess_id::text,'my_data') 
from pg_stat_activity 
where procpid = pg_backend_pid()

Tôi đã không kiểm tra điều này chống lại các cuộc tấn công tiêm chích, xin vui lòng cho tôi biết nếu cuộc gọi quote_literal không đủ cho điều đó.

Ngoài ra, nó chỉ hoạt động cho các cột có thể được chuyển đơn giản thành :: văn bản và trở lại.

Ngoài ra, đây là cho Greenplum nhưng tôi không thể nghĩ ra lý do tại sao nó không hoạt động trên Postgres, CMIIW.


-2

Bạn đã thử truy vấn thực thi pgadmin với " EXECUTE QUERY WRITE RESULT TO FILE " tùy chọn chưa

Nó chỉ xuất dữ liệu, khác thử

pg_dump -t view_name DB_name > db.sql

-t tùy chọn được sử dụng cho ==> Chỉ kết xuất các bảng (hoặc dạng xem hoặc chuỗi) khớp với bảng, tham khảo


1
Điều này sẽ chỉ xuất một create viewtuyên bố
cdmckay
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.