Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/304.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 对于空的SELECT结果,T-SQL存储过程不会按计数(*)返回零_Java_Sql Server_Spring_Tsql_Stored Procedures - Fatal编程技术网

Java 对于空的SELECT结果,T-SQL存储过程不会按计数(*)返回零

Java 对于空的SELECT结果,T-SQL存储过程不会按计数(*)返回零,java,sql-server,spring,tsql,stored-procedures,Java,Sql Server,Spring,Tsql,Stored Procedures,我使用Spring框架的StoredProcedure(当然,我正在扩展它)来获得一个结果集和一个输出参数(@totalRowsReturned)。问题是,当返回的resultset应该是一个空列表时,当我尝试检索输出参数(totalRows,我天真地认为它是零)时,会得到一个NullPointerException 我想提到的是,当找到的结果集不是空的时候,代码可以正常工作 我的问题是: List<Book> books = null; int totalRows = 0; Ma

我使用Spring框架的
StoredProcedure
(当然,我正在扩展它)来获得一个结果集和一个输出参数(
@totalRowsReturned
)。问题是,当返回的resultset应该是一个空列表时,当我尝试检索输出参数(totalRows,我天真地认为它是零)时,会得到一个
NullPointerException

我想提到的是,当找到的结果集不是空的时候,代码可以正常工作

我的问题是:

List<Book> books = null;
int totalRows = 0;

Map<String, Object> results = storedProcedure.execute(parameters);
books = (List<Book>) results.get("rs");
totalRows = (Integer) results.get("totalRowsReturned"); // NullPointerException on this line if total rows are supposed to be zero!!
CREATE PROCEDURE Find_Books

    @authorName Varchar(250),   
    @totalRowsReturned INTEGER OUTPUT

AS

BEGIN

    SET NOCOUNT ON;
    DECLARE @SelectQuery NVARCHAR(2000)

    SET @SelectQuery = 'SELECT @totalRows=COUNT(*) OVER() FROM book b WHERE b.author_name = @authorName'

    Execute sp_Executesql @SelectQuery, N'@authorName VARCHAR(250), @totalRows int OUTPUT', @authorName, @totalRows=@totalRowsReturned OUTPUT

-- Select resultset goes here...

END
  • 在这种情况下,为什么不将
    @totalrowsreturn
    设置为零?(如果是,为什么我不能通过Java代码检索它?)

  • 如何使此代码(Java代码+T-SQL代码)在需要时将
    @totalRowsReturned
    设置为零,并通过Java代码检索它

  • Dao:

    List<Book> books = null;
    int totalRows = 0;
    
    Map<String, Object> results = storedProcedure.execute(parameters);
    books = (List<Book>) results.get("rs");
    totalRows = (Integer) results.get("totalRowsReturned"); // NullPointerException on this line if total rows are supposed to be zero!!
    
    CREATE PROCEDURE Find_Books
    
        @authorName Varchar(250),   
        @totalRowsReturned INTEGER OUTPUT
    
    AS
    
    BEGIN
    
        SET NOCOUNT ON;
        DECLARE @SelectQuery NVARCHAR(2000)
    
        SET @SelectQuery = 'SELECT @totalRows=COUNT(*) OVER() FROM book b WHERE b.author_name = @authorName'
    
        Execute sp_Executesql @SelectQuery, N'@authorName VARCHAR(250), @totalRows int OUTPUT', @authorName, @totalRows=@totalRowsReturned OUTPUT
    
    -- Select resultset goes here...
    
    END
    
    更新:

    List<Book> books = null;
    int totalRows = 0;
    
    Map<String, Object> results = storedProcedure.execute(parameters);
    books = (List<Book>) results.get("rs");
    totalRows = (Integer) results.get("totalRowsReturned"); // NullPointerException on this line if total rows are supposed to be zero!!
    
    CREATE PROCEDURE Find_Books
    
        @authorName Varchar(250),   
        @totalRowsReturned INTEGER OUTPUT
    
    AS
    
    BEGIN
    
        SET NOCOUNT ON;
        DECLARE @SelectQuery NVARCHAR(2000)
    
        SET @SelectQuery = 'SELECT @totalRows=COUNT(*) OVER() FROM book b WHERE b.author_name = @authorName'
    
        Execute sp_Executesql @SelectQuery, N'@authorName VARCHAR(250), @totalRows int OUTPUT', @authorName, @totalRows=@totalRowsReturned OUTPUT
    
    -- Select resultset goes here...
    
    END
    
    实际上,我的存储过程看起来更像这样(更改是SELECT中的附加
    @first\u id=b.book\u id
    ):

    问题是,当SELECT没有返回行时,没有定义b.book_id,因此我得到一个
    org.springframework.dao.TransientDataAccessResourceException。。。“book.book\u id”列在选择列表中无效,因为它未包含在聚合函数或GROUP BY子句中。

    因此,似乎如果我保持
    OVER()
    ,那么
    @totalRows=COUNT(*)OVER()
    在返回零行时失败,如果我删除
    OVER()
    ,那么
    @first\u id=b.book\u id
    失败

    你知道我是如何克服这个问题的吗?

    COUNT(*)OVER()
    在这里使用不正确。只需使用
    COUNT(*)

    COUNT(*)OVER()
    返回一个结果集,其行数与
    计数的行数相同。e、 g如果结果为3,则结果集为

    3
    3
    3
    
    然后,查询的效果是重复将值
    3
    重新分配给
    @totalRows
    变量,分配的次数与完全没有意义的行的次数相同

    相反,如果
    COUNT(*)=0
    ,则()上的
    COUNT(*)结果集为空,因此您的变量根本不会被赋值

    COUNT(*)
    将始终在此处为您提供一个单行标量结果集,您可以将该结果集分配给变量,并且将有一个更高效的执行计划,而无需使用不必要的公共子表达式假脱机

    编辑

    回应您在评论中提出的问题。这与链接文章的作用相同。它可以使用一个更窄的索引来查找(比如)第10000名员工,然后仅为随后的1页记录加入部门。这种分页方法只能正常工作,因为每个员工只有一个部门

    WITH E1(RN, EmployeeID)
         AS (SELECT ROW_NUMBER() OVER (ORDER BY EmployeeID),
                    EmployeeID
             FROM   Employees)
    SELECT TOP (@maximumRows) e.*,
                              d.Name AS DepartmentName
    FROM   Employees e
           INNER JOIN Departments d
             ON e.DepartmentID = d.DepartmentID
    WHERE  EmployeeID >= (SELECT EmployeeID
                          FROM   E1
                          WHERE  RN = @startRowIndex)
    ORDER  BY e.EmployeeID  
    
    COUNT(*)OVER()
    在这里使用不正确。只需使用
    COUNT(*)

    COUNT(*)OVER()
    返回一个结果集,其行数与
    计数的行数相同。e、 g如果结果为3,则结果集为

    3
    3
    3
    
    然后,查询的效果是重复将值
    3
    重新分配给
    @totalRows
    变量,分配的次数与完全没有意义的行的次数相同

    相反,如果
    COUNT(*)=0
    ,则()上的
    COUNT(*)结果集为空,因此您的变量根本不会被赋值

    COUNT(*)
    将始终在此处为您提供一个单行标量结果集,您可以将该结果集分配给变量,并且将有一个更高效的执行计划,而无需使用不必要的公共子表达式假脱机

    编辑

    回应您在评论中提出的问题。这与链接文章的作用相同。它可以使用一个更窄的索引来查找(比如)第10000名员工,然后仅为随后的1页记录加入部门。这种分页方法只能正常工作,因为每个员工只有一个部门

    WITH E1(RN, EmployeeID)
         AS (SELECT ROW_NUMBER() OVER (ORDER BY EmployeeID),
                    EmployeeID
             FROM   Employees)
    SELECT TOP (@maximumRows) e.*,
                              d.Name AS DepartmentName
    FROM   Employees e
           INNER JOIN Departments d
             ON e.DepartmentID = d.DepartmentID
    WHERE  EmployeeID >= (SELECT EmployeeID
                          FROM   E1
                          WHERE  RN = @startRowIndex)
    ORDER  BY e.EmployeeID  
    

    您需要在
    b.book\u id
    上使用聚合函数

    您可以使用
    min()

    或者
    max()

    SELECT @first_id = max(b.book_id), @totalRows=COUNT(*) FROM book ...
    

    您需要在
    b.book\u id
    上使用聚合函数

    您可以使用
    min()

    或者
    max()

    SELECT @first_id = max(b.book_id), @totalRows=COUNT(*) FROM book ...
    

    我不能100%确定您想要做什么,但我认为是这样的(在这种情况下,您确实不需要动态SQL):


    我不能100%确定您想要做什么,但我认为是这样的(在这种情况下,您确实不需要动态SQL):


    您的
    WHERE
    FROM
    似乎走错了方向。还有,为什么您要使用
    COUNT(*)OVER()
    而不仅仅是
    COUNT(*)
    ?请尝试删除
    OVER()
    。当您使用
    OVER()
    并且没有点击时,您将不会得到任何行。如果没有
    OVER()
    您将始终得到1行。@Martin Smith-对不起-这是我的打字错误。我刚刚纠正了我的问题。正如我上面所说的,该代码对于零行以外的情况工作良好。@rapt。它适用于这些情况,但效率低下。它重复地将相同的值重新分配给变量。您应该只使用
    COUNT(*)
    来获得单行结果。@Mikael Eriksson-我想我没有得到您。当没有点击时,我不想得到任何行:没有点击,这意味着零结果,零行。如果没有
    OVER()
    -当有零行时,我为什么要得到一行那一行是什么?你的
    WHERE
    FROM
    似乎走错了方向。还有,为什么您要使用
    COUNT(*)OVER()
    而不仅仅是
    COUNT(*)
    ?请尝试删除
    OVER()
    。当您在上面使用