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 对标识符不区分大小写,因此 foo
和 FOO
是等价的。让我们重现您的部分代码,为清楚起见,将变量名称设置为小写:
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;
它发现所需的标识符 foo
和 foo_id
是已知的(在 table 定义的上下文中)。因此,无需在语法树中寻找更高层来定义所使用的名称。换句话说,第一个 foo
(循环变量)被 table 名称遮蔽并且不用于删除查询的编译,这与
相同
DELETE FROM foo WHERE foo_id = foo_id;
并且它的过滤条件对于除 NULL
之外的所有 foo_id
都为真,导致删除整行。
幸运的是,这个问题可以通过 naming conventions 一劳永逸地解决:在 PL/SQL 块中使用带有特殊前缀的名称等,防止您的代码与模式对象名称意外交叉。
我在 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 对标识符不区分大小写,因此 foo
和 FOO
是等价的。让我们重现您的部分代码,为清楚起见,将变量名称设置为小写:
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;
它发现所需的标识符 foo
和 foo_id
是已知的(在 table 定义的上下文中)。因此,无需在语法树中寻找更高层来定义所使用的名称。换句话说,第一个 foo
(循环变量)被 table 名称遮蔽并且不用于删除查询的编译,这与
DELETE FROM foo WHERE foo_id = foo_id;
并且它的过滤条件对于除 NULL
之外的所有 foo_id
都为真,导致删除整行。
幸运的是,这个问题可以通过 naming conventions 一劳永逸地解决:在 PL/SQL 块中使用带有特殊前缀的名称等,防止您的代码与模式对象名称意外交叉。