我正在构建一个我需要存储货币值的数据库。我将货币值存储为美分($ 100.00 = 10000¢)。所以,我决定不使用INT
来存储货币值(有符号的int仅限于存储$21,474,836.48
)。
我看到MySQL有两种类似的类型:BIGINT
和LONG
。
在研究并且无法弄清楚差异之后,我决定使用BIGINT
。但是当我去编写PreparedStatement时:
int id = ...;
BigInteger amount = ...;
String sql = "insert into transaction(id, amount) VALUES(?,?)";
PreparedStatement pstmt = conn.prepareStatement(sql);
pstmt.setInt(1, id);
if(amount == null)
pstmt.setNull(2, java.sql.Types.BIGINT);
else
pstmt.setBigInteger(2, amount); // <---- This method does not exist
没有PreparedStatement::setBigInt()
方法。唯一存在的PreparedStatement
方法是setInt()
,setLong()
和setBigDecimal
。
所以,然后我改变了我的决定并决定使用LONG
代替,但当我去编写相同的代码时,我注意到了这一点:
int id = ...;
BigInteger amount = ...;
String sql = "insert into transaction(id, amount) VALUES(?,?)";
PreparedStatement pstmt = conn.prepareStatement(sql);
pstmt.setInt(1, id);
if(amount == null)
pstmt.setNull(2, java.sql.Types.LONG); // <---- This java.sql.Type does not exist
else
pstmt.setLong(2, amount.longValue());
因此PreparedStatement
没有setBigInt
(或setBigInteger
)方法,java.sql.Types
包不包含LONG
枚举。
问题是:
BIGINT
和LONG
之间有什么区别?哪个更适合存储货币?PreparedStatement::setLong
列上使用BIGINT
会怎样?PreparedStatement::setBigDecimal
列上使用BIGINT
会怎样? EDIT / UPDATE:
我为这个糟糕的问题道歉。我不知道MySQL甚至没有LONG
数据类型。部分是因为我用来构建数据库的数据建模器(MySQL自己的:MySQL Workbench)确实允许你将LONG
设置为数据类型。但是,当您对数据库进行正向工程时,它会将LONG
更改为BIGINT
。
(来自MySQL Workbench datamodeler的图片,我用它来帮助构建我的数据库)。
答案 0 :(得分:8)
MySQL级别
BIGINT
和LONG
之间有什么区别?
Java编程语言中的常量(有时称为类型代码),用于标识通用SQL类型
BIGINT
。
在Integer Types下,MySQL手册记录了它的BIGINT
数据类型是一个8字节(即64位)的整数。 Java primitive datatype long
(及其关联的包装类java.lang.Long
)也表示一个8字节的整数。
因此,如Mapping SQL and Java Types所述:
JDBC类型
BIGINT
表示-9223372036854775808
和9223372036854775807
之间的64位有符号整数值。[ deletia — outdated ]
BIGINT
类型的推荐Java映射是Javalong
。
java.sql.Types
内没有LONG
常量,MySQL也没有LONG
数据类型。
哪种货币更理想?
都不是。使用NUMERIC
定点数据类型将美元金额存储为离散十进制值。如果您坚持将分数存储在整数类型中,则“正确”答案仅取决于您希望支持的预期值范围。
如果我在
PreparedStatement::setLong
列上使用BIGINT
会怎样?
这正是应设置BIGINT
参数值的方式。正如java.sql.PreparedStatement::setLong(int, long)
所述:
驱动程序在将其发送到数据库时将其转换为SQL
BIGINT
值。
这也引出了一个问题,如果我在
PreparedStatement::setBigDecimal
列上使用BIGINT
会怎样?
正如java.sql.PreparedStatement::setBigDecimal(int, java.math.BigDecimal)
所述:
驱动程序在将其发送到数据库时将其转换为SQL
NUMERIC
值。
因此,Java会将您的值作为NUMERIC
(定点十进制)数据类型发送给MySQL。然后,MySQL将按照Type Conversion in Expression Evaluation中的描述执行类型转换:例如如果您只是将值存储在BIGINT
列中,则该值将转换为BIGINT
进行存储。如果该值在BIGINT
的范围内,您不应该注意到任何不良影响(除了丢失小数部分)。