文章详情

短信预约信息系统项目管理师 报名、考试、查分时间动态提醒

请输入下面的图形验证码

提交验证

短信预约提醒成功

DBMS_SQL 执行查询示例

2017-10-13 20:09

关注

DBMS_SQL 执行查询示例

通常情况下,需要动态执行查询语句尽量使用语法更简洁的 OPEN {SYS_REFCURSOR} FOR ... 或 EXECUTE IMMEDIATE ...

当查询语句的列或绑定变量无法确定数量或类型时,还是需要使用更加灵活的 DBMS_SQL 包,下面是使用 DBMS_SQL 包执行列数量可变的查询示例;一个典型的应用场景就是报表的生成,因为我们可能无法事先知道这个报表有多少列。

DECLARE
  -- 可变列数的报表查询编程示例
  l_Cursor_Id INTEGER;
  l_Col_Count INTEGER;
  l_Desc_Tbl2 Dbms_Sql.Desc_Tab2;
  l_Ret       INTEGER;
  l_Row_Count BINARY_INTEGER := 0;
  l_Row_Index BINARY_INTEGER := 1;
  c_Bulk_Size CONSTANT BINARY_INTEGER := 2; -- 每次提取的记录数
  -- 报表的每一列最终都是 VARCHAR2 类型
  TYPE Col_Val_Tbl_Type IS TABLE OF Dbms_Sql.Varchar2_Table INDEX BY PLS_INTEGER;
  l_Col_Val_Tbl Col_Val_Tbl_Type;
BEGIN
  -- 打开并解析查询语句
  l_Cursor_Id := Dbms_Sql.Open_Cursor;
  Dbms_Sql.Parse(l_Cursor_Id,
                 "SELECT ""X"" M, ""Y"" M FROM DUAL WHERE DUMMY = :T_DUMMY
UNION ALL SELECT ""C"", ""D"" FROM DUAL
UNION ALL SELECT ""E"", ""F"" FROM DUAL",
                 Dbms_Sql.Native);
  -- 根据查询语句的列取出所有值
  Dbms_Sql.Describe_Columns2(l_Cursor_Id, l_Col_Count, l_Desc_Tbl2);
  FOR i IN 1 .. l_Col_Count LOOP
    l_Col_Val_Tbl(i)(0) := NULL;
    Dbms_Sql.Define_Array(c           => l_Cursor_Id,
                          Position    => i,
                          c_Tab       => l_Col_Val_Tbl(i),
                          Cnt         => c_Bulk_Size,
                          Lower_Bound => l_Row_Index);
  END LOOP;
  -- 绑定变量并执行
  Dbms_Sql.Bind_Variable(l_Cursor_Id, ":T_DUMMY", "X");
  l_Ret := Dbms_Sql.Execute(l_Cursor_Id); -- 返回 DML 语句的修改行数,此处不使用
  -- 遍历查询结果
  LOOP
    l_Row_Count := l_Row_Count + Dbms_Sql.Fetch_Rows(l_Cursor_Id);
    EXIT WHEN l_Row_Count < l_Row_Index; -- 取出记录后总行数未增加
    -- Dbms_Output.Put_Line("FETCH: " || (l_Row_Count - l_Row_Index + 1));
    -- 取每一列的值
    FOR j IN 1 .. l_Col_Count LOOP
      Dbms_Sql.Column_Value(l_Cursor_Id, j, l_Col_Val_Tbl(j));
    END LOOP;
    -- 遍历每一行
    FOR i IN l_Row_Index .. l_Row_Count LOOP
      FOR j IN 1 .. l_Col_Count LOOP
        -- 遍历每一列
        Dbms_Output.Put(l_Col_Val_Tbl(j) (i) || " ");
      END LOOP;
      Dbms_Output.Put_Line("");
    END LOOP;
    EXIT WHEN l_Row_Count - l_Row_Index + 1 < c_Bulk_Size; -- 本次取出的行数小于指定的值,不进行下次取值
    l_Row_Index := l_Row_Count + 1;
  END LOOP;
  -- 关闭
  IF Dbms_Sql.Is_Open(l_Cursor_Id) THEN
    Dbms_Sql.Close_Cursor(l_Cursor_Id);
  END IF;
END;

DBMS_SQL 包还提供了两个很棒的函数用于在 DBMS_SQL 的 CURSOR_NUMBER 和 SYS_REFCURSOR 之间切换,我们可以充分利用二者的长处:CURSOR_NUMBER 更灵活,SYS_REFCURSOR 更简洁。

例如上述示例在绑定变量上没有不确定性,只需要动态变化查询到的列,那么可以先使用语法简洁的 SYS_REFCURSOR 打开查询,然后切到 CURSOR_NUMBER 对列进行分析。

这两个函数的定义及说明如下:

function to_refcursor(cursor_number in out integer) return sys_refcursor;

CURSOR_NUMBER 必须是一个已经执行过(调用过 DBMS_SQL.EXECUTE)的查询,调用后游标的控制权转移到返回的 SYS_REFCURSOR 变量上,后续应且仅应 CLOSE SYS_REFCURSOR;

function to_cursor_number(rc in out sys_refcursor) return integer;

SYS_REFCURSOR 必须是一个已经打开(执行过 OPEN ... FOR ..)的查询,调用后游标的控制权转移到返回的 CURSOR_NUMBER 变量上,后续应且仅应 DBMS_SQL.CLOSE_CURSOR(CURSOR_NUMBER);

阅读原文内容投诉

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

软考中级精品资料免费领

  • 历年真题答案解析
  • 备考技巧名师总结
  • 高频考点精准押题
  • 2024年上半年信息系统项目管理师第二批次真题及答案解析(完整版)

    难度     813人已做
    查看
  • 【考后总结】2024年5月26日信息系统项目管理师第2批次考情分析

    难度     354人已做
    查看
  • 【考后总结】2024年5月25日信息系统项目管理师第1批次考情分析

    难度     318人已做
    查看
  • 2024年上半年软考高项第一、二批次真题考点汇总(完整版)

    难度     435人已做
    查看
  • 2024年上半年系统架构设计师考试综合知识真题

    难度     224人已做
    查看

相关文章

发现更多好内容

猜你喜欢

AI推送时光机
位置:首页-资讯-数据库
咦!没有更多了?去看看其它编程学习网 内容吧
首页课程
资料下载
问答资讯