使用SQL子查询对表中的行数进行计数,并根据结果通过/失败Java测试

时间:2018-10-20 14:22:39

标签: java sql sql-server subquery

下面是我的两个SQL Server表。

地址

addressId | addressName |
2         | testAddress |

链接

linkId | clientId | addressId |
1      | 4        | 2         |

我正在尝试编写一个Java测试,该测试使用SQL子查询来检查taddress中是否存在记录。

例如:

SELECT COUNT(*) FROM Taddress
WHERE addressId =
(SELECT addressId FROM Tlink
WHERE clientId = param)

目前,当我运行以下测试时,即使tLink中不存在clientId参数,测试也始终会通过。

try {
        dbAccessSetUp();
        ResultSet rs = stmt.executeQuery("SELECT COUNT(*) FROM taddress a INNER JOIN tlink l on a.address_id = l.internal_address_id WHERE l.ext_client_id =" + this.clientNo);

        if(!rs.next()) {
            fail("Record does not exist in taddress based on ExtClientNo");
        }

        int count = 0;

        while(rs.next()) {              

            count = rs.getInt(1);
            System.out.println("number of count : " + count);
            assertTrue(0 < count);
        } 
        rs.close(); 
    } catch(SQLException se) { 
        se.printStackTrace(); 
        assertEquals(true, false);
    } catch(Exception e) { 
        e.printStackTrace();
        assertEquals(true, false);
    } finally { 
        try { 
            if(stmt!=null) stmt.close();  
        } catch(SQLException se2) {
            assertEquals(true, false);
        } 
        try { 
            if(conn!=null) conn.close(); 
        } catch(SQLException se) {
            se.printStackTrace(); 
            assertEquals(true, false);
        } 
    } 

3 个答案:

答案 0 :(得分:0)

对于您的查询,该查询将在没有任何错误的情况下运行,直到您在Tlink表中有多于一行的记录为止,因此最好将其更改为简单的联接,

SELECT COUNT(*)
FROM Taddress A INNER JOIN Tlink L ON A.addressId = L.addressId
WHERE L.clientId = Param;

现在,我们同意该查询将返回正确的结果,但是您的Java代码无法按您提到的那样正常工作

  

此刻,当我使用上述查询运行测试时,即使tLink中不存在clientId参数,测试也始终会通过。

上面的查询将仅返回一行(一个值),因此您无需循环且此代码无用

while(rs.next()){
    count = rs.getInt(1);
    assertTrue(0 < count);
}

您所需要的全部都是获取查询返回的值,并检查其是否大于0,例如

count =  ((Number) rs.getObject(1)).intValue();
int cmp;
if (count > 0)
// Exists;
else 
//Not exists;

assertTrue(count.equals(0));

答案 1 :(得分:0)

进行查询:

SELECT COUNT(*) 
FROM taddress a INNER JOIN tlink l on a.addressid = l.addressID
WHERE l.clientid = @param

如果符合以下条件,则返回0:

  • 该参数没有链接
  • 该链接没有地址

如果您想知道关系破裂的地方:

SELECT COUNT(*) as count_link, COUNT(a.addressid) as count_address 
FROM taddress a RIGHT JOIN tlink l on a.addressid = l.addressID
WHERE l.clientid = @param

关于断言计数始终大于0的断言,无论您传递的是什么@param,我都希望看到一些其他的调试/截屏/打印输出等信息表明

编辑

所以您的代码存在以下问题:

您运行sql,然后调用if(!rs.hasNext())

您的结果集确实有一行,因此对rs.next的调用返回true,您对此取反,以便if测试返回false,如果if不运行,并且结果集现在指向该行的第一行数据查询。 唯一的数据行-您现在应该读取数据,但是您不需要...

接下来,您说while(rs.hasNext())将使结果集前进另一行,因此不再指向计数数据。没有更多的数据行,因此此调用返回false,并且您的循环主体永不运行-您永远不会从结果集中提取任何数据,您的断言永远不会运行等

重新编写代码,以便在第一个if中执行assert()并放弃while循环

if(rs.next())
  assert(rs.getInt(1) > 0);

这种形式的计数查询将始终返回一行,几乎没有意义地测试结果集是否没有数据。如果查询运行失败,则会生成异常

答案 2 :(得分:0)

根据上面的代码示例,这应该对您有用:

try {
        dbAccessSetUp();
        ResultSet rs = stmt.executeQuery("SELECT COUNT(*)FROM taddress A INNER JOIN tlink L ON A.address_id = L.internal_address_id WHERE L.ext_client_id =" + this.clientNo);
        int count=0;
        while(rs.next()) {
            count =  ((Number) rs.getObject(1)).intValue();

        }

        if(count > 0) {
            assertTrue(true);
            System.out.println(count + " record(s) in taddress based on ExtClientNo");
        }
        else {
            fail("No records in taddress");
        }

    }catch(Exception ex) {
        System.out.println(ex.getMessage());
    }

在以下情况下,此操作将失败:

  • tlink中没有与您的客户匹配的记录否
  • tlink中有匹配的记录,但taddress中没有匹配的记录

在以下情况下将通过

  • tlink中有一条匹配的记录,而taddress中有一条匹配的记录