PL/SQL 中的 for 循环和列
Posted
技术标签:
【中文标题】PL/SQL 中的 for 循环和列【英文标题】:For loop and columns in PL/SQL 【发布时间】:2011-10-26 10:48:19 【问题描述】:我是 PL/SQL 的新手。我对这种语言的循环有疑问。我想做这样的循环:
FOR nr IN 1..102
LOOP
DBMS_OUTPUT.PUT_LINE(nr);
IF rec.column_||nr IS NULL
THEN
DBMS_OUTPUT.PUT_LINE('test');
END IF;
END LOOP;
我已经创建了一个游标。如您所见,我想检查名称列从 column_1 到 column_102 的所有列。不幸的是||运算符不适用于这种情况。 你知道我的问题的一些解决方案吗?
【问题讨论】:
【参考方案1】:您可以使用dynamic PL/SQL 执行此操作。使用 EXECUTE IMMEDIATE
语句将字符串参数作为 PL/SQL 执行,您可以按照问题中的意图使用 ||
来弥补。
例子:
BEGIN
FOR nr IN 1..102
LOOP
DBMS_OUTPUT.PUT_LINE(nr);
EXECUTE IMMEDIATE
'BEGIN ' ||
'IF rec.column.' || nr ||' is null THEN ' ||
'DBMS_OUTPUT.PUT_LINE(''test''); ' ||
'END IF; ' ||
'END; ';
END LOOP;
END;
或者您也可以将rec.column.' || nr ||' is null
分配给一个变量,并将PUT_LINE
置于EXECUTE IMMEDIATE
部分之外:
更新:似乎无法绑定BOOLEAN
变量,所以我修改了示例以使用NUMBER
。
更新 2: 可能会提高效率,但可能不适合这种情况。对动态 SQL 使用常量 VARCHAR
,并使用绑定变量传入 nr
。如果在大循环中,这甚至比使用本机 SQL 更有效。不过,我认为 'rec.column.:arg is null
不会像 'rec.column.1 is null
一样执行。
DECLARE
isnull NUMBER;
BEGIN
FOR nr IN 1..102
LOOP
DBMS_OUTPUT.PUT_LINE(nr);
EXECUTE IMMEDIATE
'BEGIN ' ||
'IF rec.column.' || nr ||' IS NULL THEN ' ||
':x:=1; ' ||
'ELSE ' ||
':x:=0; ' ||
'END IF; ' ||
'END; '
USING OUT isnull;
IF isnull = 1 THEN
DBMS_OUTPUT.PUT_LINE('test');
END IF;
END LOOP;
END;
更新 3: 看到:
无法在动态 SQL 语句中访问rec
,因为它未定义(超出范围),
似乎不可能将非 sql 类型作为参数传递给动态语句(记录、游标)
一种可能的解决方法是将一些id列(SQL类型)绑定到动态语句,并使用select
子句来判断当前列是否为空:
DECLARE
isnull NUMBER;
rec_id NUMBER; -- Identifier of the fetched record
BEGIN
rec_id := rec.id;
FOR nr IN 1..102
LOOP
DBMS_OUTPUT.PUT_LINE(nr);
EXECUTE IMMEDIATE
'SELECT 1 FROM my_table WHERE id = :idarg ' ||
' AND column_' || nr || ' IS NULL'
INTO isnull USING rec_id;
IF isnull = 1 THEN
DBMS_OUTPUT.PUT_LINE('test');
END IF;
END LOOP;
END;
【讨论】:
你能举个例子吗? 不幸的是 BOOLEAN 不是 sql 类型,因此我得到一个错误。 是的,你是对的,正如here 所解释的那样。我只是在测试时发现了这一点。我已将示例更新为使用NUMBER
。
我现在有另一个问题,也许你也可以帮助我。当我尝试使用上述代码运行我的程序时。我收到此错误:PLS-00201:必须声明标识符“rec.column_1”。此问题出现在“EXECUTE IMMEDIATE...”行中
发生此错误是因为 rec
未定义且超出动态 SQL 的范围。据我所知,它没有简单的解决方法,也许您应该将某种标识符(带有 SQL 类型)绑定到动态 SQL 并使用 select
子句。查看更新后的答案,让我知道这是否适合您。以上是关于PL/SQL 中的 for 循环和列的主要内容,如果未能解决你的问题,请参考以下文章
为啥我在 PL/SQL 中的 for 循环没有打印出最后一次迭代
oracle 11g 中 for 循环中的 PL/SQL 限制