it-swarm.com.de

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

Ich habe ein Datenbankschema mit dem Namen: nyummy und 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 die Daten der Tabelle cimory als Einfügungs-SQL-Skriptdatei exportieren. Ich möchte jedoch nur Datensätze/Daten exportieren, bei denen die Stadt gleich "tokyo" ist (vorausgesetzt, die Stadtdaten sind alle Kleinbuchstaben).

Wie es geht? 

Es spielt keine Rolle, ob es sich bei der Lösung um Freeware-GUI-Tools oder eine Befehlszeile handelt (obwohl die GUI-Tool-Lösung besser ist). Ich hatte pgAdmin III ausprobiert, aber ich finde keine Option, um dies zu tun.

137
null

Erstellen Sie eine Tabelle mit dem Satz, den Sie exportieren möchten, und verwenden Sie dann das Befehlszeilendienstprogramm pg_dump, um in eine Datei zu exportieren:

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 kein Schema ausgeben.

Wie nachstehend erläutert, kann durch das Erstellen einer Ansicht anstelle einer Tabelle die Erstellung von Tabellen verhindert werden, wenn ein neuer Export erforderlich ist.

226
Clodoaldo Neto

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

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

Import dasselbe zu einer anderen Tabelle derselben Struktur mit:

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

COPY schreibt und liest Dateien lokal auf dem Server, im Gegensatz zu Clientprogrammen wie pg_dump oder psql, die Dateien lokal für den Client lesen und schreiben. Wenn beide auf demselben Computer laufen, ist dies nicht wichtig, aber für Remote-Verbindungen.

Es gibt auch den \copy Befehl von psql das:

Führt eine Frontend-Kopie (Client) aus. Dies ist eine Operation, die eine .__ ausführt. SQL COPY-Befehl, aber anstelle des Servers liest oder schreibt der Bei einer angegebenen Datei liest oder schreibt psql die Datei und leitet die Daten weiter zwischen dem Server und dem lokalen Dateisystem. Dies bedeutet diese Datei Zugriff und Berechtigungen sind die des lokalen Benutzers, nicht der Server und es sind keine SQL-Superuser-Berechtigungen erforderlich.

142

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

  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. Als Format wählen Sie "Normal".
  3. Öffnen Sie den Tab "Dump Options # 2" am unteren Rand und markieren Sie "Use Column Inserts".
  4. Klicken Sie auf die Schaltfläche "Backup". 
  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 die generierten INSERT-Anweisungen einfach kopieren. 

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

 Click right on target table and choose "Backup"

 Choose a destination path and change the format to "Plain"

 Open the tab "Dump Options #2" at the bottom and check "Use Column Inserts"

 You can copy the INSERT Statements from there.

20
Andi R

SQL Workbench hat 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ügung".

9
machinery

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

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

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'
2

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

 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, Timestamp ohne Zeitzone usw.).

Aus diesem Grund wird der Typ CAST in TEXT benötigt ..__ Mein Test wurde für etwa 9 Millionen Zeilen korrekt ausgeführt, und es scheint, als ob er kurz vor 18 Minuten fehlschlägt.

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

0
Vi Shen

Ich habe gerade eine schnelle Prozedur dafür gemacht. Es funktioniert nur für eine einzelne Zeile, also erstelle ich eine temporäre Ansicht, die nur die gewünschte Zeile auswählt und dann die pg_temp.temp_view durch die eigentliche Tabelle ersetzt, 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, ob der quote_literal-Aufruf dafür nicht ausreicht.

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

Dies ist auch für Greenplum, aber ich kann mir keinen Grund dafür vorstellen, warum es auf Postgres, CMIIW, nicht funktionieren würde.

0
PhilHibbs