Create or replace procedure sp_create_tables as
Lv_str varchar2(1000);
Begin
For I in (select distinct(deptno) from emp) loop
Lv_str:='create table deptno'||I||' select * from emp where
1=2';
Execute immediate lv_str;
End loop;
End;
答案 0 :(得分:4)
这行代码I
中是一个隐式 rowtype 变量,其数据结构由驾驶选择语句的投影定义:
For I in (select distinct(deptno) from emp) loop
但是您试图在动态SQL中引用它,就像它是一个属性一样。您需要改用列名。
Create or replace procedure sp_create_tables as
Lv_str varchar2(1000);
Begin
For I in (select distinct (deptno) from emp) loop
Lv_str:='create table deptno'|| I.deptno ||
' as select * from emp where 1=2';
Execute immediate lv_str;
End loop;
End;
偶然地,您的动态SQL语句中存在一个错误。正确的语法是CREATE TABLE ... AS SELECT ...
。动态SQL很难,因为编译器无法验证字符串中的代码位。因此,应该是编译错误的东西会表现为运行时错误。您会发现使用一些日志记录(或dbms_output.put_line()
)来记录代码以在汇编语句运行之前对其进行记录是有帮助的。它使调试更加容易。
”“我收到一个错误,提示-01031权限不足”
因此,这意味着您通过角色授予了创建表的授权。 Oracle安全模型不允许我们使用通过角色授予的特权来构建PL / SQL程序或视图。这包括通过动态SQL执行DDL的PL / SQL。您需要一个DBA用户才能将CREATE TABLE直接授予您的用户。
答案 1 :(得分:4)
据我了解,您的问题可能是“为什么程序会引发此编译错误”
PLS-00306:调用'||'时参数的数量或类型错误
原因是隐式游标循环变量I
引用了查询中的记录集,而不是deptno本身。为了引用deptno,您应该使用<loop_variable>.deptno
。另外还应该更改2件事:as
关键字丢失,DISTINCT
是关键字,并且您将其用作函数,由于默认括号,该函数可以使用,但不是正确的使用方式它。
Create or replace procedure sp_create_tables as
Lv_str varchar2(1000);
Begin
For I in (select distinct dept from emp) loop
Lv_str:='create table deptno'||I.deptno||' as select * from emp where
1=2';
Execute immediate lv_str;
End loop;
End;