Oracle dbms_output.put_行在存储过程的游标For循环中不起作用
我遇到了一个奇怪的问题,它似乎非常特定于存储过程内部循环的游标。为清楚起见,我在DBeaver中使用Oracle,并尝试循环表中的所有列,并打印select语句的结果 我无法访问确切的代码,但这在功能上是近似的:Oracle dbms_output.put_行在存储过程的游标For循环中不起作用,oracle,loops,stored-procedures,plsql,cursor,Oracle,Loops,Stored Procedures,Plsql,Cursor,我遇到了一个奇怪的问题,它似乎非常特定于存储过程内部循环的游标。为清楚起见,我在DBeaver中使用Oracle,并尝试循环表中的所有列,并打印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 S
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,所以我对它的奥秘一无所知
此外,它似乎是特定于循环的游标;如果我将循环的光标替换为通用数字循环,即1中的c_id。。10,一个过程将产生刚刚好的输出。受影响的不仅仅是DBMS_OUTPUT.PUT_行;在存储过程中,游标For循环中发生的几乎所有事情都会被忽略,包括变量更新,即使它们在正常的PL/SQL块中工作正常
总而言之:作为PL/SQL块可以很好地工作,在数字for循环中也可以很好地工作,但是由于某些原因,存储过程和游标for循环的精确组合导致不生成输出;事实上,从我的测试来看,在存储函数的游标for循环中似乎没有发生任何有意义的事情
这是一个DBeaver bug吗?PL/SQL奇怪之处?我之所以在这里发帖,是因为我不知道这是否是由于过程和/或循环游标的工作方式导致的预期行为,或者这是否是某种错误。您所做的是声明一个过程。现在您已经声明了它,您必须使用类似于bellow的程序调用它。它很可能会产生产出 选项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
获取一个返回参数。理想情况下,将表类型作为输出参数。在上面的代码中,循环并打印值
选项03。
将输出记录到日志表中。我发现只需将AUTHID current_user添加到过程中,就可以解决错误;显然,该过程没有访问它试图选择的表的权限。但奇怪的是,在尝试运行该过程时没有产生错误;它只是没有产生任何输出。您将无法打印来自动态SQL的数据。使用REF-CURSOR进行处理,然后您就可以得到解决方案。在SQL developer中使用SET-SERVEROUTPUT对我来说很好。您真的在执行这个过程吗。如果编写PLSQL块并运行它,它会直接显示结果。但对于过程,您需要在编译后执行该过程。尝试exec列_null'Yourtablename';我使用begincolumn_null'table_name'END调用该过程;这对其他程序很有效。我相信Sabarish的评论可能是正确的,但为了测试它,我需要了解更多关于REF游标的信息;其他程序需要查找哪些工作。当我了解更多信息时,我将研究选项2。