dbms_output.put_line 在存储过程的 Cursor For 循环中不起作用

dbms_output.put_line doesn't work inside a Cursor For loop of a stored procedure

我遇到了一个奇怪的问题,它似乎非常特定于存储过程内部的 CURSOR FOR Loops。为清楚起见,我在 DBeaver 中使用 Oracle,并试图遍历 table 中的所有列并打印出 select 语句的结果。

我无法访问确切的代码,但这在功能上是近似的:

CREATE OR REPLACE PROCEDURE column_null(table_name_in IN VARCHAR2) 
AS
str_query VARCHAR2(1000);
temp_number NUMBER(10);
CURSOR col_cursor IS
SELECT * FROM user_tab_cols 
WHERE table_name = table_name_in;

BEGIN
FOR c_id IN col_cursor
LOOP
  str_query := 'select COUNT(*) FROM ' || table_name_in || 
               ' WHERE ' || c_id.column_name || ' IS NOT NULL';
  EXECUTE IMMEDIATE str_query INTO temp_number;
  DBMS_OUTPUT.PUT_LINE(temp_number);
END LOOP;
END;

现在,奇怪的是,如果我在存储函数之外执行完全相同的代码块(减去额外的 DECLARE 关键字),它会按预期工作。即使我尝试在循环中回显 'Hello',它也会按预期工作,但是 一旦它成为存储过程,它就会停止工作 。我今天已经测试了几个小时了,完全不知所措;作为参考,我最近才熟悉 PL/SQL 所以它的奥秘让我无法理解。

此外,它似乎特定于 CURSOR FOR 循环;如果我将 Cursor For 循环替换为通用数字循环(即 FOR c_id IN 1 .. 10),过程将产生很好的输出。受影响的不仅仅是 DBMS_OUTPUT.PUT_LINE;几乎 在 Cursor For 循环中发生的所有事情 在存储过程中都会被忽略,包括变量更新,即使它们在正常 PL/SQL 块中工作正常。

总结:作为 PL/SQL 块工作正常,在数字 for 循环中工作正常,但由于某种原因,存储过程和游标的确切组合循环导致不产生输出;事实上,从我的测试来看,在存储函数的循环游标中似乎没有任何有意义的事情发生。

这是 DBeaver 的错误吗? PL/SQL 怪事?我在这里发帖是因为我不知道这是否是由于 Procedures and/or Cursor For 循环的工作方式而导致的预期行为,或者这是否是某种错误。

你所做的是声明一个过程。现在你已经声明了它,你必须使用像下面这样的程序来调用它。它很可能会产生输出。

选项 01

    set serveroutput on;
    Declare
      v_table_name_in IN VARCHAR2(499);

    Begin
      v_table_name_in := 'your table name';
      column_null(table_name_in => v_table_name_in);
    end;  

选项02 获取一个 return 参数。理想情况下 table 类型作为输出参数。在上面的代码中,遍历它并打印值。

选项03。 将输出记录到日志 table.

我发现只需在程序中添加 AUTHID current_user 即可解决错误;显然,该过程没有访问它试图 select 的 table 的权限。奇怪的是,尝试 运行 该过程时没有产生错误;它只是没有产生任何输出。