Esporta righe specifiche da una tabella PostgreSQL come script INSERT SQL


196

Ho uno schema di database chiamato: nyummye una tabella denominata 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)
);

Voglio esportare i cimorydati della tabella come inserire il file di script SQL. Tuttavia, desidero solo esportare record / dati in cui la città è uguale a "tokyo" (supponiamo che i dati della città siano tutti in minuscolo).

Come farlo?

Non importa se la soluzione si trova negli strumenti della GUI freeware o nella riga di comando (sebbene la soluzione degli strumenti della GUI sia migliore). Avevo provato pgAdmin III, ma non riesco a trovare un'opzione per farlo.


2
potresti saltare le istruzioni INSERT e semplicemente copiare usando SELECT direttamente tra i database. albertech.blogspot.com/2016/11/…
jar

PostgreSQL non può selezionare tra i database. Almeno, le versioni precedenti non possono e nemmeno Greenplum, non conoscono 9.x.
PhilHibbs,

Mi rendo conto che questo è vecchio, ma volevo solo menzionare che è possibile selezionare tra i database usando dblink , che è disponibile almeno dalla v8.3. Utilizza server esterni e wrapper di dati esterni per connettersi a database "remoti". Funziona indipendentemente dal fatto che tali database esistano nella stessa istanza o in host completamente diversi. L'ho usato abbastanza ampiamente per creare viste materializzate in altri database per facilitare alcuni rapporti e simili e funziona benissimo.
G_Hosa_Phat il

Risposte:


282

Creare una tabella con il set che si desidera esportare e quindi utilizzare l'utilità della riga di comando pg_dump per esportare in un file:

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 eseguirà il dump come comandi di inserimento con nomi di colonna.

--data-only non scaricare lo schema.

Come commentato di seguito, la creazione di una vista anziché una tabella eviterà la creazione della tabella ogni volta che è necessaria una nuova esportazione.


3
Bene, finora la tua soluzione funziona. Una cosa che mi manca è che devo aggiungere "-U nome_utente". Ho anche quasi successo con lo strumento ToraSQL, è solo che ha un errore nei dati data-ora nel risultato dello script. Se nessuno può fornire la soluzione dello strumento GUI in 2 giorni, la tua risposta sarà accettata
null

2
Voglio solo condividere con altre persone, puoi anche usare questo strumento GUI gratuito: SQL Workbench / J (con driver postgreSQL jdbc4), per fare la stessa cosa.
null

2
Questo sarebbe molto meglio con create view export_view..., poiché la vista rimarrebbe aggiornata con le modifiche alla tabella di base. I documenti dicono--table=table: Dump only tables (or **views**... che avevo qualche speranza che funzionasse, ma il dumping di una vista purtroppo non produce dati. : P
poshest

1
@poshest Funziona per me in 9.5. Cosa hai provato esattamente?
Clodoaldo Neto

@ClodoaldoNeto oh, OK fantastico! Spero di riuscire a farlo funzionare. Ho usato pg_dump --table=my_schema.my_view --data-only --inserts my_db > data.sql, versione 9.5.3, e la mia createaffermazione era la stessa della tua tranne create view.... Tutto ciò che ottengo nell'output sono i soliti commenti e SETdichiarazioni di pg_dump . Non sono sicuro di dove sbaglio.
più elegante il

176

Per un uso di esportazione solo datiCOPY .
Ottieni un file con una riga di tabella per riga come testo normale (non INSERTcomandi), è più piccolo e più veloce:

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

Importa lo stesso in un'altra tabella della stessa struttura ovunque con:

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

COPYscrive e legge i file locali sul server , diversamente dai programmi client simili pg_dumpo psqlche leggono e scrivono i file locali sul client . Se entrambi funzionano sulla stessa macchina, non importa molto, ma lo fa per le connessioni remote.

C'è anche il \copycomando di psql che:

Esegue una copia di frontend (client). Questa è un'operazione che esegue un SQLCOPY comando , ma invece del server che legge o scrive il file specificato, psql legge o scrive il file e instrada i dati tra il server e il file system locale. Ciò significa che l'accessibilità e i privilegi dei file sono quelli dell'utente locale, non del server, e non sono richiesti privilegi di superutente SQL.


10
L'OP chiama specificamente per i dati come inserire il file di script sql . Immagino che stia parlando di insertcomandi, vero?
Clodoaldo Neto,

1
@Clodoaldo: potresti avere ragione, nel qual caso la tua risposta sarebbe più adatta. Si potrebbe anche copiare separatamente lo script CREATE in pgAdmin (poiché l'OP menziona le GUI).
Erwin Brandstetter,

3
STDINe STDOUTpuò essere utilizzato al posto del percorso del file, utile per le esportazioni di piccoli dati.
Amir Ali Akbari,

1
Senza il --column-insertsflag, pg_dump usa un COPYda STDIN per ciascuna delle tabelle nel codice SQL che genera.
Randall,

2
Assicurarsi che l'ordine delle colonne SELEZIONATE corrisponda all'ordine delle colonne nel database di destinazione. In caso contrario, ciò potrebbe non riuscire, o peggio, riuscire ma inserire dati errati.
Nathan Wallace,

32

Questo è un modo semplice e veloce per esportare manualmente una tabella in uno script con pgAdmin senza installazioni extra :

  1. Fare clic destro sulla tabella di destinazione e selezionare "Backup".
  2. Selezionare un percorso file per archiviare il backup. Come formato scegliere "Semplice".
  3. Apri la scheda "Opzioni di scarico n. 2" in basso e seleziona "Usa inserti di colonna".
  4. Fai clic sul pulsante Backup.
  5. Se si apre il file risultante con un lettore di testo (ad esempio notepad ++) si ottiene uno script per creare l'intera tabella. Da lì puoi semplicemente copiare le istruzioni INSERT generate.

Questo metodo funziona anche con la tecnica di creazione di una tabella esportazione come dimostrato nella risposta di @Clodoaldo Neto.

Fai clic destro sulla tabella di destinazione e scegli "Backup"

Scegli un percorso di destinazione e cambia il formato in "Semplice"

Apri la scheda "Opzioni di scarico n. 2" in basso e seleziona "Usa inserti di colonna"

È possibile copiare le istruzioni INSERT da lì.


Quando lo faccio, non esiste l'opzione "Bakckup". Questa è pgAdmin III v1.18.1 che si collega a Greenplum 4.3.4.1 (basato su PostgreSQL 8.2.15).
PhilHibbs,

Ho installato pgAdmin III v1.18.1 e non vi era la possibilità di "backup". Mi sono collegato a un PostgreSQL 9.5. Quindi il problema è molto probabilmente tra pgAdmin e Greenplum.
Andi R,

Funziona come previsto in pgAdmin4
Nikhil,

9

SQL Workbench ha una tale funzionalità.

Dopo aver eseguito una query, fai clic con il pulsante destro del mouse sui risultati della query e scegli "Copia dati come SQL> Inserisci SQL"


1
Funziona benissimo. Quando scegli "postgres" come "driver", è probabile che dovrai scaricare tu stesso i driver JDBC: jdbc.postgresql.org/download.html (è un file .jar - binario java) e aggiungerlo come "driver" della connessione postgresql. La stringa di connessione (o URL come nell'interfaccia) dovrebbe apparire così: jdbc: postgresql: //127.0.0.1: 5432 /
nome_db

DBVisualizer ha una funzione simile ed eccellente che può essere copiata su un file o direttamente negli appunti.
Noumenon,

8

Per il mio caso d'uso sono stato semplicemente in grado di eseguire pipe per grep.

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

2
Bisogna considerare di avere "tokyo" in un altro campo.
Buyut Joko Rivai,

@BuyutJokoRivai dal momento che è un dump solo da tavolo nella maggior parte dei casi dovrebbe andare bene
Ismail Iqbal

Il modo più intelligente tra gli altri sul caso <3
Nam G VU

Sebbene con un grande tavolo, scaricherai tutte le righe per il grep, che è il caso della trappola per la tua soluzione. Quindi, la query modo in cui e memorizza il risultato in una tabella a discarica come qui stackoverflow.com/a/12816187/248616 è più suiteable
Nam G VU

5

Ho provato a scrivere una procedura facendo ciò, basata sui codici @PhilHibbs, in un modo diverso. Si prega di dare un'occhiata e testare.

 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;

E poi :

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

testato sul mio Postgres 9.1, con una tabella con tipo di dati di campo misto (testo, doppio, int, timestamp senza fuso orario, ecc.).

Ecco perché è necessario il cast in tipo TEXT. Il mio test ha funzionato correttamente per circa 9 milioni di righe, sembra che fallisca poco prima di 18 minuti di esecuzione.

ps: ho trovato un equivalente per mysql sul WEB.


3

È possibile visualizzare la tabella con record specifici e quindi scaricare il file sql

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

3
L'ho provato in pgAdmin III, ma per l'oggetto View non esiste alcuna opzione per il dumping.
null

Prova navicat. Lo sto usando e ha l'opzione di script sql di esportazione
Giorgi Peikrishvili,

@Giorgi: esiste una versione freeware?
null,

Non è possibile utilizzare Postgres 9.1
HCarrasko il

2

Ho appena terminato una procedura rapida per farlo. Funziona solo per una singola riga, quindi creo una vista temporanea che seleziona solo la riga desiderata e quindi sostituisco pg_temp.temp_view con la tabella effettiva in cui voglio inserire.

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;

Invocato così:

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

Non ho provato questo contro gli attacchi di iniezione, per favore fatemi sapere se la chiamata quote_literal non è sufficiente per quello.

Funziona anche con colonne che possono essere semplicemente lanciate in :: text e viceversa.

Anche questo è per Greenplum ma non riesco a pensare a un motivo per cui non funzionerebbe su Postgres, CMIIW.


-2

hai provato in pgadmin eseguendo la query con l' " EXECUTE QUERY WRITE RESULT TO FILE " opzione

esporta solo i dati, altrimenti prova come

pg_dump -t view_name DB_name > db.sql

-t opzione utilizzata per ==> Scarica solo tabelle (o viste o sequenze) tabella di corrispondenza, fare riferimento


1
Questo esporterà solo una create viewdichiarazione
cdmckay
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.