Export specific rows from a PostgreSQL table as INSERT SQL script

后端 未结 9 726
野趣味
野趣味 2020-11-30 17:01

I have a database schema named: nyummy and a table named cimory:

create table nyummy.cimory (
  id numeric(10,0) not null,
  name c         


        
9条回答
  •  挽巷
    挽巷 (楼主)
    2020-11-30 17:04

    I tried to write a procedure doing that, based on @PhilHibbs codes, on a different way. Please have a look and test.

     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[';
    
         <>
         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
         <>
         FOR valrec IN  EXECUTE  selquery
         LOOP
             dumpquery_1 := '';
             IF not found THEN
                 EXIT ;
             END IF;
    
             -- ----------- --
             -- LOOP ARRAY (EACH FIELDS) --
             <>
             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;
    

    And then :

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

    tested on my postgres 9.1, with a table with mixed field datatype (text, double, int,timestamp without time zone, etc).

    That's why the CAST in TEXT type is needed. My test run correctly for about 9M lines, looks like it fail just before 18 minutes of running.

    ps : I found an equivalent for mysql on the WEB.

提交回复
热议问题