PL/SQL 中的 For 循环和列

发布于 2024-12-12 03:53:40 字数 314 浏览 0 评论 0原文

我是 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 的所有具有名称列的列。不幸的是||运算符不适用于这种情况。 你知道我的问题有什么解决办法吗?

I am new in PL/SQL. I have a problem with loop in this language. I' d like to make loop like this:

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;

I have created a cursor. As you can see I' d like to check all column with names column from column_1 to column_102. Unfortunately || operator does not work for this situation.
Do you know some solution to my problem?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

生来就爱笑 2024-12-19 03:53:40

您可以使用动态 PL/SQL 来完成此操作。使用立即执行 语句将字符串参数作为 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。 ||编号||'变量为 null 并将 PUT_LINE 置于 EXECUTE IMMEDIATE 部分之外:

UPDATE:似乎无法绑定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;

You can do this with dynamic PL/SQL. Use an EXECUTE IMMEDIATE statement to execute a string argument as PL/SQL, which you can make up with || as it was intended in the question.

Example:

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;

Or you could also assign rec.column.' || nr ||' is null to a variable and make the PUT_LINE outside the EXECUTE IMMEDIATE part:

UPDATE: It seems it is not possible to bind BOOLEAN variables, so I've modified the example to use a NUMBER.

UPDATE 2: There is a possible efficiency improvement, altough maybe not suitable in this case. Use a constant VARCHAR for the dynamic SQL, and pass in nr with a binded variable. This is even more efficient than using native SQL if in a large loop. I don't think 'rec.column.:arg is null would execute as 'rec.column.1 is null, though.

 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;

UPDATE 3:
Seeing that:

  • It is not possible to access rec inside the dynamic SQL statement because it is undefined (out of scope),

  • It seems not possible to pass a non-sql type as an argument to the dynamic statement (record, cursor)

A possible workaround is to bind some id columns (SQL Type) to the dynamic statement, and use a select clause to find out if the current column is 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;
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文