我正在尝试在一个Execute Immediate语句中运行多个ddl语句。 我认为这将是非常直接的,但似乎我错了。
这个想法是这样的:
declare v_cnt number;
begin
select count(*) into v_cnt from all_tables where table_name='TABLE1' and owner = 'AMS';
if v_cnt = 0 then
execute immediate 'CREATE TABLE TABLE1(VALUE VARCHAR2(50) NOT NULL) ALTER TABLE TABLE1 ADD (MYVAL2 NVARCHAR2(10))';
end if;
end;
然而这会导致错误
ORA-00911:无效字符 ORA-06512:第10行
如果我自己执行它们,批处理中的每个语句都可以正常运行。如果我接受这个语句并执行它,它将运行良好(使用;在两个语句之间)。如果我删除;在语句之间我得到关于无效选项的不同错误
计划是我将能够构建一个表,导出该表的表模式,包括它的所有alter语句,然后作为安装/更新过程的一部分在另一个系统上运行批处理。
那么,我如何在单个执行立即批处理中批处理这些DDL语句?或者有更好的方法来做我需要的东西吗?
我必须承认,我有点像Oracle新手。谢谢大家的耐心等待。
答案 0 :(得分:4)
分号不是Oracle SQL语法的一部分。 SQL * Plus和其他客户端工具使用分号来表示SQL语句的结束,但服务器没有看到它。
我们可以强制SQL * Plus将分号传递给DB:
SQL> set sqlterminator off
SQL> select * from user_tables;
2 /
select * from user_tables;
*
ERROR at line 1:
ORA-00911: invalid character
如果我接受此语句并执行它,它将运行良好(使用;在两个语句之间)您正在使用的客户端工具,将其分成两次调用DB。
因此,我认为不可能在执行立即数内传递多个语句。
我想可以使用包含匿名PL / SQL块的字符串调用execute immediate,并且单独调用在其中立即执行...而且我不知道这样做的重点是什么。 ;)
答案 1 :(得分:2)
为什么需要单个EXECUTE IMMEDIATE调用?当然只是做2个电话?
请记住,每个DDL语句都包含一个隐式COMMIT,因此作为单个调用执行此操作不会产生任何可靠性。
另外,为什么不在第一次通话中正确设置表格呢?你可以做......
CREATE TABLE TABLE1(VALUE VARCHAR2(50)NOT NULL,MYVAL2 NVARCHAR2(10))
...而不是需要2个电话。
另外,你看过DBMS_METADATA ......它可以为你的表格等对象生成DDL。