对于PL/SQL中的循环和列

mat*_*yyy 3 sql database oracle plsql

我是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;
Run Code Online (Sandbox Code Playgroud)

我创建了一个游标.如您所见,我想检查列号为column_1到column_102的所有列.不幸的是|| 运营商不适用于这种情况.你知道我的问题的一些解决方案吗?

Xav*_*ica 5

您可以使用动态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;
Run Code Online (Sandbox Code Playgroud)

或者您也可以分配rec.column.' || nr ||' is null给变量并使PUT_LINE外部成为EXECUTE IMMEDIATE零件:

更新:似乎无法绑定BOOLEAN变量,所以我修改了示例以使用a NUMBER.

更新2:可能的效率提高,尽管可能不适合这种情况.VARCHAR对动态SQL 使用常量,并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;
Run Code Online (Sandbox Code Playgroud)

更新3:看到:

  • 无法访问rec动态SQL语句内部,因为它未定义(超出范围),

  • 似乎不可能将非sql类型作为参数传递给动态语句(记录,游标)

一种可能的解决方法是将一些id列(SQL Type)绑定到dynamic语句,并使用select子句来查找当前列是否为null:

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;
Run Code Online (Sandbox Code Playgroud)