立即执行 ORA-00900
execute immediate ORA-00900
我正在尝试从现有 table 创建插入语句。但是,我最终面临 ORA-00900
问题。令人惊讶的是,当我使用 execute immediate
独立执行结果时,它工作正常。
让我们创建 2 tables:
create table a (
name varchar2 (100),
age integer
);
insert into a values ('Tom', 1);
commit;
insert into a values ('John', 2);
commit;
create table b (
name varchar2 (100),
age integer
);
insert into b values ('Jane', 1);
commit;
insert into b values ('Eric', 2);
commit;
现在这是我正在处理以获取数据的块。此块将使用 SQL Plus。命令行参数将是:
SQL> @export.ddl my_schema a,b
现在,我不会在这里写 SET
语句。
/* export.ddl */
declare
p_schema_name varchar2(1000) := upper('&1');
p_table_names varchar2(4000) := upper('&2');
l_statement varchar2(30000);
type tmp_table is table of varchar2(30000);
l_result tmp_table;
begin
for c_table in (
select
regexp_substr (replace(p_table_names, ' ', ''), '[^,]+', 1, level) as t_name
from dual
connect by
regexp_substr (replace(p_table_names, ' ', ''), '[^,]+', 1, level) is not null)
loop
for c_col in (
select
'''select '''||ins.insert_stmt||'('||recs.select_rows||''')'''' stmt from '||recs.owner||'.'||recs.table_name||'''' as statement
from (
select
atc.owner,
atc.table_name,
''||listagg(case when atc.data_type = 'VARCHAR2' then '''''||decode('||atc.column_name||', null, ''''null'''', ''''''''''''''''||'||atc.column_name||'||'''''''''''''''')||'''
when atc.data_type = 'NUMBER' then '''''||decode('||atc.column_name||', null, ''''null'''', '||atc.column_name||')||'''
when atc.data_type = 'DATE' then 'to_date(''''''||to_char('||atc.column_name||', ''DD-MON-YYYY HH24:MI:SS'')||'''''', ''''DD-MON-YYYY HH24:MI:SS'''')'
end, ''', ') within group (order by atc.column_id) as select_rows
from dba_tab_columns atc
where atc.table_name in (c_table.t_name) -- here
group by atc.owner, atc.table_name) recs,
(
select
atc.owner,
atc.table_name,
'''insert into '||atc.owner||'.'||atc.table_name||' ('||listagg(atc.column_name, ', ') within group (order by atc.column_id)||') VALUES ' as insert_stmt
from all_tab_columns atc
where atc.table_name in (c_table.t_name) -- here
group by atc.owner, atc.table_name
) ins
where recs.owner = ins.owner
and recs.table_name = ins.table_name)
loop
l_statement := c_col.statement;
dbms_output.put_line(l_statement);
execute immediate l_statement bulk collect into l_result;
for i in 1 .. l_result.count() loop
dbms_output.put_line(l_result(i));
end loop;
end loop;
end loop;
end;
在这段代码中我遇到了:
ORA-00900: invalid SQL statement
ORA-06512: at line 44
这是执行立即语句的行号。
但是,如果我仅复制 dbms_output(注释掉执行立即语句和后续循环),即:
'select ''insert into MY_SCHEMA.A (NAME, AGE) VALUES (''||decode(NAME, null, ''null'', ''''''''||NAME||'''''''')||'', ''||decode(AGE, null, ''null'', AGE)||'')'' stmt from MY_SCHEMA.A'
'select ''insert into MY_SCHEMA.B (NAME, AGE) VALUES (''||decode(NAME, null, ''null'', ''''''''||NAME||'''''''')||'', ''||decode(AGE, null, ''null'', AGE)||'')'' stmt from MY_SCHEMA.B'
并像这样使用它:
/* second.ddl */
declare
l_statememt varchar2(30000);
type typ_varcharlist IS TABLE OF VARCHAR2(30000);
col_list typ_varcharlist;
statemement varchar2(30000) := 'select ''insert into MY_SCHEMA.A (NAME, AGE) VALUES (''||decode(NAME, null, ''null'', ''''''''||NAME||'''''''')||'', ''||decode(AGE, null, ''null'', AGE)||'')'' stmt from MY_SCHEMA.A';
begin
execute immediate statemement bulk collect into col_list;
for i in 1 .. col_list.count() loop
dbms_output.put_line(col_list(i));
end loop;
end;
然后我得到所需的输出是:
insert into MY_SCHEMA.A (NAME, AGE) VALUES ('Tom', 1)
insert into MY_SCHEMA.A (NAME, AGE) VALUES ('John', 2)
我的问题是:
为什么立即执行在第一个代码中给我错误(export.ddl)?我能做些什么来防止它,并使自己免于执行第二步 (second.ddl)?
这意味着,使用一个脚本来获取在比方说 insert.ddl 脚本中的插入语句。
提前致谢:-)
如果您只想生成插入语句(不完全是这种方式),在 SQLDeveloper 中有一个函数可以生成插入语句。您只需左键单击 table> 导出,然后取消选中 "EXPORT DDL"。 Next> 接下来,您有纯 SQL Insert 语句。
您输入了太多(转义)引号。您从 dbms_output
看到的生成语句是
'select ''insert into MY_SCHEMA.A (NAME, AGE) VALUES (''||decode(NAME, null, ''null'', ''''''''||NAME||'''''''')||'', ''||decode(AGE, null, ''null'', AGE)||'')'' stmt from MY_SCHEMA.A'
当您 运行 在第二个块中将其视为字符串文字时,当您将其分配给 statemement
变量时 - 并且该分配有效地取消了所有转义引号.当您 运行 它直接在第一个块中时,开盘价和收盘价无效。或者换句话说,复制该输出(包括那些引号)并将其作为 SQL 语句直接粘贴到 SQL*Plus - 然后您 将 看到ORA-00900.
仅仅移除最外面的那些是不够的;只删除那些,i.er。变化
'''select '''||ins.insert_stmt||'('||recs.select_rows||''')'''' stmt from '||recs.owner||'.'||recs.table_name||'''' as statement
至
'select '''||ins.insert_stmt||'('||recs.select_rows||''')'' stmt from '||recs.owner||'.'||recs.table_name||'' as statement
...它得到 "ORA-00923: FROM keyword not found where expected"。要摆脱它,您需要从 insert_smt
中删除多余的引号,并且在 stmt
:
之前关闭
'select '''||ins.insert_stmt||'('||recs.select_rows||''')'' stmt from '||recs.owner||'.'||recs.table_name||'' as statement
和
'insert into '||atc.owner||'.'||atc.table_name||' ('||listagg(atc.column_name, ', ') within group (order by atc.column_id)||') VALUES ' as insert_stmt
... 现在 运行,但不会产生您想要的输出:
PL/SQL procedure successfully completed.
select 'insert into MYSCHEMA.A (NAME, AGE) VALUES (''||decode(NAME, null, ''null'', ''''''''||NAME||'''''''')||'', ''||decode(AGE, null, ''null'', AGE)||'')' stmt from MYSCHEMA.A
insert into MYSCHEMA.A (NAME, AGE) VALUES ('||decode(NAME, null, 'null', ''''||NAME||'''')||', '||decode(AGE, null, 'null', AGE)||')
insert into MYSCHEMA.A (NAME, AGE) VALUES ('||decode(NAME, null, 'null', ''''||NAME||'''')||', '||decode(AGE, null, 'null', AGE)||')
select 'insert into MYSCHEMA.B (NAME, AGE) VALUES (''||decode(NAME, null, ''null'', ''''''''||NAME||'''''''')||'', ''||decode(AGE, null, ''null'', AGE)||'')' stmt from Whosebug.B
insert into MYSCHEMA.B (NAME, AGE) VALUES ('||decode(NAME, null, 'null', ''''||NAME||'''')||', '||decode(AGE, null, 'null', AGE)||')
insert into MYSCHEMA.B (NAME, AGE) VALUES ('||decode(NAME, null, 'null', ''''||NAME||'''')||', '||decode(AGE, null, 'null', AGE)||')
您还需要删除许多其他转义引号。
我正在尝试从现有 table 创建插入语句。但是,我最终面临 ORA-00900
问题。令人惊讶的是,当我使用 execute immediate
独立执行结果时,它工作正常。
让我们创建 2 tables:
create table a (
name varchar2 (100),
age integer
);
insert into a values ('Tom', 1);
commit;
insert into a values ('John', 2);
commit;
create table b (
name varchar2 (100),
age integer
);
insert into b values ('Jane', 1);
commit;
insert into b values ('Eric', 2);
commit;
现在这是我正在处理以获取数据的块。此块将使用 SQL Plus。命令行参数将是:
SQL> @export.ddl my_schema a,b
现在,我不会在这里写 SET
语句。
/* export.ddl */
declare
p_schema_name varchar2(1000) := upper('&1');
p_table_names varchar2(4000) := upper('&2');
l_statement varchar2(30000);
type tmp_table is table of varchar2(30000);
l_result tmp_table;
begin
for c_table in (
select
regexp_substr (replace(p_table_names, ' ', ''), '[^,]+', 1, level) as t_name
from dual
connect by
regexp_substr (replace(p_table_names, ' ', ''), '[^,]+', 1, level) is not null)
loop
for c_col in (
select
'''select '''||ins.insert_stmt||'('||recs.select_rows||''')'''' stmt from '||recs.owner||'.'||recs.table_name||'''' as statement
from (
select
atc.owner,
atc.table_name,
''||listagg(case when atc.data_type = 'VARCHAR2' then '''''||decode('||atc.column_name||', null, ''''null'''', ''''''''''''''''||'||atc.column_name||'||'''''''''''''''')||'''
when atc.data_type = 'NUMBER' then '''''||decode('||atc.column_name||', null, ''''null'''', '||atc.column_name||')||'''
when atc.data_type = 'DATE' then 'to_date(''''''||to_char('||atc.column_name||', ''DD-MON-YYYY HH24:MI:SS'')||'''''', ''''DD-MON-YYYY HH24:MI:SS'''')'
end, ''', ') within group (order by atc.column_id) as select_rows
from dba_tab_columns atc
where atc.table_name in (c_table.t_name) -- here
group by atc.owner, atc.table_name) recs,
(
select
atc.owner,
atc.table_name,
'''insert into '||atc.owner||'.'||atc.table_name||' ('||listagg(atc.column_name, ', ') within group (order by atc.column_id)||') VALUES ' as insert_stmt
from all_tab_columns atc
where atc.table_name in (c_table.t_name) -- here
group by atc.owner, atc.table_name
) ins
where recs.owner = ins.owner
and recs.table_name = ins.table_name)
loop
l_statement := c_col.statement;
dbms_output.put_line(l_statement);
execute immediate l_statement bulk collect into l_result;
for i in 1 .. l_result.count() loop
dbms_output.put_line(l_result(i));
end loop;
end loop;
end loop;
end;
在这段代码中我遇到了:
ORA-00900: invalid SQL statement
ORA-06512: at line 44
这是执行立即语句的行号。
但是,如果我仅复制 dbms_output(注释掉执行立即语句和后续循环),即:
'select ''insert into MY_SCHEMA.A (NAME, AGE) VALUES (''||decode(NAME, null, ''null'', ''''''''||NAME||'''''''')||'', ''||decode(AGE, null, ''null'', AGE)||'')'' stmt from MY_SCHEMA.A'
'select ''insert into MY_SCHEMA.B (NAME, AGE) VALUES (''||decode(NAME, null, ''null'', ''''''''||NAME||'''''''')||'', ''||decode(AGE, null, ''null'', AGE)||'')'' stmt from MY_SCHEMA.B'
并像这样使用它:
/* second.ddl */
declare
l_statememt varchar2(30000);
type typ_varcharlist IS TABLE OF VARCHAR2(30000);
col_list typ_varcharlist;
statemement varchar2(30000) := 'select ''insert into MY_SCHEMA.A (NAME, AGE) VALUES (''||decode(NAME, null, ''null'', ''''''''||NAME||'''''''')||'', ''||decode(AGE, null, ''null'', AGE)||'')'' stmt from MY_SCHEMA.A';
begin
execute immediate statemement bulk collect into col_list;
for i in 1 .. col_list.count() loop
dbms_output.put_line(col_list(i));
end loop;
end;
然后我得到所需的输出是:
insert into MY_SCHEMA.A (NAME, AGE) VALUES ('Tom', 1)
insert into MY_SCHEMA.A (NAME, AGE) VALUES ('John', 2)
我的问题是: 为什么立即执行在第一个代码中给我错误(export.ddl)?我能做些什么来防止它,并使自己免于执行第二步 (second.ddl)?
这意味着,使用一个脚本来获取在比方说 insert.ddl 脚本中的插入语句。
提前致谢:-)
如果您只想生成插入语句(不完全是这种方式),在 SQLDeveloper 中有一个函数可以生成插入语句。您只需左键单击 table> 导出,然后取消选中 "EXPORT DDL"。 Next> 接下来,您有纯 SQL Insert 语句。
您输入了太多(转义)引号。您从 dbms_output
看到的生成语句是
'select ''insert into MY_SCHEMA.A (NAME, AGE) VALUES (''||decode(NAME, null, ''null'', ''''''''||NAME||'''''''')||'', ''||decode(AGE, null, ''null'', AGE)||'')'' stmt from MY_SCHEMA.A'
当您 运行 在第二个块中将其视为字符串文字时,当您将其分配给 statemement
变量时 - 并且该分配有效地取消了所有转义引号.当您 运行 它直接在第一个块中时,开盘价和收盘价无效。或者换句话说,复制该输出(包括那些引号)并将其作为 SQL 语句直接粘贴到 SQL*Plus - 然后您 将 看到ORA-00900.
仅仅移除最外面的那些是不够的;只删除那些,i.er。变化
'''select '''||ins.insert_stmt||'('||recs.select_rows||''')'''' stmt from '||recs.owner||'.'||recs.table_name||'''' as statement
至
'select '''||ins.insert_stmt||'('||recs.select_rows||''')'' stmt from '||recs.owner||'.'||recs.table_name||'' as statement
...它得到 "ORA-00923: FROM keyword not found where expected"。要摆脱它,您需要从 insert_smt
中删除多余的引号,并且在 stmt
:
'select '''||ins.insert_stmt||'('||recs.select_rows||''')'' stmt from '||recs.owner||'.'||recs.table_name||'' as statement
和
'insert into '||atc.owner||'.'||atc.table_name||' ('||listagg(atc.column_name, ', ') within group (order by atc.column_id)||') VALUES ' as insert_stmt
... 现在 运行,但不会产生您想要的输出:
PL/SQL procedure successfully completed.
select 'insert into MYSCHEMA.A (NAME, AGE) VALUES (''||decode(NAME, null, ''null'', ''''''''||NAME||'''''''')||'', ''||decode(AGE, null, ''null'', AGE)||'')' stmt from MYSCHEMA.A
insert into MYSCHEMA.A (NAME, AGE) VALUES ('||decode(NAME, null, 'null', ''''||NAME||'''')||', '||decode(AGE, null, 'null', AGE)||')
insert into MYSCHEMA.A (NAME, AGE) VALUES ('||decode(NAME, null, 'null', ''''||NAME||'''')||', '||decode(AGE, null, 'null', AGE)||')
select 'insert into MYSCHEMA.B (NAME, AGE) VALUES (''||decode(NAME, null, ''null'', ''''''''||NAME||'''''''')||'', ''||decode(AGE, null, ''null'', AGE)||'')' stmt from Whosebug.B
insert into MYSCHEMA.B (NAME, AGE) VALUES ('||decode(NAME, null, 'null', ''''||NAME||'''')||', '||decode(AGE, null, 'null', AGE)||')
insert into MYSCHEMA.B (NAME, AGE) VALUES ('||decode(NAME, null, 'null', ''''||NAME||'''')||', '||decode(AGE, null, 'null', AGE)||')
您还需要删除许多其他转义引号。