如何通过 JDBC 从 Db2 匿名块返回动态结果集?

Posted

技术标签:

【中文标题】如何通过 JDBC 从 Db2 匿名块返回动态结果集?【英文标题】:How to return dynamic results sets from a Db2 anonymous block via JDBC? 【发布时间】:2021-06-02 12:45:36 【问题描述】:

我正在查看Db2 LUW feature "returning result sets from SQL",它的工作方式似乎与 mysql、SQL Server 中的工作方式相似,方法是从任何过程逻辑运行简单的SELECT,或者在 Oracle 中使用 DBMS_SQL.RETURN_RESULT。以下匿名块似乎是有效的:

BEGIN
  DECLARE i INTEGER DEFAULT 1;
  WHILE i < 10 DO
    BEGIN 
      DECLARE cur CURSOR WITH RETURN TO CLIENT FOR SELECT i FROM sysibm.dual;
      OPEN cur;
      SET i = i + 1;
    END;
  END WHILE;
END

然而,它产生了这个警告,并且没有结果被获取。 DBeaver:

过程“BEGIN...END”返回“9”个查询结果集,超出了定义的限制“0”.. SQLCODE=464, SQLSTATE=0100E, DRIVER=4.26.14

如果这是一个程序,我必须声明:

动态结果集 n

但是我怎样才能在匿名块中声明呢?

【问题讨论】:

【参考方案1】:

如果不是来自过程,则无法返回结果集

见docs

有回报 指定游标的结果表旨在用作将从过程返回的结果集。和 RETURN 仅在包含 DECLARE CURSOR 语句时才相关 带有过程的源代码。在其他情况下,预编译器 可能会接受该子句,但它没有效果。

我知道这可能只是一个例子,但不需要过程语句来返回从 1 到 10 的整数,以下查询也可以:

with loop(k) as (
  values 1
  union all select k+1 from loop where k < 10
)
select * from loop order by k

【讨论】:

是的,这只是一个例子【参考方案2】:

试试下面的。它至少适用于我的 11.1。

    String str = 
        "begin"
    + "  declare l_c CURSOR; "
    + "  set l_c = cursor with hold for select empno from employee; "
    + "  open l_c; "
    + "  set ? = l_c; "
    + "end";
    CallableStatement st = null;
    ResultSet rs = null;
    try 
    
        st = con.prepareCall(str);
        st.registerOutParameter (1, com.ibm.db2.jcc.DB2Types.CURSOR); 
        st.execute(); 
        rs = (java.sql.ResultSet) st.getObject(1);
        if (rs != null)
        
          while (rs.next()) 
            System.out.println(rs.getString(1));
          rs.close();           
        
     ...

【讨论】:

以上是关于如何通过 JDBC 从 Db2 匿名块返回动态结果集?的主要内容,如果未能解决你的问题,请参考以下文章

如何在 DB2 中执行 SQL 匿名块?

如何使用返回数据的回调函数设置匿名块

在 DB2 PL/SQL 匿名块中声明局部变量和声明继续处理程序会导致错误?

匿名块存储在 SGA 中吗?

如何通过 JDBC 连接了解 DB2 风格

如何给druid指定db2数据库jdbc驱动类