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 实用程序 RMAN
或 ExpDP
生成 table.
的备份
我想动态地创建一个具有多个值的 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 实用程序 RMAN
或 ExpDP
生成 table.