table 创建的 EXECUTE IMMEDIATE 语句不起作用

EXECUTE IMMEDIATE statement for table creation doesn't work

我必须编写一个存储过程来创建一个 table 用于记录树的类型以及 X 和 Y 坐标。我知道您必须使用 EXECUTE IMMEDIATE 语句才能创建 table 这是代码:

Create or replace Procedure add_populate_trees 
(p_treenum in NUMBER)
IS
v_loop_counter NUMBER := 0;
v_artari_counter NUMBER :=0;
v_mesteceni_counter NUMBER :=0;
v_fagi_counter NUMBER :=0;
v_arini_counter NUMBER :=0;
v_stejari_counter NUMBER :=0;
BEGIN
EXECUTE IMMEDIATE 'drop table copaci';
EXECUTE IMMEDIATE 'create table copaci (Tip_copac VARCHAR2(25), Coord_X NUMBER(5), Coord_Y NUMBER(5))';
WHILE v_loop_counter <= p_treenum LOOP
    INSERT INTO copaci (Tip_copac, Coord_X, Coord_Y) Values('Artar',DBMS_RANDOM.value(0,1000000),DBMS_RANDOM.value(0,1000000));
    v_artari_counter := v_artari_counter + 1;
    v_loop_counter :=v_loop_counter + 1;
INSERT INTO copaci (Tip_copac, Coord_X, Coord_Y) Values('Mesteacan',DBMS_RANDOM.value(0,1000),DBMS_RANDOM.value(0,1000));
    v_mesteceni_counter := v_mesteceni_counter + 1;
    v_loop_counter := v_loop_counter + 1;


    INSERT INTO copaci (Tip_copac, Coord_X, Coord_Y) Values('Fag',DBMS_RANDOM.value(0,1000),DBMS_RANDOM.value(0,1000));
    v_fagi_counter := v_fagi_counter + 1;
    v_loop_counter := v_loop_counter + 1;


    INSERT INTO copaci (Tip_copac, Coord_X, Coord_Y) Values('Arin',DBMS_RANDOM.value(0,1000),DBMS_RANDOM.value(0,1000));
    v_arini_counter := v_arini_counter + 1;
    v_loop_counter := v_loop_counter + 1;


    INSERT INTO copaci (Tip_copac, Coord_X, Coord_Y) Values('Stejar',DBMS_RANDOM.value(0,1000),DBMS_RANDOM.value(0,1000));
    v_stejari_counter := v_stejari_counter + 1;
    v_loop_counter := v_loop_counter + 1;
END LOOP;
DBMS_OUTPUT.PUT_LINE('In padure au fost plantati '||v_artari_counter||'artari');
DBMS_OUTPUT.PUT_LINE('In padure au fost plantati '||v_mesteceni_counter||'mesteceni');
DBMS_OUTPUT.PUT_LINE('In padure au fost plantati '||v_fagi_counter||'fagi');
DBMS_OUTPUT.PUT_LINE('In padure au fost plantati '||v_arini_counter||'arini');
DBMS_OUTPUT.PUT_LINE('In padure au fost plantati '||v_stejari_counter||'stejari');
end;

之后是类似的插入和变量增量,但是当我执行此操作时,我得到插入错误 table 不存在,这只能意味着未创建 table。在此先感谢您的帮助

调用过程之前 'copaci' table 是否存在?否则,一旦您尝试发出 'drop table copaci' 命令,它就会死掉。包装您的 drop 语句以查看是否发生了这种情况并允许您的过程继续:

BEGIN
  EXECUTE IMMEDIATE 'drop table copaci';
EXCEPTION WHEN OTHERS THEN
  dbms_output.put_line('exception occurred because the copaci table did not exist');
END;   

如果您遇到权限不足错误,请查看此答案: Execute Immediate within a stored procedure keeps giving insufficient priviliges error

如果这是您的问题,您需要添加 AUTHID:

Create or replace Procedure add_populate_trees 
(p_treenum in NUMBER)
AUTHID CURRENT_USER
IS
v_loop_counter NUMBER := 0;
v_artari_counter NUMBER :=0;
v_mesteceni_counter NUMBER :=0;
v_fagi_counter NUMBER :=0;
v_arini_counter NUMBER :=0;
v_stejari_counter NUMBER :=0;
BEGIN
  BEGIN
    EXECUTE IMMEDIATE 'drop table copaci';
  EXCEPTION WHEN OTHERS THEN
    NULL;
  END;  
EXECUTE IMMEDIATE 'create table copaci (Tip_copac VARCHAR2(25), Coord_X NUMBER(10), Coord_Y NUMBER(10))';
WHILE v_loop_counter <= p_treenum LOOP
    EXECUTE IMMEDIATE 'INSERT INTO copaci (Tip_copac, Coord_X, Coord_Y) Values(''Artar'',DBMS_RANDOM.value(0,1000000),DBMS_RANDOM.value(0,1000000))';
    v_artari_counter := v_artari_counter + 1;
    v_loop_counter :=v_loop_counter + 1;
    EXECUTE IMMEDIATE 'INSERT INTO copaci (Tip_copac, Coord_X, Coord_Y) Values(''Mesteacan'',DBMS_RANDOM.value(0,1000),DBMS_RANDOM.value(0,1000))';
    v_mesteceni_counter := v_mesteceni_counter + 1;
    v_loop_counter := v_loop_counter + 1;


    EXECUTE IMMEDIATE 'INSERT INTO copaci (Tip_copac, Coord_X, Coord_Y) Values(''Fag'',DBMS_RANDOM.value(0,1000),DBMS_RANDOM.value(0,1000))';
    v_fagi_counter := v_fagi_counter + 1;
    v_loop_counter := v_loop_counter + 1;


    EXECUTE IMMEDIATE 'INSERT INTO copaci (Tip_copac, Coord_X, Coord_Y) Values(''Arin'',DBMS_RANDOM.value(0,1000),DBMS_RANDOM.value(0,1000))';
    v_arini_counter := v_arini_counter + 1;
    v_loop_counter := v_loop_counter + 1;


    EXECUTE IMMEDIATE 'INSERT INTO copaci (Tip_copac, Coord_X, Coord_Y) Values(''Stejar'',DBMS_RANDOM.value(0,1000),DBMS_RANDOM.value(0,1000))';
    v_stejari_counter := v_stejari_counter + 1;
    v_loop_counter := v_loop_counter + 1;
END LOOP;
DBMS_OUTPUT.PUT_LINE('In padure au fost plantati '||v_artari_counter||'artari');
DBMS_OUTPUT.PUT_LINE('In padure au fost plantati '||v_mesteceni_counter||'mesteceni');
DBMS_OUTPUT.PUT_LINE('In padure au fost plantati '||v_fagi_counter||'fagi');
DBMS_OUTPUT.PUT_LINE('In padure au fost plantati '||v_arini_counter||'arini');
DBMS_OUTPUT.PUT_LINE('In padure au fost plantati '||v_stejari_counter||'stejari');
end;

请注意,您尝试插入的值不适合您的列,因此我不得不将大小增加到 number(10)。

如果在您最初尝试编译和执行过程时 table 不存在,您将得到一个错误。这是因为 PL/SQL 在编译时针对它引用的对象进行验证。引用可能存在的 table 的唯一方法是使用 EXECUTE IMMEDIATE。解决此问题的最简单方法是在最初创建过程之前 运行 您的 create table 脚本。

但是,对于 Oracle,从过程代码发出 DDL 通常不是一个好主意。与其每次使用 table 并重新创建它,不如处理这种需求的最佳方法是创建一次 global temporary table (GTT) 并编写代码以引用它。 GTT 的值会在您提交或会话结束时自动删除(取决于您在创建它时选择的选项),因此在会话中首次访问时它始终是干净的。


在过程中访问尚不存在的 table 的唯一方法是将对它的每个引用更改为 EXECUTE IMMEDIATE。由于您没有将任何变量传递给 insert 命令,这应该只是将它们转换为字符串的问题。