Exportieren Sie bestimmte Zeilen aus einer PostgreSQL-Tabelle als INSERT SQL-Skript

196

Ich habe ein Datenbankschema mit dem Namen: nyummyund eine Tabelle mit dem Namen 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)
);

Ich möchte cimorydie Daten der Tabelle als SQL-Skriptdatei einfügen exportieren . Ich möchte jedoch nur Datensätze / Daten exportieren, bei denen die Stadt gleich "Tokio" ist (vorausgesetzt, die Stadtdaten sind alle in Kleinbuchstaben).

Wie es geht?

Es spielt keine Rolle, ob sich die Lösung in Freeware-GUI-Tools oder in der Befehlszeile befindet (obwohl die GUI-Tools-Lösung besser ist). Ich habe pgAdmin III ausprobiert, kann aber keine Option dafür finden.

Null
quelle
2
Sie können die INSERT-Anweisungen überspringen und einfach mit SELECT direkt zwischen den Datenbanken kopieren. albertech.blogspot.com/2016/11/…
jar
PostgreSQL kann nicht datenbankübergreifend auswählen. Zumindest können und können ältere Versionen Greenplum nicht und wissen nichts über 9.x.
PhilHibbs
Ich weiß , das ist alt, aber ich wollte nur sagen , dass es ist möglich , über Datenbanken auszuwählen mit dblink , die seit mindestens v8.3 verfügbar ist. Es verwendet fremde Server und fremde Daten-Wrapper, um eine Verbindung zu "entfernten" Datenbanken herzustellen. Dies funktioniert unabhängig davon, ob diese Datenbanken auf derselben Instanz oder auf völlig unterschiedlichen Hosts vorhanden sind. Ich habe es ziemlich ausgiebig verwendet, um materialisierte Ansichten in anderen Datenbanken zu erstellen, um bestimmte Berichte und dergleichen zu erleichtern, und es funktioniert hervorragend.
G_Hosa_Phat

Antworten:

280

Erstellen Sie eine Tabelle mit dem Satz, den Sie exportieren möchten, und exportieren Sie dann mit dem Befehlszeilenprogramm pg_dump in eine Datei:

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 wird als Einfügebefehle mit Spaltennamen ausgegeben.

--data-only Schema nicht sichern.

Wie unten kommentiert, wird durch das Erstellen einer Ansicht anstelle einer Tabelle die Tabellenerstellung vermieden, wenn ein neuer Export erforderlich ist.

Clodoaldo Neto
quelle
3
Okay, soweit funktioniert Ihre Lösung. Eine Sache, die übersehen wurde, ist, dass ich "-U Benutzername" hinzufügen muss. Ich bin auch fast erfolgreich mit dem ToraSQL-Tool, es ist nur so, dass es Fehler in Datums- und Uhrzeitdaten im Skriptergebnis hat. Wenn niemand innerhalb von 2 Tagen eine GUI-Tool-Lösung anbieten kann, wird Ihre Antwort akzeptiert
null
2
Wenn Sie nur für andere Personen freigeben möchten, können Sie auch dieses kostenlose GUI-Tool verwenden: SQL Workbench / J (mit postgreSQL jdbc4-Treiber), um dasselbe zu tun.
null
1
Dies wäre viel besser create view export_view..., da die Ansicht mit Änderungen an der Basistabelle auf dem neuesten Stand bleiben würde. Die Dokumente sagen, --table=table: Dump only tables (or **views**...dass ich einige Hoffnung hatte, dass dies funktionieren würde, aber das Speichern einer Ansicht liefert leider keine Daten. : P
vornehmster
@poshest Es funktioniert für mich in 9.5. Was genau hast du versucht?
Clodoaldo Neto
@ ClodoaldoNeto oh, OK, großartig! Ich hoffe, ich kann es auch zum Laufen bringen. Ich habe pg_dump --table=my_schema.my_view --data-only --inserts my_db > data.sqlVersion 9.5.3 verwendet, und meine createAussage war dieselbe wie Ihre, außer create view.... Alles, was ich in der Ausgabe bekomme, sind die üblichen pg_dump-Kommentare und -Anweisungen SET. Ich bin mir nicht sicher, wo ich falsch liege.
vornehmster
176

Für einen Nur-Daten-Export verwenden COPY.
Sie erhalten eine Datei mit einer Tabellenzeile pro Zeile als Klartext (keine INSERTBefehle). Sie ist kleiner und schneller:

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

Importieren Sie dasselbe in eine andere Tabelle derselben Struktur an einer beliebigen Stelle mit:

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

COPYschreibt und liest Dateien lokal auf dem Server , im Gegensatz zu Client-Programmen wie pg_dumpoder psqldie Dateien lokal auf dem Client lesen und schreiben . Wenn beide auf demselben Computer ausgeführt werden, spielt dies keine große Rolle, dies gilt jedoch für Remoteverbindungen.

Es gibt auch den \copyBefehl von psql, dass:

Führt eine Frontend-Kopie (Client-Kopie) durch. Dies ist eine Operation, die einen SQL- COPYBefehl ausführt. Statt dass der Server die angegebene Datei liest oder schreibt, liest oder schreibt psql die Datei und leitet die Daten zwischen dem Server und dem lokalen Dateisystem weiter. Dies bedeutet, dass Dateizugriff und Berechtigungen die des lokalen Benutzers und nicht des Servers sind und keine SQL-Superuser-Berechtigungen erforderlich sind.

Erwin Brandstetter
quelle
10
Das OP fordert speziell Daten als SQL-Skriptdatei einfügen an . Ich denke, er spricht über insertBefehle, nicht wahr?
Clodoaldo Neto
1
@ Clodoaldo: Sie haben vielleicht Recht. In diesem Fall passt Ihre Antwort besser. Man könnte das CREATE-Skript auch separat in pgAdmin kopieren (da das OP GUIs erwähnt).
Erwin Brandstetter
3
STDINund STDOUTkann anstelle des Dateipfads verwendet werden, der für den Export kleiner Daten nützlich ist.
Amir Ali Akbari
1
Ohne das --column-insertsFlag verwendet COPYpg_dump für jede der Tabellen im generierten SQL-Code ein from STDIN.
Randall
2
Achten Sie darauf, dass die Reihenfolge der von Ihnen ausgewählten Spalten mit der Reihenfolge der Spalten in der Zieldatenbank übereinstimmt. Wenn dies nicht der Fall ist, kann dies fehlschlagen oder schlimmer noch, aber fehlerhafte Daten einfügen.
Nathan Wallace
32

Dies ist eine einfache und schnelle Möglichkeit, eine Tabelle mit pgAdmin manuell ohne zusätzliche Installationen in ein Skript zu exportieren :

  1. Klicken Sie mit der rechten Maustaste auf die Zieltabelle und wählen Sie "Backup".
  2. Wählen Sie einen Dateipfad zum Speichern der Sicherung. Wählen Sie als Format "Normal".
  3. Öffnen Sie unten die Registerkarte "Dump Options # 2" und aktivieren Sie "Use Column Inserts".
  4. Klicken Sie auf die Schaltfläche Sichern.
  5. Wenn Sie die resultierende Datei mit einem Textleser (z. B. Notepad ++) öffnen, erhalten Sie ein Skript zum Erstellen der gesamten Tabelle. Von dort können Sie einfach die generierten INSERT-Anweisungen kopieren.

Diese Methode funktioniert auch mit der Technik, eine export_table zu erstellen, wie in der Antwort von @Clodoaldo Neto gezeigt.

Klicken Sie rechts auf die Zieltabelle und wählen Sie "Backup".

Wählen Sie einen Zielpfad und ändern Sie das Format in "Normal".

Öffnen Sie unten die Registerkarte "Dump Options # 2" und aktivieren Sie "Use Column Inserts".

Sie können die INSERT-Anweisungen von dort kopieren.

Andi R.
quelle
Wenn ich das mache, gibt es keine "Bakckup" -Option. Dies ist pgAdmin III v1.18.1, das eine Verbindung zu Greenplum 4.3.4.1 herstellt (basierend auf PostgreSQL 8.2.15).
PhilHibbs
Ich habe pgAdmin III v1.18.1 installiert und es gab die Option "Backup". Ich habe mich mit einem PostgreSQL 9.5 verbunden. Das Problem liegt also höchstwahrscheinlich zwischen pgAdmin und dem Greenplum.
Andi R
Funktioniert wie in pgAdmin4
Nikhil vorgesehen
9

SQL Workbench verfügt über eine solche Funktion.

Klicken Sie nach dem Ausführen einer Abfrage mit der rechten Maustaste auf die Abfrageergebnisse und wählen Sie "Daten als SQL kopieren> SQL einfügen".

Maschinen
quelle
1
Es funktioniert großartig. Wenn Sie "postgres" als "Treiber" auswählen, müssen Sie wahrscheinlich die JDBC-Treiber selbst herunterladen: jdbc.postgresql.org/download.html (es ist eine .jar-Datei - Java-Binärdatei) und als "hinzufügen" 'Fahrer' der Postgresql-Verbindung. Die Verbindungszeichenfolge (oder URL wie in der Schnittstelle) sollte folgendermaßen aussehen: jdbc: postgresql: //127.0.0.1: 5432 / db_name
mrmuggles
DBVisualizer verfügt über eine ähnliche und hervorragende Funktion, die in eine Datei oder direkt in die Zwischenablage kopiert werden kann.
Noumenon
8

Für meinen Anwendungsfall konnte ich einfach auf grep pfeifen.

pg_dump -U user_name --data-only --column-inserts -t nyummy.cimory | grep "tokyo" > tokyo.sql
M. Vanderlee
quelle
2
Man muss darüber nachdenken, "Tokio" in einem anderen Bereich zu haben.
Buyut Joko Rivai
@ BuyutJokoRivai, da es in den meisten Fällen nur ein Dump für Tabellen ist, sollte es in Ordnung sein
Ismail Iqbal
Der klügste Weg unter den anderen in dem Fall <3
Nam G VU
Bei einer großen Tabelle werden Sie jedoch alle Zeilen für den grep ausgeben, was der Fall für Ihre Lösung ist. Dann ist die Art und Weise, wie wir Ergebnisse abfragen und in einer Tabelle speichern, um sie wie hier zu speichern , geeigneter
Nam G VU
5

Ich habe versucht, eine Prozedur zu schreiben, die auf @PhilHibbs-Codes basiert, auf eine andere Art und Weise. Bitte schauen Sie und testen Sie.

 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;

Und dann :

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

getestet auf meinem Postgres 9.1 mit einer Tabelle mit gemischtem Felddatentyp (Text, Double, Int, Zeitstempel ohne Zeitzone usw.).

Aus diesem Grund wird der Typ CAST in TEXT benötigt. Mein Testlauf wurde für ungefähr 9 Millionen Zeilen korrekt ausgeführt. Es sieht so aus, als ob er kurz vor 18 Minuten fehlschlägt.

ps: Ich habe im WEB ein Äquivalent für MySQL gefunden.

Vi Shen
quelle
3

Sie können die Tabelle mit bestimmten Datensätzen anzeigen und dann die SQL-Datei sichern

CREATE VIEW foo AS
SELECT id,name,city FROM nyummy.cimory WHERE city = 'tokyo'
Giorgi Peikrishvili
quelle
3
Ich habe es in pgAdmin III versucht, aber für das View-Objekt gibt es keine Option zum Dumping.
null
Versuchen Sie es mit navicat. Ich benutze es und es hat SQL-Skript-Exportoption
Giorgi Peikrishvili
@Giorgi: Gibt es eine Freeware-Version?
null
Es ist nicht möglich mit Postgres 9.1
HCarrasko
2

Ich habe gerade eine schnelle Prozedur durchgeführt, um dies zu tun. Es funktioniert nur für eine einzelne Zeile, daher erstelle ich eine temporäre Ansicht, in der nur die gewünschte Zeile ausgewählt wird, und ersetze dann die pg_temp.temp_view durch die tatsächliche Tabelle, in die ich einfügen möchte.

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;

So aufgerufen:

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

Ich habe dies nicht gegen Injektionsangriffe getestet. Bitte lassen Sie mich wissen, wenn der Aufruf von quote_literal dafür nicht ausreicht.

Es funktioniert auch nur für Spalten, die einfach in :: text und wieder zurück umgewandelt werden können.

Auch dies ist für Greenplum, aber ich kann mir keinen Grund vorstellen, warum es bei Postgres, CMIIW nicht funktionieren würde.

PhilHibbs
quelle
-2

Haben Sie versucht, in pgadmin eine Abfrage mit " EXECUTE QUERY WRITE RESULT TO FILE " Option auszuführen?

Es ist nur der Export der Daten, sonst versuchen Sie es wie

pg_dump -t view_name DB_name > db.sql

-t Option für ==> Dump nur Tabellen (oder Ansichten oder Sequenzen) passende Tabelle, siehe

solaimuruganv
quelle
1
Dies wird nur eine create viewAnweisung exportieren
cdmckay