有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

java在MySQL中存储美元金额:INT vs LONG vs BIGINT

我正在构建一个数据库,需要在其中存储货币值。我将货币值存储为美分($100.00=10000)。因此,我决定不使用INT来存储货币值(带符号的int仅限于存储$21,474,836.48

我看到MySQL还有两种类似的类型:BIGINTLONG

在研究之后,我无法找出其中的区别,于是我决定使用BIGINT。但当我去写准备好的声明时:

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枚举

问题是:

  1. 在MySQL级别上BIGINTLONG之间有什么区别?哪个更适合储存货币
  2. 如果我在BIGINT列上使用PreparedStatement::setLong,会发生什么
  3. 这也引出了一个问题,如果我在BIGINT列上使用PreparedStatement::setBigDecimal,会发生什么

编辑/更新:

我为这个糟糕的问题道歉。我不知道MySQL甚至没有LONG数据类型。部分原因是我用来构建数据库的数据建模器(MySQL自己的:MySQL Workbench)允许您将LONG设置为数据类型。但是,当您对数据库进行正向工程时,它会将LONG更改为BIGINT

picture from MySQL Workbench datamodeler which I'm using to assist the construction of my DB

(图片来自MySQL Workbench datamodeler,我正在使用它来帮助构建我的数据库)


共 (1) 个答案

  1. # 1 楼答案

    1. What is the difference between BIGINT and LONG on the MySQL level?

      • ^{}的定义如下:

        The constant in the Java programming language, sometimes referred to as a type code, that identifies the generic SQL type BIGINT.

        Integer Types下,MySQL手册记录了它的BIGINT数据类型是一个8字节(即64位)的整数。Java primitive datatype{}(及其关联的包装类^{})也表示一个8字节的整数

        因此,如Mapping SQL and Java Types所述:

        The JDBC type BIGINT represents a 64-bit signed integer value between -9223372036854775808 and 9223372036854775807.

        [ deletia — outdated ]

        The recommended Java mapping for the BIGINT type is as a Java long.

      • ^{}中没有LONG常量,MySQL也没有LONG数据类型

      Which is more ideal for storing currencies?

      都不是。使用^{}定点数据类型将美元金额存储为离散十进制值。如果您坚持以整数类型存储分金额,“正确”答案仅取决于您希望支持的预期值范围

    2. What would happen if I use PreparedStatement::setLong on a BIGINT column?

      这正是应该设置BIGINT参数值的方式。如^{}所述:

      The driver converts this to an SQL BIGINT value when it sends it to the database.

    3. That also begs the question, what happens if I use PreparedStatement::setBigDecimal on a BIGINT column?

      ^{}所述:

      The driver converts this to an SQL NUMERIC value when it sends it to the database.

      因此,Java将把您的值作为^{}(定点十进制)数据类型发送到MySQL。MySQL随后将按照Type Conversion in Expression Evaluation中的描述执行类型转换:例如,如果您只是将值存储在BIGINT列中,则该值将转换为BIGINT存储。如果该值在BIGINT的范围内,则不应注意到任何不良影响(小数部分丢失除外)