在oracle中动态创建和执行sql命令

Ken*_*h J 1 sql oracle plsql dynamic-sql cursor

我正在上一个数据库类,在该类的实验部分的开头,我们通常必须删除之前创建的数据库中的所有表.我希望能够运行一个动态执行此操作的脚本,但似乎无法使其工作.这是我到目前为止的代码.

declare tname string(50);
cursor ctable is select table_name from user_tables;

begin
 open ctable;
 LOOP
   FETCH ctable into tname;
   if tname != ''  then
     execute immediate 'drop table ' || tname;
   END if;
   EXIT WHEN ctable%NOTFOUND;
 END LOOP;
 close ctable;
end;
Run Code Online (Sandbox Code Playgroud)

如果有人可以指出我正确的方向,我做错了什么会很好.谢谢.

Pet*_*ang 5

Oracle VARCHAR2将空字符串视为NULL.
所以

if tname != '' then
Run Code Online (Sandbox Code Playgroud)

是相同的

if tname != NULL then
Run Code Online (Sandbox Code Playgroud)

这将返回NULL而不是TRUE因为它没有定义.

您可以检查NULL通过tname IS NOT NULL.

table_nameuser_tables虽然是强制性的,所以不需要这个检查.


还有两件事:

  1. %NOTFOUND取出后立即检查
  2. 如果可能,使用列引用作为变量声明(user_tables.table_name%TYPE)

所以你的代码看起来像这样:

DECLARE
  tname user_tables.table_name%TYPE;
  CURSOR ctable IS SELECT table_name FROM user_tables;
BEGIN
  OPEN ctable;
  LOOP
    FETCH ctable INTO tname;
    EXIT WHEN ctable%NOTFOUND;
    EXECUTE IMMEDIATE 'drop table ' || tname;
  END LOOP;
  CLOSE ctable;
END;
Run Code Online (Sandbox Code Playgroud)

您还可以使用隐式游标以获得更好的可读性:

BEGIN
  FOR cur IN ( SELECT table_name FROM user_tables ) LOOP
    EXECUTE IMMEDIATE 'drop table ' || cur.table_name;
  END LOOP;
END;
Run Code Online (Sandbox Code Playgroud)

  • 如果使用外键约束,则需要在生成的命令中附加"级联约束",否则DROP命令将对引用的表失败. (3认同)