ORACLE - 生成插入声明

时间:2013-12-10 16:55:08

标签: oracle insert

以下函数生成SELECT以生成Oracle表记录的INSERT STATEMENT:

CREATE OR REPLACE FUNCTION GEN_INSERT_STATEMENT (IN_TABLE_NAME VARCHAR2)
   RETURN CLOB
IS
   LC$COLS_SELECT   CLOB;
   LC$COLS_VALUES   CLOB;
   LC$COLOUMN       CLOB;

   CURSOR LCUR$TAB_COLUMNS (IN_TABLE_NAME VARCHAR2)
   IS
        SELECT   COLUMN_NAME, DATA_TYPE, COLUMN_ID
          FROM   USER_TAB_COLS
         WHERE   TABLE_NAME = IN_TABLE_NAME
      ORDER BY   COLUMN_ID;
BEGIN
   FOR LREC$TAB_COLUMNS IN LCUR$TAB_COLUMNS (UPPER (IN_TABLE_NAME))
   LOOP
      LC$COLS_SELECT :=
            LC$COLS_SELECT
         || CASE LREC$TAB_COLUMNS.COLUMN_ID WHEN 1 THEN '' ELSE ',' END
         || LREC$TAB_COLUMNS.COLUMN_NAME;

      IF INSTR (LREC$TAB_COLUMNS.DATA_TYPE, 'CHAR') > 0
      THEN
         LC$COLOUMN :=
               '''''''''||REPLACE('
            || LREC$TAB_COLUMNS.COLUMN_NAME
            || ','''''''','''''''''''')||''''''''';
      ELSIF INSTR (LREC$TAB_COLUMNS.DATA_TYPE, 'DATE') > 0
      THEN
         LC$COLOUMN :=
            '''TO_DATE(''''''||TO_CHAR(' || LREC$TAB_COLUMNS.COLUMN_NAME
            || ',''mm/dd/yyyy hh24:mi:ss'')||'''''',''''mm/dd/yyyy hh24:mi:ss'''')''';
      ELSE
         LC$COLOUMN := LREC$TAB_COLUMNS.COLUMN_NAME;
      END IF;

      LC$COLS_VALUES :=
            LC$COLS_VALUES
         || CASE LREC$TAB_COLUMNS.COLUMN_ID WHEN 1 THEN '' ELSE ',' END
         || '''||DECODE('
         || LREC$TAB_COLUMNS.COLUMN_NAME
         || ',NULL,''NULL'','
         || LC$COLOUMN
         || ')||''';
   END LOOP;

   RETURN    'SELECT ''INSERT INTO '
          || IN_TABLE_NAME
          || ' ('
          || LC$COLS_SELECT
          || ') VALUES ('
          || LC$COLS_VALUES
          || ');'' FROM '
          || IN_TABLE_NAME
          || ';';
END;
/

问题是这个函数不处理存在一些VARCHAR2字段的字符结尾的字符串:CHR(0)

用法:

SELECT GEN_INSERT_STATEMENT ('MY_ORACLE_TABLE_NAME') FROM DUAL;

...生成一个SELECT以生成INSERT语句。

如果在VARCHAR2字段中,值以CHR(0)结尾,则INSERT语句将被截断到CHR(0)所在的确切位置。

我该如何解决这个问题?

2 个答案:

答案 0 :(得分:2)

如果我理解你所看到的内容,你需要从值中删除空字符:

  IF INSTR (LREC$TAB_COLUMNS.DATA_TYPE, 'CHAR') > 0
  THEN
     LC$COLOUMN :=
           '''''''''||REPLACE(REPLACE('
        || LREC$TAB_COLUMNS.COLUMN_NAME
        || ',CHR(0),NULL),'''''''','''''''''''')||''''''''';

为您的函数提供输出:

SELECT 'INSERT INTO T42 (STR) VALUES ('||DECODE(STR,NULL,'NULL',''''||REPLACE(REPLACE(STR,CHR(0),NULL),'''','''''')||'''')||');' FROM T42;

并使用名为t42的虚拟表,其中包含str的单个列'hello'后跟一个空字符,输出为:

INSERT INTO T42 (STR) VALUES ('Hello');

或者在插入过程中保留它:

     LC$COLOUMN :=
           '''''''''||REPLACE(REPLACE('
        || LREC$TAB_COLUMNS.COLUMN_NAME
        || ','''''''',''''''''''''),CHR(0),''''''||CHR(0)||'''''')||''''''''';

给出:

SELECT 'INSERT INTO T42 (STR) VALUES ('||DECODE(STR,NULL,'NULL',''''||REPLACE(REPLACE(STR,'''',''''''),CHR(0),'''||CHR(0)||''')||'''')||');' FROM T42;

最后:

INSERT INTO T42 (STR) VALUES ('Hello'||CHR(0)||'');

所以在第二个版本中,空字符从固定字符串中移除(在任何地方,而不仅仅是在结尾处),并作为插入语句的一部分放回。

这似乎是一种可怕的方法,当您可以导出数据时,或者让SQL Developer或其他IDE为您生成插入语句。可能还有其他数据类型和值让您感到头疼,而其他人已经努力克服这些问题。除非你真的需要能够看到实际的陈述,否则使用expdp会更简单。

答案 1 :(得分:1)

使用此:

用法:

select fn_gen_inserts('select * from tablename', 'p_new_owner_name', 'p_new_table_name')
from dual;

其中:

p_sql            –  dynamic query which will be used to export metadata rows
p_new_owner_name – owner name which will be used for generated INSERT
p_new_table_name – table name which will be used for generated INSERT

您可以在此处找到原始源代码: