在MySQL中存储美元金额:INT与LONG对比BIGINT

ryv*_*age 3 java mysql prepared-statement bigint long-integer

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

我看到MySQL有两个类似的类型:BIGINTLONG.

在研究并且无法弄清楚差异之后,我做出了一个随意的决定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
Run Code Online (Sandbox Code Playgroud)

没有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());
Run Code Online (Sandbox Code Playgroud)

所以PreparedStatement没有setBigInt(或setBigInteger)方法,并且java.sql.Types包不包含LONG枚举.

问题是:

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

编辑/ UPDATE:

我为这个糟糕的问题道歉.我不知道MySQL甚至没有LONG数据类型.部分是因为我用来构建数据库的数据建模器(MySQL自己的:MySQL Workbench)确实允许你设置LONG为数据类型.但是,当您转发工程师数据库时,它会更改LONGBIGINT.

来自MySQL Workbench datamodeler的图片,我用它来帮助构建我的数据库

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

egg*_*yal 8

  1. MySQL级别BIGINT和之间有什么区别LONG

    • java.sql.Types.BIGINT 定义为:

      标识一般SQL类型的Java编程语言中的常量(有时称为类型代码)BIGINT.

      整数类型下,MySQL手册记录其BIGINT数据类型是一个8字节(即64位)整数.Java 原始数据类型 long(及其关联的包装类java.lang.Long)也表示8字节整数.

      因此,如映射SQL和Java类型中所述:

      JDBC类型BIGINT表示-9223372036854775808和之间的64位有符号整数值9223372036854775807.

      [ deletia — outdated ]

      BIGINT类型的推荐Java映射是Java long.

    • 内部没有LONG常数java.sql.Types,MySQL也没有LONG数据类型.

    哪个更适合存储货币?

    都不是.使用NUMERIC定点数据类型将美元金额存储为离散十进制值.如果您坚持将分数存储在整数类型中,则"正确"答案仅取决于您希望支持的预期值范围.

  2. 如果我PreparedStatement::setLongBIGINT列上使用会发生什么?

    这正是应该如何设置BIGINT参数的值.由于根据记载java.sql.PreparedStatement::setLong(int, long):

    驱动程序在将BIGINT其发送到数据库时将其转换为SQL 值.

  3. 这也引出了一个问题,如果我PreparedStatement::setBigDecimalBIGINT列上使用会发生什么?

    由于根据记载java.sql.PreparedStatement::setBigDecimal(int, java.math.BigDecimal):

    驱动程序在将NUMERIC其发送到数据库时将其转换为SQL 值.

    因此,Java会将您的值作为NUMERIC(定点十进制)数据类型发送给MySQL .然后MySQL将执行类型转换,如表达式评估中的类型转换所述:例如,如果您只是将值存储在BIGINT列中,则该值将转换BIGINT为存储.如果该值在a的范围内BIGINT,您不应该注意到任何不良影响(除了小数部分的丢失).