尝试从JDBC查询中获取返回码

时间:2018-11-17 21:49:39

标签: java sql-server jdbc

我的老板给了我一个存储过程,该存储过程应该返回一个代码,该代码指示它是成功还是存在问题。为了访问此过程并获取返回代码,我使用以下代码:

  SQLServerDataSource src = makeConnection();

  CallableStatement statement = null;
  ResultSet resultSet = null;

  try(Connection conn = src.getConnection())
  {
     statement = conn.prepareCall("{ ? = call uspGetBillOfMaterials(?,?) }");

     statement.registerOutParameter(1,Types.INTEGER);
     statement.setInt("StartProductID",733);
     statement.setString("CheckDate","2018-02-18 00:00:00.000");

     resultSet = statement.executeQuery();

     if(resultSet != null)
     {
        System.out.println("Query was successful. Code: "+resultSet.getInt(1));
     }
  }
  catch (Throwable t)
  {
     t.printStackTrace();
  }

应该注意,我在Microsoft SQL Server中使用JDBC。我正在使用用于SQL Server的Microsoft JDBC驱动程序。

不幸的是,当我执行此代码时,出现以下异常:

com.microsoft.sqlserver.jdbc.SQLServerException: The result set has no current row.
    at com.microsoft.sqlserver.jdbc.SQLServerException.makeFromDriverError(SQLServerException.java:226)
    at com.microsoft.sqlserver.jdbc.SQLServerResultSet.verifyResultSetHasCurrentRow(SQLServerResultSet.java:534)
    at com.microsoft.sqlserver.jdbc.SQLServerResultSet.getterGetColumn(SQLServerResultSet.java:2006)
    at com.microsoft.sqlserver.jdbc.SQLServerResultSet.getValue(SQLServerResultSet.java:2037)
    at com.microsoft.sqlserver.jdbc.SQLServerResultSet.getValue(SQLServerResultSet.java:2023)
    at com.microsoft.sqlserver.jdbc.SQLServerResultSet.getInt(SQLServerResultSet.java:2297) 
                                   ...
                       --- The rest removed for brevity---

我相信我的代码对于获取返回值是正确的。我想念什么吗?

还是存储过程编写不正确?存储过程如下:

USE [AdventureWorks2014]
GO

SET ANSI_NULLS ON
GO

SET QUOTED_IDENTIFIER ON
GO

ALTER PROCEDURE [dbo].[uspGetBillOfMaterials] @StartProductID [int]
    ,@CheckDate [datetime]
AS
BEGIN
    DECLARE @ReturnCode INT = 0
        ,@logrowcount VARCHAR(36)

    SET NOCOUNT ON;

    -- Use recursive query to generate a multi-level Bill of Material (i.e. all level 1 
    -- components of a level 0 assembly, all level 2 components of a level 1 assembly)
    -- The CheckDate eliminates any components that are no longer used in the product on this date.
    WITH [BOM_cte] (
        [ProductAssemblyID]
        ,[ComponentID]
        ,[ComponentDesc]
        ,[PerAssemblyQty]
        ,[StandardCost]
        ,[ListPrice]
        ,[BOMLevel]
        ,[RecursionLevel]
        ) -- CTE name and columns
    AS (
            SELECT b.[ProductAssemblyID]
            ,b.[ComponentID]
            ,p.[Name]
            ,b.[PerAssemblyQty]
            ,p.[StandardCost]
            ,p.[ListPrice]
            ,b.[BOMLevel]
            ,0 -- Get the initial list of components for the bike assembly
        FROM [Production].[BillOfMaterials] b
        INNER JOIN [Production].[Product] p ON b.[ComponentID] = p.[ProductID]
        WHERE b.[ProductAssemblyID] = @StartProductID
            AND @CheckDate >= b.[StartDate]
            AND @CheckDate <= ISNULL(b.[EndDate], @CheckDate)

        UNION ALL

        SELECT b.[ProductAssemblyID]
            ,b.[ComponentID]
            ,p.[Name]
            ,b.[PerAssemblyQty]
            ,p.[StandardCost]
            ,p.[ListPrice]
            ,b.[BOMLevel]
            ,[RecursionLevel] + 1 -- Join recursive member to anchor
        FROM [BOM_cte] cte
        INNER JOIN [Production].[BillOfMaterials] b ON b.[ProductAssemblyID] = cte.[ComponentID]
        INNER JOIN [Production].[Product] p ON b.[ComponentID] = p.[ProductID]
        WHERE @CheckDate >= b.[StartDate]
            AND @CheckDate <= ISNULL(b.[EndDate], @CheckDate)
        )
    -- Outer select from the CTE
    SELECT b.[ProductAssemblyID]
        ,b.[ComponentID]
        ,b.[ComponentDesc]
        ,SUM(b.[PerAssemblyQty]) AS [TotalQuantity]
        ,b.[StandardCost]
        ,b.[ListPrice]
        ,b.[BOMLevel]
        ,b.[RecursionLevel]
    FROM [BOM_cte] b
    GROUP BY b.[ComponentID]
        ,b.[ComponentDesc]
        ,b.[ProductAssemblyID]
        ,b.[BOMLevel]
        ,b.[RecursionLevel]
        ,b.[StandardCost]
        ,b.[ListPrice]
    ORDER BY b.[BOMLevel]
        ,b.[ProductAssemblyID]
        ,b.[ComponentID]
    OPTION (MAXRECURSION 25)
END;

SET @logrowcount = CONVERT(VARCHAR(36), @@ROWCOUNT)

IF @logrowcount = '0'
BEGIN
    SET @ReturnCode = 999
 END

RETURN @ReturnCode

请有人指教。如何使它工作并返回返回码?

编辑:我在评论中问的最后一个问题是不是。我的问题格式不正确。

我不是要问有关如何获取结果集的一般性问题。我问我从语句中读取返回代码后如何获得结果集

问题是我老板的存储过程正在返回一个代码,该代码除其他外可以告诉我结果集中是否需要获取数据。不幸的是,如果我使用statement.getInt()读取代码,则ResultSet对象被“关闭”,并且在获得返回代码说有数据I之后,由于ResultSet的关闭,ResultSet的getXXX()函数生成了一个例外。我实际上想问的是,是否有一种方法可以从CallableStatement中获取返回代码而不关闭ResultSet;或者相反,是否有一种方法可以在我抓住返回代码后重新打开ResultSet。提到的答案不能解决这个问题。

我的问题还意味着另外一个问题:我是否在CallableStatement API中发现错误?当然,这里没有任何地方回答该问题。

0 个答案:

没有答案