有没有办法在执行存储过程或函数时提前确定要返回的结果集的数量?

Posted

技术标签:

【中文标题】有没有办法在执行存储过程或函数时提前确定要返回的结果集的数量?【英文标题】:Is there a way to determine ahead the number of result sets to be returned when executing a stored procedure or function? 【发布时间】:2021-04-11 07:52:52 【问题描述】:

让我们假设以下 JDBC 中的虚拟示例:

   Statement statement = connection.createStatement();
   statement.execute("call sp1(); select * from X;");
   
   int uc = statement .getUpdateCount();
   boolean isResult = (uc == -1);

   do
   
      if( isResult )
      
         ResultSet rs = statement.getResultSet();

         if( rs != null )
         
            doSomethingWithRS( rs );
         
      
      else
      
         System.out.println( "update count: " + uc );
      
   
   while( ( isResult = statement.getMoreResults() ) || ( uc = statement.getUpdateCount() ) != -1 );

众所周知,某些数据库/驱动程序允许执行多条语句(以 SQL Server 为例)。 程序员不一定知道存储过程的详细信息。 有没有办法提前确定要从存储过程调用返回的 ResultSet 的数量 - 以便可以将它们与为随后的 SELECT 返回的 ResultSet 区分开来?

【问题讨论】:

【参考方案1】:

不,JDBC 中没有任何东西可以让您提前知道这一点,而且通常在底层数据库系统中甚至没有选项可以知道这一点。例如,在 SQL Server 中,完全可以编写一个存储过程,根据其输入(包括它访问的表、环境配置等)输出零个、一个或几十个结果集(和更新计数)。这样的事情是不可判定的,不做执行本身。

您唯一能做的就是正确解释execute()getMoreResults()getUpdateCount()getResultSet() 的结果,或者不要编写可能有多个或动态结果的存储过程。

顺便说一句,你的初始代码不应该调用getUpdateCount()来决定它是否是一个结果集,它应该使用execute()的返回值:

boolean isResultSet = statement.execute("call sp1(); select * from X;");
while (true) 
  if (isResultset) 
    // Null-check not necessary, a correctly implemented JDBC driver 
    // should never return null if execute or getMoreResults returned true
    try (ResultSet rs = statement.getResultSet()) 
      // process rs
    
   else 
    int uc = statement.getUpdateCount();
    if (uc == -1) 
      // when isResultSet is false and update count is -1, 
      // there are no more results
      break;
    
    System.out.println("update count: " + uc);
  
  isResultSet = statement.getMoreResults()

【讨论】:

以上是关于有没有办法在执行存储过程或函数时提前确定要返回的结果集的数量?的主要内容,如果未能解决你的问题,请参考以下文章

请问MyBatis.net 如何执行一个不需要参数但返回结果集的oracle数据库的存储过程?

如何通过MyBatis获取mysql存储过程返回的不确定个数的多个结果集

从函数执行存储过程

将结果行强制转换为对象

存储过程与函数的区别

有没有办法让函数返回类型名?