在sql plus 中,运行dbms_output.put时提示SP2-0734: unknown command beginning 请问是何缘故?

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了在sql plus 中,运行dbms_output.put时提示SP2-0734: unknown command beginning 请问是何缘故?相关的知识,希望对你有一定的参考价值。

新装了oracle 10g(winxp),在sql plus 中,登录system,先已经set serverout on,再运行dbms_output.put时提示SP2-0734: unknown command beginning "dbms_outpu..." - rest of line ignored. 请问是何缘故?

使用 set sqlblanklines on
这是因为有空行导致sql语句加载到机器内存中截断了

或者你看看你的oracle安装目录下\sqlplus\admin中的glogin.sql文件,去掉其中的乱码和中文
参考技术A 前面没敲 execute? 参考技术B imp SISINTERGRATIONMGR/SISINTERGRATIONPWD file=/home/oracle/SISINTERGRATIONMGR.dmp fromuser=SISINTERGRATIONMGR touser=SISINTERGRATIONMGR commit=Y buffer=2048000 log=impSISINTERGRATIONMGR
不能再SQL>下的执行,否则会出现上述错误,需要在[oracle@app ~]$ 下执行就行了

我的长时间 SQL*Plus 循环在执行期间不打印 DBMS_OUTPUT.PUT_LINE 输出

【中文标题】我的长时间 SQL*Plus 循环在执行期间不打印 DBMS_OUTPUT.PUT_LINE 输出【英文标题】:My long time SQL*Plus loop doesn't print DBMS_OUTPUT.PUT_LINE output during execution 【发布时间】:2020-11-14 20:00:56 【问题描述】:

我知道为了在 sqlplus 上打印一些东西,如下所示:

begin
   dbms_output.put_line('Hello!'); 
end;
/

我需要打电话

set serveroutput on;

在那之前。 我也知道不需要,但我也可以调用

DBMS_OUTPUT.enable;

之前,以防万一。这对我有用。

但是如果我想继续打印一个长循环的进度怎么办?这对我来说似乎是不可能的。我已经尝试了一切以在下面的循环上打印一些进度,但只是不起作用。有没有办法做到这一点?我什至试图假脱机到一个文件,但没有工作。

注意 1:我无法截断或分区此表,因为 DBA 不想帮助我,所以我必须使用这个讨厌的循环...

注意 2:我注意到一旦循环完成,整个输出就会被打印出来。看起来 oracle 正在缓冲输出并在最后打印所有内容。我不确定如何避免这种情况并在每次循环迭代时打印。

set serveroutput on;
declare
    e number;
    i number;
    nCount number;
    f number;
begin
    DBMS_OUTPUT.enable;
    dbms_output.put_line('Hello!'); 
    select count(*) into e from my_big_table  where upd_dt < to_date(sysdate-64);
    f :=trunc(e/10000)+1;
    for i in 1..f
    loop
       delete from my_big_table where upd_dt < to_date(sysdate-64) and rownum<=10000;
       commit;
       DBMS_OUTPUT.PUT_LINE('Progress: ' || to_char(i) || ' out of ' || to_char(f));
    end loop;
end;

感谢您的任何回答。

【问题讨论】:

dbms_output,put_line 将所有输出保存在 dbms_output 包的集合(嵌套表)变量中,因此您无法从另一个会话中获取它,并且客户端在用户调用(执行)期间无法获取它。除了set serveroutput on,您还可以使用 dbms_output.get_lines 获取输出:orasql.org/2017/12/10/… 当您的用户调用在数据库中执行时,您无法在同一个会话中从中获取任何内容,因为您的客户端只是在用户调用完成时等待。但我可以建议您使用 Oracle 调度程序:您可以将您的长流程作为一次性作业开始,并使用我的回答中的相同变体在您的会话中对其进行监控 【参考方案1】:

此类事情有两种标准方法:

    在您的会话中设置模块和操作DBMS_APPLICATION_INFO.SET_MODULE:

    SQL> exec DBMS_APPLICATION_INFO.SET_MODULE('my_long_process', '1 from 100');
    
    PL/SQL procedure successfully completed.
    
    SQL> select action from v$session where module='my_long_process';
    
    ACTION
    ----------------------------------------------------------------
    1 from 100
    

    设置 session_longops: DBMS_APPLICATION_INFO.SET_SESSION_LONGOPS

    我会在您的情况下推荐它,因为它专为长时间操作而设计。Example on Oracle-Base。

----

PS: dbms_output,put_line 将所有输出保存在 dbms_output 包的一个集合(嵌套表)变量中,因此您无法从另一个会话中获取它,并且客户端在用户调用(执行)期间无法获取它。除了set serveroutput on,您还可以使用 dbms_output.get_lines 获取输出:http://orasql.org/2017/12/10/sqlplus-tips-8-dbms_output-without-serveroutput-on/

顺便说一句,如果您需要过滤或分析来自 dbms_output 的输出,有时在查询中获取输出很方便,因此您可以在 where 子句中使用过滤器字符串或聚合它们:https://gist.github.com/xtender/aa12b537d3884f4ba82eb37db1c93c25

【讨论】:

我尝试了第一种方法,因为它看起来很容易实现,但给了我一个错误。我已将 set_module 放入循环中,然后立即进行选择,以便我可以看到进度...这可能吗?还是我需要打开另一个会话来查询 v$session?从 v$session 中选择操作,其中 module='my_long_process'; * 第 16 行出现错误:ORA-06550:第 16 行,第 4 列:PLS-00428:此 SELECT 语句中应有一个 INTO 子句 我可以看到另一个会话的数据。已经很有用了,谢谢。 嗨@arthur 是的,它更容易实现,但是第二个可以为您提供更多有关进度的数据,因此您即使在执行后也可以对其进行分析【参考方案2】:

DBMS_OUTPUT 只会在 PL/SQL 代码终止并且控制权返回到调用程序后才会显示。

如您所见,输出是缓冲的。当您的 PL/SQL 代码完成时,调用程序(例如 SQL*Plus)可以去获取该输出。

【讨论】:

【参考方案3】:

插入另一个表,也许叫它“MYOUTPUT”。

创建表:

create table myoutput (lineno number, outline varchar2(80));

删除后添加:

insert into MYOUTPUT values (i,'Progress: ' || to_char(i) || ' out of ' || to_char(f));

然后定期从 MYOUTPUT 中选择以查看进度。

select outline from myoutput order by lineno;

鲍比

【讨论】:

你知道我是否可以从我的循环中进行选择,以便我可以在循环中看到结果吗?在同一个会话中? 没有。我在想你会在单独的会话中进行选择。【参考方案4】:

您可以使用 UTL_FILE 将输出写入外部文件,如下所示:

DECLARE
  fh          UTL_FILE.FILE_TYPE;
  nRow_count  NUMBER := 0;
BEGIN
  fh := UTL_FILE.FOPEN('DIRECTORY_NAME', 'some_file.txt', 'w');

  FOR aRow IN (SELECT *
                 FROM SOME_TABLE)
  LOOP
    nRow_count := nRow_count + 1;

    IF nRow_count MOD 1000 = 0 THEN
      UTL_FILE.PUT_LINE(fh, 'Processing row ' || nRow_count);
      UTL_FILE.FFLUSH(fh);
    END IF;

    -- Do something useful with the data in aRow
  END LOOP;  -- aRow

  UTL_FILE.FCLOSE_ALL;  -- Close all open file handles, including
                        -- the ones I've forgotten about...
END;

【讨论】:

以上是关于在sql plus 中,运行dbms_output.put时提示SP2-0734: unknown command beginning 请问是何缘故?的主要内容,如果未能解决你的问题,请参考以下文章

如何使用oracle的DBMS

dbms_output 大小缓冲区溢出

Oracle PL/SQL 中的漂亮打印

plsql 中如何使用dbms_output输出结果

plsql 中如何使用dbms_output输出结果

SQL Plus 与 Toad IDE - 在 SQL Plus 中运行插入需要更长的时间