pl sql中游标变量名有什么限制?

What restricition imposed on cursor variable name in plsql?

我在 sql 开发人员中执行了以下简单的匿名块,期望从​​“FOO”中删除 x 行 table 但是我最终得到了意想不到的结果,这又删除了整行.

DECLARE
  type pkarray IS VARRAY(3) OF RAW(16);
  ids pkarray;      
BEGIN  
  ids := pkarray('guid_value1','guid_value2','guid_value3');          
  FOR i in 1 .. 3 LOOP  
    FOR foo IN (SELECT FOO_ID FROM FOO WHERE BAR_ID = UPPER(ids(i))) LOOP                  
           DELETE FROM FOO WHERE FOO_ID = foo.FOO_ID;                  
    END LOOP;        
  END LOOP;      
END;

然而,当我将游标变量“foo”更改为“abc”之类的其他变量时,程序通过删除 x 行正常工作。我提前知道的数字 x。

由于 PL/SQL 对标识符不区分大小写,因此 fooFOO 是等价的。让我们重现您的部分代码,为清楚起见,将变量名称设置为小写:

 FOR foo /*1*/ IN (SELECT foo_id FROM foo WHERE bar_id = UPPER(ids(i))) LOOP                  
     DELETE FROM foo /*2*/ WHERE foo_id = foo.foo_id;                  
 END LOOP;

我们正在处理名称隐藏问题。当编译器计算这个表达式时

DELETE FROM foo WHERE foo_id = foo.foo_id;

它发现所需的标识符 foofoo_id 是已知的(在 table 定义的上下文中)。因此,无需在语法树中寻找更高层来定义所使用的名称。换句话说,第一个 foo (循环变量)被 table 名称遮蔽并且不用于删除查询的编译,这与

相同
DELETE FROM foo WHERE foo_id = foo_id;

并且它的过滤条件对于除 NULL 之外的所有 foo_id 都为真,导致删除整行。


幸运的是,这个问题可以通过 naming conventions 一劳永逸地解决:在 PL/SQL 块中使用带有特殊前缀的名称等,防止您的代码与模式对象名称意外交叉。