ORACLE解析游标生成JSON

2025-11-11  本文已影响0人  登录成功

1. 背景

存储过程中使用oracleutl_http调用rest接口https://www.naquan.com/,并以JSON的方式传输数据.此需求下,业务和环境有如下限制:

业务已经通过sys_refcursor生成了业务数据,不希望重新编写存储过程

当前ORACLE版本为11G,不支持JSON操作

2. 思路

需要将游标转换为文本,有以下两个方法

使用游标生成XML,从XML转JSON,比较繁琐,如何生成XML,可参考ORACLE游标序列化

直接解析sys_refcursor,生成JSON数据,比较合理

第一种方法,适合接口为xml正文的接口,比如SOAP协议接口.若需要接口为json正文,还需要将XML转为JSON.需要掌握Oracle中的XML操作

第二种方法,直接转成JSON文本,需要借助DBMS_SQL解析游标数据

不管使用哪种方法,接口传输多为大文本,需要使用DBMS_LOB对文本进行文本操作

3. 实现

主要分为以下几个步骤

使用 DBMS_SQL.to_cursor_number 获取游标ID

使用 DBMS_SQL.DESCRIBE_COLUMNS 获取列数以及列信息

使用 DBMS_SQL.DEFINE_COLUMN 循环定义列类型

使用 DBMS_SQL.FETCH_ROWS 遍历数据

使用 DBMS_SQL.COLUMN_VALUE 获取每一列值

使用 DBMS_SQL.CLOSE_CURSOR 关闭游标

其中能获取到到列信息如下

-- author : herbert 公众号: 小满小慢 日期: 2025-11-11

  type desc_rec is record (

        col_type            binary_integer := 0,

        col_max_len        binary_integer := 0,

        col_name            varchar2(32)  := '',

        col_name_len        binary_integer := 0,

        col_schema_name    varchar2(32)  := '',

        col_schema_name_len binary_integer := 0,

        col_precision      binary_integer := 0,

        col_scale          binary_integer := 0,

        col_charsetid      binary_integer := 0,

        col_charsetform    binary_integer := 0,

        col_null_ok        boolean        := TRUE);

具体测试代码如下

declare

  v_cursor_id  NUMBER;

  v_col_count  BINARY_INTEGER;

  v_col_desc    DBMS_SQL.DESC_TAB;

  v_value      VARCHAR2(4000);

  v_row_data    VARCHAR2(4000);

  v_p_refcursor sys_refcursor;

BEGIN

  open v_p_refcursor FOR

    select '小游戏1' F_A, '地心侠士' F_B

      from dual

    union all

    select '小游戏2', '地心侠士'

      from dual;

  v_cursor_id := DBMS_SQL.to_cursor_number(v_p_refcursor);

  DBMS_SQL.DESCRIBE_COLUMNS(v_cursor_id, v_col_count, v_col_desc);

  FOR i IN 1 .. v_col_count LOOP

    DBMS_SQL.DEFINE_COLUMN(v_cursor_id, i, v_value, 4000);

  END LOOP;

  WHILE DBMS_SQL.FETCH_ROWS(v_cursor_id) > 0 LOOP

    v_row_data := '';

    FOR i IN 1 .. v_col_count LOOP

      DBMS_SQL.COLUMN_VALUE(v_cursor_id, i, v_value);

      v_row_data := v_row_data ||v_col_desc(i).col_name|| ': ' || v_value ;

    END LOOP;

    DBMS_OUTPUT.PUT_LINE(v_row_data);

  END LOOP;

  DBMS_SQL.CLOSE_CURSOR(v_cursor_id);

EXCEPTION

  WHEN OTHERS THEN

    IF DBMS_SQL.IS_OPEN(v_cursor_id) THEN

      DBMS_SQL.CLOSE_CURSOR(v_cursor_id);

    END IF;

    RAISE;

END;

输出内容如下

F_A : 小游戏F_B : 地心侠士

F_A : 公众号F_B : 小满小慢

我们最终想要的JSON格式如下

[{

"F_A": "小游戏",

"F_B": "地心侠士"

}, {

"F_A": "公众号",

"F_B": "小满小慢"

}]

通过上边的示列代码简单修改就完全可以实现了.

4. 总结

我在ORACLE游标序列化中实现了游标转XML文本,可以实现多个动态游标的合并.当时就考虑如何生成JSON文本,没有找到合适的方法.当真实的业务诉求出现以后,结合AI问答,找到了一个实际可行的方法.

需要完整游标转JSON的过程,请关注公众号小满小慢,回复游标转JSON获取完整代码.

上一篇 下一篇

猜你喜欢

热点阅读