首页 文章

如何使用动态列名和动态数据类型在oracle中创建动态表,而不包含任何视图或任何其他表类型

提问于
浏览
3

谢谢大家,我们可以在 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

2 回答

  • 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
    

    但还有另一个问题 .

    您需要了解替换变量(和变量)的工作原理

    SQL * Plus将仅提示替换变量一次:在脚本编译之前,在运行之前 . 然后在脚本中逐字替换变量,之后它将被编译和执行 .

    例如,当您运行脚本时,SQL * Plus会识别出有两个未知文字( &colname&coldata ),并会提示您 . 如果为它们提供值'age'和'number',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
    

    假设您提供'age' for colname SQL * Plus会很乐意将其转换为:

    colname varchar2(30) := 'age';
    

    所以, placing a substitution variable inside a loop will not make SQL*Plus repeatedly prompt you for it's value .

  • 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;
    

相关问题