Oracle - Как я могу создать одну вставку с несколькими значениями динамически - PullRequest
0 голосов
/ 20 мая 2019

Я хочу создать один оператор 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

спасибо всем

Ответы [ 3 ]

2 голосов
/ 20 мая 2019

Используйте INSERT INTO ... SELECT с иерархическим запросом, если вы хотите вставить статические инкрементные данные (согласно исходному примеру):

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

Если вы хотите построить запрос из существующей таблицы, то:

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

дБ <> скрипка здесь

Или используйте утилиты Oracle RMAN или ExpDP для создания резервной копии таблицы.

0 голосов
/ 20 мая 2019

Одним из способов является использование XML-файлов для передачи данных.

Получить данные в формате 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
0 голосов
/ 20 мая 2019

На мой взгляд, вы должны прекратить изобретать велосипед. Oracle предлагает утилиты экспорта / импорта данных, которые предназначены для такой цели - перемещение данных. В простых (или, скажем, большинстве ) случаях вы можете даже использовать оригинальные утилиты экспорта / импорта.

Вы не указали версию базы данных, которую используете, поэтому - вот документация по 12c Data Pump: https://docs.oracle.com/database/121/SUTIL/GUID-501A9908-BCC5-434C-8853-9A6096766B5A.htm#SUTIL2877

Есть немало примеров, которые покажут как сделать это. Я бы посоветовал вам не пропускать чтение документации и переходить прямо к выполнению некоторого кода. Вам было бы полезно знать, что вы на самом деле делаете, вместо того, чтобы надеяться, что оно повернет вправо .

...