【问题标题】:Getting a result set from a SQL SERVER stored procedure using GROOVY SQL使用 GROOVY SQL 从 SQL SERVER 存储过程中获取结果集
【发布时间】:2011-08-31 05:03:53
【问题描述】:

我正在尝试从我的 GRAILS 应用程序中的 SQL SERVER(我相信是 2005 年)中的存储过程中获取结果集。 (Grails 1.3.2,Groovy 1.7.6)

存储过程在任何查询浏览器上都运行良好,我使用 SQLDBX,它返回结果集,正如我一直预期的那样。

但是,在我的应用程序中,如果程序实际修改了数据,它会抛出一个错误,但如果不是,它不会抛出这个错误,而是会返回我想要的结果集。

现在我不能在这里发布程序,但这是修改后的版本。做的事情大致相同。

CREATE PROCEDURE [procedure1]
@year VARCHAR(4)
as
begin
DECLARE @var1 INT
DECLARE @var2 varchar(50)
DECLARE @counter INT

SET @counter=0

set @cursor = CURSOR FAST_FORWARD for
        select *
        FROM [table1] as t1
        INNER JOIN [table2] as t2
        ON t1.f_id = t2.f_id
        WHERE t1.year = @year
open @cursor
set @date = GETDATE()

fetch next from @cursor into @var1,@var2
while @@FETCH_STATUS = 0
begin
    select @numRows = count(id) from table1
    if(@numRows = 0)
    begin
        SET @counter=@counter+1
    END

    fetch next from @cursor into @var1,@var2
end

close @cursor
deallocate @cursor
SELECT @counter AS 'count'
return 0
END
GO

修改后的版本没有多大意义,但它执行相同的操作。

在我的 GRAILS 应用中,我正在做相当于

Sql conn = new Sql(dataSource) //A valid declaration  
try{  
  def results = conn.rows("execute [dbo].[procedure1] @year='2011'")  
  println("${results}")  
}  
catch(SQLException e){  
  println(e.getMessage())  
}  

每次运行并且计数器被修改(也就是不为零)时,它都会引发异常。但是,如果我跑 execute procedure1 @year='2011' 来自 SQLDBX,计数器不为零,它按我的预期返回。

我也尝试了一些来自 Groovy SQL 类的不同方法,但它们似乎都抛出了这个异常或者不是我想要的。

例外是

com.microsoft.sqlserver.jdbc.SQLServerException - The statement did not return a result set.

如果您需要更多信息,请告诉我。

【问题讨论】:

  • 您是否可能返回多个结果集,每个SELECT 对应一个您在过程中运行的结果集?我会尝试用set @numRows = (select count(id) from table1) 替换select @numRows = count(id) from table1
  • 那没有效果,仍然给出“语句没有返回结果集”错误。它仍然完成了这个过程。
  • 我有一个解决方法,基本上在存储过程之前查询受影响的表,然后在之后,并计算计数的差异。我真的很想让结果集正常工作,因为当这个表变得相当大时,这两个额外的查询将花费宝贵的时间。谢谢。
  • 作为对此的更新,我想我忘了提到我在 IBM Websphere 中运行。 GRAILS 应用程序使用 JNDI 源,而在 WAS 中,主 SQL Server 数据库的 JNDI 源使用过时的 JDBC 驱动程序。我无法在本地运行它(因为一些外部配置)或更新 WAS 上的驱动程序,所以我无法测试它是驱动程序还是 GROOVY。不幸的是,我被困住了。

标签: java sql stored-procedures grails groovy


【解决方案1】:

在存储过程中的AS 之后添加SET NOCOUNT ON。添加这个将告诉sql server不要返回sproc中的修改记录数。

这是文档...

http://msdn.microsoft.com/en-us/library/ms189837.aspx

【讨论】:

    【解决方案2】:

    executeQuery() 旨在用于返回 ResultSet 的查询,通常是 SELECT 语句。

    executeUpdate() 用于返回更新计数的 INSERT、UPDATE、DELETE 或 DDL 语句。

    上述两个(结果集和更新计数)都被 JDBC 视为“结果”。对于返回多个结果的查询,我们需要调用 execute()。

    如果存储过程使用临时表,它可能首先返回一个更新计数,然后是一个 ResultSet。您应该使用 execute() 运行查询,调用 getMoreResults() 跳过更新计数,然后调用 getResultSet() 来获取 您想要的结果集。这里的问题是我们必须通过多次调用 getMoreResults() 进行反复试验,才能通过调用 getResultSet() 来获取我们想要的结果集。

    您可以通过指定“SET NOCOUNT ON”来抑制所有额外的“查询结果”,而不是上述的反复试验方式。

    需要更改,

    1. 将您的逻辑放入 SP“SPCHILD”。此存储过程将具有逻辑以及临时表的创建。

    2. 如下创建一个SP“SPPARENT”,

       CREATE PROCEDURE [dbo].[SPPARENT]    @Id int = NULL
       AS
       BEGIN
       SET NOCOUNT ON;
       EXEC(' SPCHILD @Id = ' + @Id)
       END
      

      您必须从父 SP“SPPARENT”调用您的实际 SP,即“SPCHILD”。

    3. 从您的 JDBC 代码对“SPPARENT”进行 SP 调用。

    【讨论】:

      【解决方案3】:

      请参阅我的回答 here 以获取可以以类似于 groovy.sql.Sql 的方式处理存储过程 ResultSets 的工具

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2010-09-08
        • 2018-07-13
        • 2021-09-18
        • 1970-01-01
        • 2012-01-15
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多