Exportar filas específicas de una tabla PostgreSQL como INSERT SQL script


196

Tengo un esquema de base de datos llamado: nyummyy una tabla llamada 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)
);

Quiero exportar los cimorydatos de la tabla como insertar un archivo de script SQL. Sin embargo, solo quiero exportar registros / datos donde la ciudad es igual a 'tokio' (supongamos que los datos de la ciudad están en minúsculas).

¿Cómo hacerlo?

No importa si la solución está en herramientas GUI gratuitas o en la línea de comandos (aunque la solución de herramientas GUI es mejor). Intenté pgAdmin III, pero no puedo encontrar una opción para hacerlo.


2
puede omitir las instrucciones INSERT y simplemente copiar usando SELECT directamente entre las bases de datos. albertech.blogspot.com/2016/11/…
jar

PostgreSQL no puede seleccionar entre bases de datos. Al menos, las versiones anteriores no pueden y tampoco Greenplum, no saben acerca de 9.x.
PhilHibbs

Me doy cuenta de que esto es antiguo, pero solo quería mencionar que es posible seleccionar entre bases de datos usando dblink , que ha estado disponible desde al menos v8.3. Utiliza servidores externos y contenedores de datos externos para conectarse a bases de datos "remotas". Esto funciona si esas bases de datos existen en la misma instancia o en hosts completamente diferentes. Lo he usado bastante para crear vistas materializadas en otras bases de datos para facilitar ciertos informes y tal, y funciona muy bien.
G_Hosa_Phat

Respuestas:


282

Cree una tabla con el conjunto que desea exportar y luego use la utilidad de línea de comandos pg_dump para exportar a un archivo:

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 volcará como comandos de inserción con nombres de columna.

--data-only No volcar el esquema.

Como se comenta a continuación, la creación de una vista en lugar de una tabla evitará la creación de la tabla siempre que sea necesaria una nueva exportación.


3
Muy bien, hasta ahora su solución funciona. Una cosa perdida es que necesito agregar "-U nombre_usuario". También casi tengo éxito con la herramienta ToraSQL, es solo que tiene un error en los datos de fecha y hora en el resultado del script. Si ninguno puede proporcionar una solución de herramienta GUI en 2 días, su respuesta será aceptada
nulo

2
Solo desea compartir con otras personas, también puede usar esta herramienta GUI gratuita: SQL Workbench / J (con el controlador postgreSQL jdbc4), para hacer lo mismo.
nulo

2
Esto sería mucho mejor create view export_view..., ya que la vista se mantendría actualizada con los cambios en la tabla base. Los documentos dicen --table=table: Dump only tables (or **views**...que tenía esperanzas de que esto funcionara, pero lamentablemente arrojar una vista no arroja datos. : P
poshest

1
@poshest Funciona para mí en 9.5. ¿Qué intentaste exactamente?
Clodoaldo Neto

@ClodoaldoNeto oh, está bien genial! Espero poder hacerlo funcionar también. Utilicé la pg_dump --table=my_schema.my_view --data-only --inserts my_db > data.sqlversión 9.5.3, y mi createdeclaración fue la misma que la tuya, excepto create view.... Todo lo que obtengo en la salida son los comentarios y SETdeclaraciones habituales de pg_dump . No estoy seguro de dónde me estoy equivocando.
poshest

176

Para un uso de exportación solo de datosCOPY .
Obtiene un archivo con una fila de tabla por línea como texto sin formato (no INSERTcomandos), es más pequeño y más rápido:

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

Importe lo mismo a otra tabla de la misma estructura en cualquier lugar con:

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

COPYescribe y lee archivos locales en el servidor , a diferencia de los programas cliente como pg_dumpo psqlque leen y escriben archivos locales en el cliente . Si ambos se ejecutan en la misma máquina, no importa mucho, pero lo hace para conexiones remotas.

También existe el \copycomando de psql que:

Realiza una copia frontend (cliente). Esta es una operación que ejecuta un COPYcomando SQL , pero en lugar de que el servidor lea o escriba el archivo especificado, psql lee o escribe el archivo y enruta los datos entre el servidor y el sistema de archivos local. Esto significa que la accesibilidad y los privilegios del archivo son los del usuario local, no el servidor, y no se requieren privilegios de superusuario de SQL.


10
El OP llama específicamente a los datos como insertar archivo de script sql . Supongo que está hablando de insertcomandos, ¿no?
Clodoaldo Neto

1
@Clodoaldo: Puede que tengas razón, en cuyo caso tu respuesta sería mejor. También se podría copiar el script CREATE en pgAdmin por separado (como el OP menciona las GUI).
Erwin Brandstetter

3
STDINy STDOUTse puede usar en lugar de la ruta del archivo, útil para pequeñas exportaciones de datos.
Amir Ali Akbari

1
Sin la --column-insertsbandera, pg_dump usa un COPYfrom STDIN para cada una de las tablas en el código SQL que genera.
Randall

2
Tenga cuidado de que el orden de las columnas que SELECCIONA coincida con el orden de las columnas en la base de datos de destino. Si no lo hace, esto podría fallar, o peor aún, tener éxito pero insertar datos incorrectos.
Nathan Wallace

32

Esta es una manera fácil y rápida de exportar una tabla a un script con pgAdmin manualmente sin instalaciones adicionales :

  1. Haga clic derecho en la tabla de destino y seleccione "Copia de seguridad".
  2. Seleccione una ruta de archivo para almacenar la copia de seguridad. Como formato, elija "Normal".
  3. Abra la pestaña "Opciones de volcado # 2" en la parte inferior y marque "Usar inserciones de columna".
  4. Haga clic en el botón Copia de seguridad.
  5. Si abre el archivo resultante con un lector de texto (p. Ej., Notepad ++) obtendrá un script para crear toda la tabla. Desde allí, simplemente puede copiar las instrucciones INSERT generadas.

Este método también funciona con la técnica de hacer una export_table como se demuestra en la respuesta de @Clodoaldo Neto.

Haga clic derecho en la tabla de destino y elija "Copia de seguridad"

Elija una ruta de destino y cambie el formato a "Normal"

Abra la pestaña "Opciones de volcado # 2" en la parte inferior y marque "Usar inserciones de columna"

Puede copiar las instrucciones INSERT desde allí.


Cuando hago esto, no hay opción "Bakckup". Esto es pgAdmin III v1.18.1 que se conecta a Greenplum 4.3.4.1 (basado en PostgreSQL 8.2.15).
PhilHibbs

He instalado pgAdmin III v1.18.1 y no era la opción "copia de seguridad". Me conecté a un PostgreSQL 9.5. Entonces, el problema es más probable entre pgAdmin y Greenplum.
Andi R

Funciona según lo previsto en pgAdmin4
Nikhil

9

SQL Workbench tiene tal característica.

Después de ejecutar una consulta, haga clic derecho en los resultados de la consulta y elija "Copiar datos como SQL> Insertar SQL"


1
Funciona muy bien Cuando elige 'postgres' como 'controlador', es probable que tenga que descargar los controladores JDBC usted mismo: jdbc.postgresql.org/download.html (es un archivo .jar - binario java) y agregarlo como el 'driver' de la conexión postgresql. La cadena de conexión (o URL como en la interfaz) debería verse así: jdbc: postgresql: //127.0.0.1: 5432 /
db_name

DBVisualizer tiene una característica similar y excelente que puede copiar a un archivo o directamente al portapapeles.
Noumenon

8

Para mi caso de uso pude simplemente conectar a grep.

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

2
Hay que considerar tener 'tokio' en otro campo.
Buyut Joko Rivai

@BuyutJokoRivai ya que es un volcado de tabla solo en la mayoría de los casos, debería estar bien
Ismail Iqbal

La forma más inteligente entre los demás en el caso <3
Nam G VU

Aunque con una tabla grande, volcará todas las filas para el grep, que es el caso de peligro para su solución. Entonces, la forma en que consultamos y almacenamos el resultado en una tabla para volcar como aquí stackoverflow.com/a/12816187/248616 es más conveniente
Nam G VU

5

Traté de escribir un procedimiento haciendo eso, basado en los códigos @PhilHibbs, de una manera diferente. Por favor, eche un vistazo y prueba.

 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;

Y entonces :

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

probado en mi postgres 9.1, con una tabla con tipos de datos de campo mixto (texto, doble, int, marca de tiempo sin zona horaria, etc.).

Es por eso que se necesita el tipo CAST en TEXT. Mi prueba se ejecutó correctamente durante aproximadamente 9 millones de líneas, parece que falla justo antes de 18 minutos de ejecución.

ps: encontré un equivalente para mysql en la WEB.


3

Puede hacer una vista de la tabla con registros específicos y luego volcar el archivo sql

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

3
Lo probé en pgAdmin III, pero para el objeto Ver, no hay opción para el volcado.
nulo

Prueba navicat. Lo estoy usando y tiene la opción de exportar script SQL
Giorgi Peikrishvili

@Giorgi: ¿hay una versión gratuita?
nulo

No es posible usar Postgres 9.1
HCarrasko

2

Acabo de hacer un procedimiento rápido para hacer esto. Solo funciona para una sola fila, por lo que creo una vista temporal que solo selecciona la fila que quiero, y luego reemplazo pg_temp.temp_view con la tabla real en la que quiero insertar.

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;

Invocado así:

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

No he probado esto contra ataques de inyección, avíseme si la llamada quote_literal no es suficiente para eso.

Además, solo funciona para columnas que simplemente se pueden convertir a :: texto y viceversa.

También esto es para Greenplum, pero no puedo pensar en una razón por la que no funcionaría en Postgres, CMIIW.


-2

¿Has intentado en pgadmin ejecutar consulta con la " EXECUTE QUERY WRITE RESULT TO FILE " opción

solo exporta los datos, de lo contrario intente como

pg_dump -t view_name DB_name > db.sql

-t opción utilizada para ==> Volcar solo tablas (o vistas o secuencias) que coinciden con la tabla, consulte


1
Esto solo exportará una create viewdeclaración
cdmckay
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.