ส่งออกแถวเฉพาะจากตาราง 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.