Oracle - 如何动态创建一个具有多个值的插入

Oracle - How can I create one insert with multiple values dynamically

我想动态地创建一个具有多个值的 INSERT 语句,如下例所示:

INSERT INTO table_name (ID, PARENT, NAME, ENABLED) 
VALUES (1, 't1', 'Test1', 1 ), (2, 't2', 'Test2', 1 ), (3, 't3', 'Test3', 1 );

目前我正在使用以下语句,但现在我收到了太多单独的语句,这并不能提供良好的性能

SELECT 'INSERT INTO table_name(ID, PARENT, NAME, ENABLED) ' 
|| 'VALUES ('|| ID ||','''|| PARENT ||''','''|| NAME || ''', '|| ENABLED ||');'
FROM table_name WHERE ID IN (... [inner select] ...);

如何创建一个循环,将新值附加到像这样的单个插入语句中?

SELECT 'INSERT INTO table_name (ID, PARENT, NAME, ENABLED)' VALUES

DECLARE
    myValues varchar2(500);
    CURSOR myCur IS SELECT ID, PARENT, NAME, ENABLED FROM table_name;
BEGIN
    FOR values IN myCur LOOP

        IF myCur%ROWCOUNT = 1 THEN
            myValues := '('||values.ID ||', '''|| values.PARENT ||''', '''|| values.NAME ||''', '|| values.ENABLED ||'),';
        ELSE
            myValues := '('||values.ID ||', '''|| values.PARENT ||''', '''|| values.NAME ||''', '|| values.ENABLED ||')';
        end if;
    END LOOP;
END;
--...

我需要这个来导出我的数据并使用 sqlplus 插入到另一个数据库中

谢谢大家

在我看来,你应该停止重新发明轮子。 Oracle 提供了数据泵 export/import 实用程序,这些实用程序专为这种目的而设计 - 移动数据。在简单的(或者,我应该说 大多数 )情况下,您甚至可以使用 original export/import 实用程序。

您没有指定您使用的数据库版本 - 这是 12c 数据泵文档:https://docs.oracle.com/database/121/SUTIL/GUID-501A9908-BCC5-434C-8853-9A6096766B5A.htm#SUTIL2877

有很多示例可以说明如何做到这一点。我建议您不要跳过阅读文档并直接跳到 运行 一些代码。了解自己实际在做什么,而不是希望它会正确

,你会受益匪浅

一种方法是使用 XML-Files 进行数据传输。

获取数据为XML:

DECLARE
  l_xml        DBMS_XMLGEN.ctxHandle;
BEGIN
  l_xml := dbms_xmlgen.newContext('SELECT * FROM table_name WHERE ID IN (... [inner select] ...)');
  dbms_output.put_line(dbms_xmlgen.getXML(l_xml));
  dbms_xmlgen.closeContext(l_xml);
END;

插入语句:

INSERT INTO table_name (ID, PARENT, NAME, ENABLED)
SELECT dbms_xmlgen.convert(value(soc).EXTRACT('/ROW/ID/text()'     ).getStringVal(), 1)
     , dbms_xmlgen.convert(value(soc).EXTRACT('/ROW/PARENT/text()' ).getStringVal(), 1)
     , dbms_xmlgen.convert(value(soc).EXTRACT('/ROW/NAME/text()'   ).getStringVal(), 1)
     , dbms_xmlgen.convert(value(soc).EXTRACT('/ROW/ENABLED/text()').getStringVal(), 1)
  FROM TABLE(XMLSequence(EXTRACT(XMLType(<XML>), '/ROWSET/ROW'))) SOC

如果要插入静态递增数据(根据您的原始示例),请将 INSERT INTO ... SELECT 与分层查询一起使用:

INSERT INTO table_name ( id, parent, name, enabled )
  SELECT LEVEL, 't' || LEVEL, 'Test' || LEVEL, 1
  FROM   DUAL
  CONNECT BY LEVEL <= 3

如果您想从现有的 table 构建查询,则:

SELECT 'INSERT INTO table_name ( id, parent, name, enabled )'
       || LISTAGG( 
            'SELECT ' || id || ', '
                    || '''' || REPLACE( parent, '''', '''''' ) || ''', '
                    || '''' || REPLACE( name, '''', '''''' ) || ''', '
                    || enabled
            || ' FROM DUAL',
            ' UNION ALL '
          ) WITHIN GROUP ( ORDER BY ROWNUM )
FROM   table_name

如果要超过 4000 个字符,那么您可以生成多行:

SELECT 'INSERT INTO table_name ( id, parent, name, enabled )' FROM DUAL
UNION ALL
SELECT 'SELECT ' || id || ', '
                 || '''' || REPLACE( parent, '''', '''''' ) || ''', '
                 || '''' || REPLACE( name, '''', '''''' ) || ''', '
                 || enabled
       || ' FROM DUAL'
       || CASE WHEN ROWNUM < COUNT(*) OVER () THEN ' UNION ALL ' END
FROM   table_name

db<>fiddle here

或使用 Oracle 实用程序 RMANExpDP 生成 table.

的备份