0%

SQL-count(1)的返回类型

在不同数据库中,select(1)可能会有不同的返回类型。

ResultSet.getObject

不同的数据库对ResultSet接口有不同的实现。

  • MySQL的驱动jar包为mysql-connector-java-8.0.22.jar,实现方法为com.mysql.cj.jdbc.result.ResultSetImpl
  • Oracle的驱动jar包为ojdbc6-11.2.0.4.jar,实现方法为oracle.jdbc.driver.OracleResultSetImpl

代码示例

1
2
3
4
5
6
7
8
9
10
Connection conn = DriverManager.getConnection(URL, USER, PASSWORD);
Statement stmt = conn.createStatement();
ResultSet rs = stmt.executeQuery("select count(1) from task");
while(rs.next()){
int result = (int) rs.getObject(1);
System.out.println(result);
}
rs.close();
stmt.close();
conn.close();
  • 如果是MySQL,输出内容为java.lang.Long cannot be cast to java.lang.Integer
  • 如果是Oracle,输出内容为java.math.BigDecimal cannot be cast to java.lang.Integer

MySQL

MySQL支持SQL标准的整数类型INTEGER(INT) and SMALLINT,作为扩展,还支持三种整数类型TINYINTMEDIUMINTBIGINT,需要的字节和范围如下图所示。

类型 占用空间 有符号数范围 无符号数范围
TINYINT 1字节 -128~127 0~255
SMALLINT 2字节 -32768~32767 0~65535
MEDIUMINT 3字节 -8388608~8388607 0~16777215
INT 4字节 -2147483648~2147483647 0~4294967295
BIGINT 8字节 -2的63次方~2的63次方-1 0~2的64次方-1
  • COUNT(expr)返回结果不为null的行数,返回类型是BIGINT
  • 但COUNT(*)返回结果包含null的行数。

可以在Object getObject(int columnIndex)方法中,找到如下代码

1
2
case BIGINT:
return this.getLong(columnIndex);

所以返回Long类型。

Oracle

Oracle中count返回number类型。
会调用NumberCommonAccessor类的Object getObject(int var1)方法,主要代码如下

1
2
3
4
5
if (this.statement.connection.j2ee13Compliant && this.precision != 0 && this.scale == -127) {
var2 = new Double(this.getDouble(var1));
} else {
var2 = this.getBigDecimal(var1);
}

所以返回BigDecimal类型。

解决方法

可以使用通用代码,先转化为Number再转为int,如

1
int result = ((Number)rs.getObject(1)).intValue();

总结

ResultSet接口的Object getObject(int columnIndex)方法,select(1)在Oracle驱动下返回类型是BigDecimal,在MySQL驱动下返回类型是Long。其中ResultSet接口又是很多方法的底层实现,包括Map<String,Object> map = jdbcTemplate.queryForMap(sql);JdbcUtils.getResultSetValue(rs,1);等方法。

参考资料