我理解这个问题取决于供应商,但是如果像SUM
这样的聚合函数对小类型进行操作,我应该担心吗?
例如,MariaDB对类型INT
使用4个字节。开发人员可能会假设每笔交易的金额不会超过几千。
但如果我们试图让所有部门获得一整年的收入会怎样呢? E.g:
-- CREATE TABLE income (dt DATETIME, department INT, amount INT);
SELECT SUM(amount) FROM income WHERE dt BETWEEN '2014-01-01' and '2014-12-31'
增加存储空间只是为了修复聚合函数SUM
的溢出问题,这看起来很愚蠢。
我应该担心什么? SQL 92/99/2008标准是否有任何保证或澄清?
JDBC驱动程序是否有任何特殊支持?
我应该在表格中重写选择:
SELECT SUM(CAST(amount AS BIGINT)) FROM income
WHERE dt BETWEEN '2014-01-01' and '2014-12-31'
答案 0 :(得分:3)
在mysql上测试相当容易:
32位溢出:
class MainThreadClass implements InputListner {
public MainThreadClass() {
InputRunner inputRunner = new InputRunner();
inputRunner.addInputListener(this);
Thread t = new Thread(new InputThread())
t.start();
}
@Override
public void inputReceived() {
//bla bla bla
}
}
class InputRunner implements Runnable {
ArrayList<InputListener> listeners = new ArrayList<InputLIsteners>();
public void run() {
//code to read input, when it is recieved execute fireInputReceived
}
public void addListener(InputListener listener) {
listeners.add(listener);
}
public void fireInputReceived(String input) {
//loop through all listeners
//fire inputRecieved on each
}
}
public Interface InputListener {
public void inputReceived(String input);
}
64位:
mysql> select sum(x) from (
select pow(2,31) as x
union all
select pow(2,31)
union all
select pow(2,31)
) as bignums;
+------------+
| sum(x) |
+------------+
| 6442450944 | // returned as a "bigint"
+------------+
1 row in set (0.00 sec)
双:
mysql> select sum(x) from (
select pow(2,63) as x
union all
select pow(2,63)
union all
select pow(2,63)
) as bignums;
+-----------------------+
| sum(x) |
+-----------------------+
| 2.7670116110564327e19 | // returned as float
+-----------------------+
1 row in set (0.00 sec)
在mysql上测试相当容易:
32位溢出:
mysql> select sum(x) from (
select 1.7e+308 as x
union all
select 1.7e+308
union all
select 1.7e+308
) as bignums;
+--------+
| sum(x) |
+--------+
| 0 |
+--------+
64位:
mysql> select sum(x) from (
select pow(2,31) as x
union all
select pow(2,31)
union all
select pow(2,31)
) as bignums;
+------------+
| sum(x) |
+------------+
| 6442450944 | // returned as a "bigint"
+------------+
1 row in set (0.00 sec)
双:
mysql> select sum(x) from (
select pow(2,63) as x
union all
select pow(2,63)
union all
select pow(2,63)
) as bignums;
+-----------------------+
| sum(x) |
+-----------------------+
| 2.7670116110564327e19 | // returned as float
+-----------------------+
1 row in set (0.00 sec)
评论后续:
mysql> select sum(x) from (
select 1.7e+308 as x
union all
select 1.7e+308
union all
select 1.7e+308
) as bignums;
+--------+
| sum(x) |
+--------+
| 0 |
+--------+
答案 1 :(得分:2)
Postgres处理这个没有溢出或截断:
从手册:
sum(表达式),返回类型:bigint用于smallint或int参数,numeric用于bigint参数,否则与参数数据类型相同
http://www.postgresql.org/docs/current/static/functions-aggregate.html
快速测试证明:
public extension Array where Element: (timeZoneName: String, formattedName: String){
}
有趣的是,在这种情况下,SQL标准要求语句失败:
如果在计算AF结果的过程中,中间结果在包含该中间结果的网站的声明类型中无法表示,那么
...
否则,会引发异常条件:数据异常 - 数值超出范围。
(AF =聚合函数)
答案 2 :(得分:1)
当我理解你的时候,你问的是在溢出的情况下会发生什么。
至少对于SQL Server,请查看以下文档:
https://msdn.microsoft.com/de-de/library/ms187810%28v=sql.120%29.aspx
这里说明了sum()
对特定输入类型的返回类型:
Expression result Return type
------------------------------------------------
tinyint int
smallint int
int int
bigint bigint
decimal category (p, s) decimal(38, s)
money and smallmoney category money
float and real category float
这意味着,可以确实是溢出。因此,我建议您使用float
或money
类型来获取工资,而不是类型int
。