ส่งออกแถวเฉพาะจากตาราง PostgreSQL เป็นสคริปต์ INSERT SQL


196

ฉันมีสคีมาฐานข้อมูลชื่อ: nyummyและตารางที่ชื่อว่า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)
);

ฉันต้องการส่งออกcimoryข้อมูลของตารางเป็นการแทรกไฟล์สคริปต์ SQL อย่างไรก็ตามฉันต้องการส่งออกบันทึก / ข้อมูลที่มีค่าเท่ากับ 'tokyo' เท่านั้น (สมมติว่าข้อมูลเมืองเป็นตัวพิมพ์เล็กทั้งหมด)

ทำอย่างไร?

ไม่สำคัญว่าโซลูชันจะอยู่ในเครื่องมือ GUI ฟรีแวร์หรือบรรทัดคำสั่ง (แม้ว่าโซลูชันเครื่องมือ GUI จะดีกว่า) ฉันลอง pgAdmin III แล้ว แต่ไม่พบตัวเลือกในการทำเช่นนี้


2
คุณสามารถข้ามคำสั่ง INSERT และเพียงคัดลอกโดยใช้ SELECT โดยตรงระหว่างฐานข้อมูล albertech.blogspot.com/2016/11/...
— ขวด

PostgreSQL ไม่สามารถเลือกข้ามฐานข้อมูลได้ อย่างน้อยรุ่นที่เก่ากว่าไม่สามารถและไม่สามารถ Greenplum ไม่รู้เรื่อง 9.x
— PhilHibbs

ฉันรู้ว่านี่เป็นรุ่นเก่า แต่ฉันแค่อยากพูดถึงว่าเป็นไปได้ที่จะเลือกข้ามฐานข้อมูลโดยใช้dblinkซึ่งมีให้บริการตั้งแต่ v8.3 เป็นอย่างน้อย มันทำให้การใช้เซิร์ฟเวอร์ต่างประเทศและห่อข้อมูลต่างประเทศเพื่อเชื่อมต่อกับฐานข้อมูล "ระยะไกล" สิ่งนี้ทำงานได้หรือไม่ว่าฐานข้อมูลเหล่านั้นมีอยู่บนอินสแตนซ์เดียวกันหรือโฮสต์ที่แตกต่างกันโดยสิ้นเชิง ฉันใช้มันอย่างกว้างขวางในการสร้างมุมมองที่เป็นรูปธรรมในฐานข้อมูลอื่น ๆ เพื่ออำนวยความสะดวกในการรายงานบางอย่างและมันก็ใช้งานได้ดี
— G_Hosa_Phat

คำตอบ:


282

สร้างตารางด้วยชุดที่คุณต้องการส่งออกจากนั้นใช้ยูทิลิตีบรรทัดคำสั่ง pg_dump เพื่อส่งออกไปยังไฟล์:

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 จะถ่ายโอนข้อมูลเป็นคำสั่งแทรกด้วยชื่อคอลัมน์

--data-only อย่าดัมพ์สกีมา

ตามที่แสดงความคิดเห็นด้านล่างการสร้างมุมมองแทนที่จะเป็นตารางจะทำให้เกิดการสร้างตารางเมื่อใดก็ตามที่จำเป็นต้องทำการเอ็กซ์ปอร์ตใหม่


3
เอาล่ะวิธีแก้ปัญหาของคุณก็ใช้ได้ สิ่งหนึ่งที่ฉันพลาดคือฉันต้องเพิ่ม "-U user_name" ฉันก็เกือบจะประสบความสำเร็จกับเครื่องมือ ToraSQL มันเป็นเพียงว่ามันมีข้อผิดพลาดในข้อมูลวันที่ในผลสคริปต์ หากไม่มีใครสามารถให้โซลูชันเครื่องมือ GUI ได้ภายใน 2 วันคำตอบของคุณจะได้รับการยอมรับ
— null

2
เพียงแค่ต้องการแบ่งปันให้กับคนอื่น ๆ คุณยังสามารถใช้เครื่องมือ GUI ฟรีนี้: SQL Workbench / J (พร้อมไดรเวอร์ jpgc4 postgreSQL) เพื่อทำสิ่งเดียวกัน
— null

2
สิ่งนี้จะดีกว่ามากcreate view export_view...เนื่องจากมุมมองจะยังคงทันสมัยกับการเปลี่ยนแปลงในตารางฐาน เอกสารกล่าวว่า--table=table: Dump only tables (or **views**...ดังนั้นผมจึงมีความหวังบางอย่างนี้จะทำงาน แต่การทุ่มตลาดมุมมองที่น่าเศร้าที่อัตราผลตอบแทนที่ไม่มีข้อมูล : P
— poshest

1
@poshest มันเหมาะกับฉันใน 9.5 คุณลองทำอะไรบ้าง
— Clodoaldo Neto

@ ClodoaldoNeto โอ้เยี่ยมมาก! ฉันหวังว่าฉันจะสามารถทำงานได้ ผมใช้pg_dump --table=my_schema.my_view --data-only --inserts my_db > data.sqlรุ่น 9.5.3 และฉันคำสั่งเป็นเช่นเดียวกับคุณยกเว้นcreate create view...สิ่งที่ฉันได้รับในผลลัพธ์คือความคิดเห็นและSETคำสั่งpg_dump ปกติ ไม่แน่ใจว่าฉันจะไปไหนผิด
— poshest

176

สำหรับข้อมูลการส่งออกอย่างเดียวCOPYการใช้งาน
คุณได้รับไฟล์ที่มีหนึ่งตารางแถวต่อบรรทัดเป็นข้อความธรรมดา (ไม่ใช่INSERTคำสั่ง) มันเล็กกว่าและเร็วกว่า:

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

นำเข้าสิ่งเดียวกันไปยังอีกตารางหนึ่งของโครงสร้างเดียวกันทุกที่ด้วย:

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

COPYเขียนและอ่านไฟล์ในเครื่องไปยังเซิร์ฟเวอร์ซึ่งแตกต่างจากโปรแกรมไคลเอนต์เช่นpg_dumpหรือpsqlที่อ่านและเขียนไฟล์ในเครื่องไปยังลูกค้าในท้องถิ่นให้กับลูกค้าหากทั้งสองทำงานบนเครื่องเดียวกันมันไม่สำคัญมากนัก แต่มันสำหรับการเชื่อมต่อระยะไกล

นอกจากนี้ยังมี\copyคำสั่งของ psqlที่:

ดำเนินการสำเนาส่วนหน้า (ไคลเอนต์) นี่คือการดำเนินการที่รันCOPYคำสั่งSQL แต่แทนที่จะเซิร์ฟเวอร์อ่านหรือเขียนไฟล์ที่ระบุ psql จะอ่านหรือเขียนไฟล์และกำหนดเส้นทางข้อมูลระหว่างเซิร์ฟเวอร์และระบบไฟล์โลคัล ซึ่งหมายความว่าการเข้าถึงไฟล์และสิทธิพิเศษเป็นของผู้ใช้ท้องถิ่นไม่ใช่เซิร์ฟเวอร์และไม่ต้องการสิทธิ์ SQL superuser


10
สหกรณ์เรียกเฉพาะสำหรับข้อมูลเป็นไฟล์สคริปต์แทรก SQL ฉันเดาว่าเขากำลังพูดถึงinsertคำสั่งใช่ไหม?
— Clodoaldo Neto

1
@Cloñaldo: คุณอาจจะถูกซึ่งในกรณีนี้คำตอบของคุณจะเหมาะสมกว่า หนึ่งสามารถคัดลอกสคริปต์สร้างใน pgAdmin แยกต่างหาก (เป็น GUI กล่าวถึง OP)
— Erwin Brandstetter

3
STDINและSTDOUTสามารถใช้แทนพา ธ ไฟล์ซึ่งมีประโยชน์สำหรับการส่งออกข้อมูลขนาดเล็ก
— อาเมียร์อาลีอั

1
โดยไม่ต้อง--column-insertsธง pg_dump ใช้COPYจาก STDIN สำหรับแต่ละตารางใน SQL รหัสมันสร้าง
— Randall

2
โปรดระวังว่าลำดับของคอลัมน์ที่คุณเลือกตรงกับลำดับของคอลัมน์ในฐานข้อมูลปลายทาง หากไม่เป็นเช่นนี้อาจล้มเหลวหรือแย่กว่านั้นได้สำเร็จ แต่แทรกข้อมูลที่ไม่ดี
— Nathan Wallace

32

นี่เป็นวิธีที่ง่ายและรวดเร็วในการส่งออกตารางไปยังสคริปต์ด้วย pgAdminด้วยตนเองโดยไม่ต้องติดตั้งเพิ่มเติม :

  1. คลิกขวาที่ตารางเป้าหมายและเลือก "สำรองข้อมูล"
  2. เลือกเส้นทางไฟล์เพื่อจัดเก็บข้อมูลสำรอง ในฐานะที่เป็นรูปแบบเลือก "ธรรมดา"
  3. เปิดแท็บ "ตัวเลือกการถ่ายโอนข้อมูล # 2" ที่ด้านล่างและทำเครื่องหมาย "ใช้การแทรกคอลัมน์"
  4. คลิกปุ่มสำรองข้อมูล
  5. หากคุณเปิดไฟล์ผลลัพธ์ด้วยโปรแกรมอ่านข้อความ (เช่น notepad ++) คุณจะได้รับสคริปต์เพื่อสร้างตารางทั้งหมด จากตรงนั้นคุณสามารถคัดลอก INSERT-Statement ที่สร้างขึ้น

วิธีนี้ยังทำงานร่วมกับเทคนิคการสร้าง export_table ตามที่แสดงในคำตอบของ @Clodoaldo Neto

คลิกขวาที่ตารางเป้าหมายและเลือก "สำรองข้อมูล"

เลือกเส้นทางปลายทางและเปลี่ยนรูปแบบเป็น "ธรรมดา"

เปิดแท็บ "Dump Options # 2" ที่ด้านล่างและทำเครื่องหมาย "ใช้การแทรกคอลัมน์"

คุณสามารถคัดลอกคำสั่ง INSERT ได้จากตรงนั้น


เมื่อฉันทำสิ่งนี้ไม่มีตัวเลือก "Bakckup" นี่คือ pgAdmin III v1.18.1 ที่เชื่อมต่อกับ Greenplum 4.3.4.1 (อ้างอิงจาก PostgreSQL 8.2.15)
— PhilHibbs

ผมติดตั้ง v1.18.1 pgAdmin III และมีเป็น "Backup" ตัวเลือก ฉันเชื่อมต่อกับ PostgreSQL 9.5 ดังนั้นปัญหาน่าจะเป็นระหว่าง pgAdmin และ Greenplum
— Andi R

ทำงานตามที่คาดไว้ใน pgAdmin4
— Nikhil

9

ปรับแต่ง SQLมีคุณสมบัติดังกล่าว

หลังจากเรียกใช้แบบสอบถามคลิกขวาที่ผลลัพธ์แบบสอบถามแล้วเลือก "คัดลอกข้อมูลเป็น SQL> แทรก SQL"


1
มันใช้งานได้ดี เมื่อคุณเลือก 'postgres' เป็น 'driver' อาจเป็นไปได้ว่าคุณจะต้องดาวน์โหลดไดรเวอร์ JDBC ด้วยตัวเอง: jdbc.postgresql.org/download.html (เป็นไฟล์. jar - java binary) และเพิ่มเป็น 'ไดรเวอร์' ของการเชื่อมต่อ postgresql สตริงการเชื่อมต่อ (หรือ URL ในอินเทอร์เฟซ) ควรมีลักษณะดังนี้: jdbc: postgresql: //127.0.0.1: 5432 / db_name
— mrmuggles

DBVisualizerมีคุณสมบัติที่คล้ายกันและยอดเยี่ยมที่สามารถคัดลอกไปยังไฟล์หรือตรงไปที่คลิปบอร์ด
— Noumenon

8

สำหรับกรณีการใช้งานของฉันฉันก็สามารถท่อไป grep

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

2
เราต้องคำนึงถึงการมี 'โตเกียว' ในสาขาอื่น
— Buyut Joko Rivai

@BuyutJokoRivai เนื่องจากเป็นตารางการถ่ายโอนข้อมูลเพียงในกรณีส่วนใหญ่ควรจะปรับ
— อิสมาอิลอิคบาล

วิธีที่ฉลาดที่สุดในหมู่คนอื่นในคดี <3
— Nam G VU

แม้ว่าจะมีตารางขนาดใหญ่คุณจะทิ้งแถวทั้งหมดสำหรับ grep ซึ่งเป็นกรณีที่ผิดพลาดสำหรับวิธีการแก้ปัญหาของคุณ จากนั้นวิธีที่เราสืบค้นและจัดเก็บผลลัพธ์ลงในตารางเพื่อถ่ายโอนข้อมูลที่นี่stackoverflow.com/a/12816187/248616นั้นมีความเหมาะสมมากกว่า
— Nam G VU

5

ฉันพยายามเขียนขั้นตอนการทำตามรหัส @PhilHibbs ด้วยวิธีอื่น กรุณาดูและทดสอบ

 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;

แล้ว:

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

ทดสอบกับ postgres ของฉัน 9.1 พร้อมกับตารางที่มีประเภทข้อมูลผสม (ข้อความ, double, int, timestamp โดยไม่มีเขตเวลา ฯลฯ )

นั่นเป็นเหตุผลที่จำเป็นต้องใช้ CAST ในรูปแบบ TEXT การทดสอบของฉันทำงานอย่างถูกต้องสำหรับสายประมาณ 9M ดูเหมือนว่าจะล้มเหลวก่อนการทำงาน 18 นาที

ps: ฉันพบว่า mysql บนเว็บเทียบเท่ากัน


3

คุณสามารถสร้างมุมมองของตารางด้วยเร็กคอร์ด specifit จากนั้นดัมพ์ไฟล์ sql

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

3
ฉันลองใช้ใน pgAdmin III แต่สำหรับวัตถุ View ไม่มีตัวเลือกสำหรับการถ่ายโอนข้อมูล
— null

ลองใช้ navicat ฉันใช้มันและมีตัวเลือกสคริปต์ส่งออก sql
— Giorgi Peikrishvili

@Giorgi: มีรุ่นฟรีแวร์หรือไม่
— null

ไม่สามารถใช้ Postgres 9.1
— HCarrasko

2

ฉันเพิ่งทำขั้นตอนด่วนเพื่อทำสิ่งนี้ ใช้งานได้กับแถวเดียวเท่านั้นดังนั้นฉันจึงสร้างมุมมองชั่วคราวที่เลือกแถวที่ฉันต้องการจากนั้นแทนที่ pg_temp.temp_view ด้วยตารางจริงที่ฉันต้องการแทรก

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;

อุทธรณ์ดังนี้:

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

ฉันยังไม่ได้ทดสอบสิ่งนี้กับการโจมตีของการฉีดโปรดแจ้งให้เราทราบหากการเรียก quote_literal นั้นไม่เพียงพอสำหรับเรื่องนั้น

นอกจากนี้ยังใช้งานได้กับคอลัมน์ที่สามารถส่งไปยัง :: text และกลับมาอีกครั้งได้อย่างง่ายดาย

นอกจากนี้สำหรับ Greenplum แต่ฉันไม่สามารถคิดได้ว่าทำไมมันถึงไม่ทำงานกับ Postgres, CMIIW


-2

คุณได้ลอง pgadmin ในการดำเนินการค้นหาด้วย " EXECUTE QUERY WRITE RESULT TO FILE " ตัวเลือก

มันเป็นเพียงการส่งออกข้อมูลมิฉะนั้นจะลอง

pg_dump -t view_name DB_name > db.sql

ตัวเลือกที่ใช้สำหรับ ==> การถ่ายโอนข้อมูลตารางเท่านั้น (หรือมุมมองหรือลำดับ) ตารางการจับคู่อ้างอิง


1
สิ่งนี้จะส่งออกcreate viewข้อความ
— cdmckay
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.