感谢大家,我们可以在execute immediate
查询的帮助下动态创建表格。但是当我们创建一个表时,它已被创建,但如果我想用动态no列动态创建表,那么问题就出现了。实际上我创建了一个表,但是当我在表中创建了没有列的时候,引发了很多错误。以下是我在过程中在Oracle中编写的代码。
declare
no_of_cols number:=&no_of_cols;
colname varchar2(20);
coldata varchar2(20);
i number;
begin
execute immediate 'create table smap1(nam varchar2(10))';
age:='age';
datf:='number'
if(no_of_cols>=2) then
for i in 2..no_of_cols loop
colname:=age;
coldata:=datf;
execute immediate 'alter table smapl add '||colname||' '||coldata;
end loop;
end if;
end;
然后,如果no_of_cols是5,则此代码使用相同类型的四列执行。然后我修改了代码并运行了plsql程序。该程序如下
declare
no_of_cols number:=&no_of_cols;
colname varchar2(20);
age varchar2(20);
datf varchar2(20);
coldata varchar2(20);
i number;
begin
execute immediate 'create table smap1(nam varchar2(10))';
if(no_of_cols>=2) then
for i in 2..no_of_cols loop
age :=&age;
datf:=&datf;
colname:=age;
coldata:=datf;
execute immediate 'alter table smapl add '||colname||' '||coldata;
end loop;
end if;
end;
以下是创建上述过程时生成的错误
[Error] Execution (13: 19): ORA-06550: line 13, column 19:
PLS-00103: Encountered the symbol ";" when expecting one of the following:
( - + case mod new not null <an identifier>
<a double-quoted delimited-identifier> <a bind variable>
continue avg count current exists max min prior sql stddev
sum variance execute forall merge time timestamp interval
date <a string literal with character set specification>
<a number> <a single-quoted SQL string> pipe
<an alternatively-quoted string literal with character set specification>
<an alternatively
我对上面的plsql做了一些修改,然后plsql代码如下
declare
no_of_cols number:=&no_of_cols;
colname varchar2(20):='&colname';
coldata varchar2(20):='&coldata';
i number;
begin
execute immediate 'create table smap1(nam varchar2(10))';
if(no_of_cols>=2) then
for i in 2..no_of_cols loop
execute immediate 'alter table smapl add '||colname||' '||coldata;
end loop;
end if;
end;
然后在执行后我收到以下错误并且它确实动态读取列名
[Error] Execution (1: 1): ORA-02263: need to specify the datatype for this column
ORA-06512: at line 10
答案 0 :(得分:2)
EXECUTE IMMEDIATE
中使用分号表示单个语句以下是documentation:
的引用除了多行查询之外,动态字符串可以包含任何SQL语句( 没有最终分号 )或任何PL / SQL块(带有最后一个分号)
从EXECUTE IMMEDIATE
删除分号。
execute immediate 'create table smap1(nam varchar2(10));'; -- this is your code
execute immediate 'create table smap1(nam varchar2(10))'; -- correct code, no semicolon at end
但还有另外一个问题。
&variable
)的工作原理SQL * Plus将仅提示替换变量一次:在脚本编译之前,在运行之前。然后在脚本中逐字替换变量,之后它将被编译并执行。
例如,当您运行脚本时,SQL * Plus会识别出有两个未知的文字(&colname
和&coldata
),并会提示您。如果您提供值&#39; age&#39;和&#39; number&#39;对于他们来说,SQL * Plus会像这样重写脚本:
declare
-- omitted to add clarity
begin
execute immediate 'create table smap1(nam varchar2(10));';
if(no_of_cols>=2) then
for i in 2..no_of_cols loop
colname:=age;
coldata:=number;
execute immediate 'alter table smapl add '||colname||' '||coldata;
end loop;
end if;
end;
因此,如果要将字符串文字分配给变量,并且希望从替换变量中获取该字符串,则需要执行以下操作:
colname varchar2(30) := '&colname'; -- notice the single quotes
假设您提供了&#39; age&#39; for colname
SQL * Plus会很乐意将其转换为:
colname varchar2(30) := 'age';
因此, 在循环中放置替换变量不会使SQL * Plus反复提示您输入值 。
答案 1 :(得分:0)
为了更好地理解和分析,你应该这样做:
sqlcmd varhchar(30000);
begin
sqlcmd := 'create table smap1(nam varchar2(10))';
DBMS_OUTPUT.PUT_LINE(sqlcmd);
execute immediate sqlcmd;
if(no_of_cols>=2) then
for i in 2..no_of_cols loop
age :=&age;
datf:=&datf;
colname:=age;
coldata:=datf;
sqlcmd := 'alter table smapl add '||colname||' '||coldata;
DBMS_OUTPUT.PUT_LINE(sqlcmd);
execute immediate sqlcmd;
end loop;
end if;