colemar

Dump user table data in INSERT format in Oracle

May 16th, 2014
339
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. DROP PACKAGE DATA2INSERT;
  2.  
  3. --------------------------------------------------------------------------------
  4. CREATE PACKAGE DATA2INSERT IS
  5.  
  6. /*
  7.   Dump user table data in INSERT format.
  8.  
  9.   Any Oracle database version 9 or above should be fine.
  10.  
  11.   Usage:
  12.     select * from table(DATA2INSERT.TAB2INSERT(...));
  13.     select * from table(DATA2INSERT.TABLIST2INSERT(...));
  14.  
  15.     This will be most likely found embedded between SPOOL commands inside a SQL
  16.     script for SQL*Plus.
  17.     Or perhaps used in a Korn shell script containing something like the following:
  18.       #!/usr/bin/ksh
  19.       $ORACLE_HOME/bin/sqlplus -s << SQLEND
  20.       connect user/password@dbname
  21.       set pagesize 0 linesize 9999 tab off feedback off
  22.       select * from table(DATA2INSERT.TAB2INSERT('TABLENAME'[,parameters ...]));
  23.       SQLEND
  24.     Then you can redirect the output to your taste:
  25.       myscript.ksh > mydumpfile.sql
  26.  
  27.   This package should not be used in a context where the input values (function
  28.   parameters) cannot be trusted. In other words: beware of SQL injection!
  29.  
  30.   Copyright (C) Marco Coletti, marco.coletti<replace this with the snail>it.telecomitalia.it
  31.  
  32.   This program is free software: you can redistribute it and/or modify
  33.   it under the terms of the GNU General Public License as published by
  34.   the Free Software Foundation, either version 3 of the License, or
  35.   (at your option) any later version.
  36.  
  37.   This program is distributed in the hope that it will be useful,
  38.   but WITHOUT ANY WARRANTY; without even the implied warranty of
  39.   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  40.   GNU General Public License for more details.
  41.  
  42.   You should have received a copy of the GNU General Public License
  43.   along with this program.  If not, see <http://www.gnu.org/licenses/>.
  44. */
  45.  
  46.   TYPE STRTABLE IS TABLE OF VARCHAR2(32767);
  47.  
  48.   debug BOOLEAN := FALSE;
  49.  
  50.   /*
  51.     Accepts a current user table name.
  52.     Returns a one-column rowset representing data of the given table as a
  53.     sequence of SQL INSERT statements.
  54.     The rows are issued in no particular order.
  55.  
  56.     The output format is meant to be immediately executable SQL.
  57.  
  58.     Usage:
  59.       select * from table(DATA2INSERT.TAB2INSERT('TABLENAME'[,parameters ...]));
  60.  
  61.     Parameters:
  62.       p_table_name:
  63.         The name of any table in the current user schema.
  64.       p_commit_interval:
  65.         N>0 means that a commit statement will be issued every N rows, with a
  66.         final commit.
  67.         Zero means no commit statements, not even a final commit.
  68.         Null means only a final commit, and is the default.
  69.       p_ddl:
  70.         Any value means that a DDL CREATE statement for the given table will be
  71.         issued first.
  72.         Null means no DDL statement and is the default.
  73.       p_where_clause:
  74.         Data filter: this string will be evaluated in the context of the SQL
  75.         statement [select ... from <p_table_name> where <p_where_clause>],
  76.         determining which table rows are to be issued in the output rowset.
  77.         The default is null, that is no where clause, hence no filter.
  78.   */
  79.   FUNCTION TAB2INSERT (
  80.     p_table_name      IN VARCHAR2
  81.    ,p_commit_interval IN PLS_INTEGER DEFAULT NULL
  82.    ,p_ddl             IN VARCHAR2 DEFAULT NULL
  83.    ,p_where_clause    IN VARCHAR2 DEFAULT NULL )
  84.     RETURN STRTABLE pipelined;
  85.  
  86.   /*
  87.     Accepts a csv list of current user table names.
  88.     Returns a one-column rowset representing the data of the given tables as a
  89.     sequence of SQL INSERT statements.
  90.  
  91.     The output format is like that of the function TAB2INSERT.
  92.     The order of tables as given is honored.
  93.  
  94.     Usage:
  95.       select * from table(DATA2INSERT.TABLIST2INSERT('TABLE1,TABLE2,...'[,parameters ...]));
  96.  
  97.     Parameters:
  98.       p_tablist:
  99.         A comma separated list of names of tables in the current user schema.
  100.       p_commit_interval:
  101.         Like the homonymous parameter of the function TAB2INSERT.
  102.       p_ddl:
  103.         Like the homonymous parameter of the function TAB2INSERT.
  104.   */
  105.   FUNCTION TABLIST2INSERT (
  106.     p_tablist IN VARCHAR2
  107.    ,p_commit_interval IN PLS_INTEGER DEFAULT NULL
  108.    ,p_ddl IN VARCHAR2 DEFAULT NULL )
  109.     RETURN STRTABLE pipelined;
  110.  
  111. END DATA2INSERT;
  112. /
  113. show errors
  114.  
  115. --------------------------------------------------------------------------------
  116. CREATE PACKAGE BODY DATA2INSERT IS
  117.  
  118.   ------------------------------------------------------------------------------
  119.   FUNCTION TAB2INSERT (
  120.     p_table_name IN VARCHAR2
  121.    ,p_commit_interval IN PLS_INTEGER DEFAULT NULL
  122.    ,p_ddl IN VARCHAR2 DEFAULT NULL
  123.    ,p_where_clause IN VARCHAR2 DEFAULT NULL )
  124.     RETURN STRTABLE pipelined
  125.   IS
  126.     column_list LONG;
  127.     insertable_value LONG;
  128.     value_list LONG;
  129.     sql_text LONG;
  130.     separator VARCHAR2(9);
  131.     cur sys_refcursor;
  132.     insert_statement LONG;
  133.     commit_counter PLS_INTEGER := 0;
  134.   BEGIN
  135.  
  136.     FOR c IN (
  137.       SELECT COLUMN_NAME, DATA_TYPE
  138.       FROM USER_TAB_COLUMNS
  139.       WHERE TABLE_NAME = UPPER(p_table_name)
  140.       ORDER BY DATA_TYPE )
  141.     LOOP
  142.  
  143.       separator := CASE WHEN column_list IS NULL THEN NULL ELSE ',' END;
  144.       column_list := column_list || separator || c.COLUMN_NAME;
  145.  
  146.       CASE
  147.         WHEN c.DATA_TYPE IN ('NUMBER','FLOAT','BINARY_DOUBLE') THEN
  148.           insertable_value := 'decode(' || c.COLUMN_NAME || ',null,''null'',' || c.COLUMN_NAME || ')';
  149.         WHEN c.DATA_TYPE IN ('VARCHAR2','CHAR') THEN
  150.           insertable_value := '''''''''||replace(' || c.COLUMN_NAME || ','''''''','''''''''''')||''''''''';
  151.         WHEN c.DATA_TYPE LIKE 'TIMESTAMP%' THEN
  152.           insertable_value := 'decode(' || c.COLUMN_NAME || ',null,''null'',''to_timestamp(''''''||to_char(' || c.COLUMN_NAME || ',''yyyymmddhh24missff'')||'''''',''''yyyymmddhh24missff'''')'')';
  153.         WHEN c.DATA_TYPE = 'DATE' THEN
  154.           insertable_value := 'decode(' || c.COLUMN_NAME || ',null,''null'',''to_date(''''''||to_char(' || c.COLUMN_NAME || ',''yyyymmddhh24miss'')||'''''',''''yyyymmddhh24miss'''')''';
  155.         ELSE
  156.           insertable_value := 'unknown_data_type';
  157.       END CASE;
  158.  
  159.       separator := CASE WHEN value_list IS NULL THEN NULL ELSE '||'',''||' END;
  160.       value_list := value_list || separator || insertable_value;
  161.  
  162.     END LOOP;
  163.  
  164.     -- build a dynamic select statement to extract data in INSERT format from the given user table
  165.     sql_text := 'select ''insert into ' || p_table_name ||
  166.                 ' (' || column_list ||
  167.                 ') values (''||' || value_list ||
  168.                 '||'');'' as INSERT_STATEMENT from ' || p_table_name ||
  169.                 CASE WHEN p_where_clause IS NOT NULL THEN ' where ' || p_where_clause END;
  170.     sql_text := REPLACE(sql_text,'''||''',''); -- remove redundant concatenation between VARCHAR2 type literals
  171.  
  172.     IF p_ddl IS NOT NULL THEN
  173.       pipe ROW (dbms_metadata.get_ddl('TABLE',UPPER(p_table_name),USER) || ';');
  174.     END IF;
  175.  
  176.     IF debug THEN
  177.       pipe ROW (sql_text);
  178.     ELSE
  179.       OPEN cur FOR sql_text;
  180.       LOOP -- generate INSERT statements from data of the given table
  181.         FETCH cur INTO insert_statement;
  182.         EXIT WHEN cur%NOTFOUND;
  183.         pipe ROW (insert_statement);
  184.         commit_counter := MOD(commit_counter + 1, p_commit_interval);
  185.         IF commit_counter = 0 THEN
  186.           pipe ROW ('commit;');
  187.         END IF;
  188.       END LOOP;
  189.       IF commit_counter = 0 -- there is already a final commit
  190.          OR p_commit_interval = 0 -- caller asked for zero commit
  191.       THEN
  192.         NULL;
  193.       ELSE
  194.         pipe ROW ('commit;'); -- final commit
  195.       END IF;
  196.     END IF;
  197.  
  198.     RETURN;
  199.  
  200.   END TAB2INSERT;
  201.  
  202.   ------------------------------------------------------------------------------
  203.   FUNCTION TABLIST2INSERT (
  204.     p_tablist IN VARCHAR2
  205.    ,p_commit_interval IN PLS_INTEGER DEFAULT NULL
  206.    ,p_ddl IN VARCHAR2 DEFAULT NULL )
  207.     RETURN STRTABLE pipelined
  208.   IS
  209.   BEGIN
  210.  
  211.     FOR c IN (
  212.       SELECT TABLE_NAME
  213.       FROM USER_TABLES
  214.       WHERE ','||UPPER(p_tablist)||',' LIKE '%,'||TABLE_NAME||',%'
  215.       ORDER BY INSTR(','||UPPER(p_tablist)||',',','||TABLE_NAME||',') )
  216.     LOOP
  217.  
  218.       pipe ROW ('-- '||c.TABLE_NAME);
  219.  
  220.       FOR d IN ( SELECT COLUMN_VALUE FROM TABLE(TAB2INSERT(c.TABLE_NAME,p_commit_interval,p_ddl)) )
  221.       LOOP
  222.         pipe ROW (d.COLUMN_VALUE);
  223.       END LOOP;
  224.  
  225.     END LOOP;
  226.  
  227.     RETURN;
  228.  
  229.   END TABLIST2INSERT;
  230.  
  231. END DATA2INSERT;
  232. /
  233. show errors
Add Comment
Please, Sign In to add comment