以下函数生成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)
所在的确切位置。
我该如何解决这个问题?
答案 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
您可以在此处找到原始源代码: