#DBMS_OUTPUT

DBMS_OUTPUT包提供了一组内置的存储过程,主要用于调试PL时输出变量、表达式的值等。

Note:

  • 执行set serveroutput on命令会调用DBMS_OUTPUT.ENABLE(NULL),并打开打印开关。在开关处于打开状态时,执行一条SQL语句或调用匿名PL后会调用DBMS_OUTPUT.GET_LINES()获取缓冲区内剩余的信息并打印。
  • 执行set serveroutput off命令会调用DBMS_OUTPUT.DISABLE(),并关闭打印开关。默认场景下缓冲区和打印开关都是关闭状态。
  • 客户端只有yasql支持set serveroutput选项。
  • 缓冲区每行大小不能超过32000bytes。
  • 分布式部署中,在CN节点上所有用户均可调用该高级包,但在DN/MN节点上必须使用sys用户方可调用该高级包。
  • HA环境中,只能在主库/主节点上调用该高级包。

# CHARARR

TYPE CHARARR IS TABLE OF VARCHAR2(32000) INDEX BY BINARY_INTEGER;

CHARARR是DBMS_OUTPUT高级包内定义的数据类型,结合GET_LINES用于接收PUT、PUT_LINE输入缓冲区的信息。具体使用见GET_LINES示例。

# ENABLE

DBMS_OUTPUT.ENABLE(
    buffer_size IN INTEGER DEFAULT 20000);

ENABLE存储过程启用缓冲区,使其能够被PUT、PUT_LINE、NEW_LINE、GET_LINE、GET_LINES存储过程操作。

参数 描述
buffer_size 启用的缓冲区大小(单位:字节),取值范围为[2000,1000000],超出范围的数值按照较近的边界值处理,默认值为20000。若设置为NULL则等同于设置为4000000。

# DISABLE

DBMS_OUTPUT.DISABLE();

DISABLE存储过程禁用缓冲区,禁止PUT、PUT_LINE、NEW_LINE、GET_LINE、GET_LINES存储过程操作缓冲区,并清除缓冲区中所有剩余信息。该存储过程无参数。

示例(单机、共享集群部署)

BEGIN
    DBMS_OUTPUT.ENABLE(3000);
    DBMS_OUTPUT.PUT('yashanDB');   
    DBMS_OUTPUT.PUT_LINE('hello world!');
    DBMS_OUTPUT.DISABLE();
END;        
/

--result

# PUT

DBMS_OUTPUT.PUT(
    string IN VARCHAR2);

PUT存储过程向缓冲区输入一段无换行的文本。可以多次调用PUT,将多段信息拼接成一行。当使用PUT输入完一行后,需要调用NEW_LINE进行换行。GET_LINE、GET_LINES不会返回没有换行符的行。

# NEW_LINE

DBMS_OUTPUT.NEW_LINE();

NEW_LINE存储过程向缓冲区输入一个换行符。GET_LINE、GET_LINES返回以换行符分隔的行。每次调用PUT_LINE或NEW_LINE会生成可被GET_LINE或GET_LINES返回的一行。

# PUT_LINE

DBMS_OUTPUT.PUT_LINE(
    line IN VARCHAR2);

PUT_LINE存储过程向缓冲区输入一行。PUT_LINE输入的内容以换行符结尾,无需再调用NEW_LINE进行换行。

示例(单机、共享集群部署)

SET serveroutput ON;
BEGIN
    DBMS_OUTPUT.ENABLE(3000);
    DBMS_OUTPUT.PUT('yashanDB');
    DBMS_OUTPUT.PUT_LINE('hello world!');
    DBMS_OUTPUT.PUT('coming'); 
END;
/

--result
yashanDBhello world!

# GET_LINE

DBMS_OUTPUT.GET_LINE(
    line OUT VARCHAR2,
    status OUT INTEGER);

GET_LINE存储过程从缓冲区获取一行以换行符结尾的信息,并丢弃换行符。当触发GET_LINE后,如果首次调用PUT、PUT_LINE或NEW_LINE,会先清空缓冲区再执行写入。

参数 描述
line 返回的缓冲区中的一行信息,不包括最后的换行符。
status 该次调用的状态。若调用执行成功,状态值置为0。若缓冲区已没有行,状态值置为1。

示例(单机、共享集群部署)

SET serveroutput ON;

DECLARE
    line VARCHAR2(100);
    status INT;
BEGIN
    DBMS_OUTPUT.ENABLE(3000);
    DBMS_OUTPUT.PUT_LINE('后勤部');
    DBMS_OUTPUT.PUT_LINE('后勤管理部');
    DBMS_OUTPUT.GET_LINE(line,status);
    INSERT INTO department VALUES(status,line);
END;
/

SELECT deparment_no,department_name FROM department ORDER BY deparment_no;
DELETE FROM department WHERE deparment_no='0';

--result
后勤管理部

DEPARMENT_NO DEPARTMENT_NAME
------------ ---------------------
0            后勤部
000          不分部门
002          财务部
008          采购部
010          销售部

# GET_LINES

DBMS_OUTPUT.GET_LINES(
    lines OUT CHARARR,
    numlines IN OUT INTEGER);

GET_LINES存储过程从缓冲区获取行组成的数组。若缓冲区内剩余的行数不小于请求的行数,返回的行数即为请求的行数。若剩余的行数小于请求的行数,返回的行数为实际剩余的行数。当触发GET_LINES后,如果首次调用PUT、PUT_LINE或NEW_LINE,会先清空缓冲区再执行写入。

参数 描述
lines 返回的缓冲区中的多行组成的数组。
numlines 想要从缓冲区获取的行数。返回实际获取的行数。

示例(单机、共享集群部署)

DECLARE
    lines DBMS_OUTPUT.CHARARR;
    num INT;
BEGIN
    DBMS_OUTPUT.ENABLE(3000);
    DBMS_OUTPUT.PUT_LINE('后勤部');
    DBMS_OUTPUT.PUT_LINE('后勤管理部');
    num:=10;
    DBMS_OUTPUT.GET_LINES(lines,num);
    INSERT INTO department VALUES('050',lines(1));
    INSERT INTO department VALUES(num,lines(2));
END;
/
SELECT deparment_no,department_name FROM department ORDER BY deparment_no;
DELETE FROM department WHERE deparment_no IN ('050','2');

--result
DEPARMENT_NO DEPARTMENT_NAME
------------ ---------------------
000          不分部门
002          财务部
008          采购部
010          销售部
050          后勤部
2            后勤管理部

# 异常说明

调用DBMS_OUTPUT高级包进行缓冲区写入时,若写入字符串长度超过上限会抛出如下异常:

错误码 错误内容 解释
YAS-30005 line length overflow, limit of 32000 bytes per line 缓冲区写入当前行导致溢出,每行上限为32000bytes
YAS-30006 buffer overflow, limit of %d bytes 缓冲区写入导致溢出,缓冲区总长度上限为%d bytes