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

时间:2014-05-08 18:00:45

标签: java mysql prepared-statement long-integer bigint

我正在构建一个我需要存储货币值的数据库。我将货币值存储为美分($ 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

没有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. 如果我在PreparedStatement::setLong列上使用BIGINT会怎样?
  3. 这也引出了一个问题,如果我在PreparedStatement::setBigDecimal列上使用BIGINT会怎样?
  4. EDIT / UPDATE:

    我为这个糟糕的问题道歉。我不知道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 个答案:

答案 0 :(得分:8)

  1.   

    MySQL级别BIGINTLONG之间有什么区别?

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

        

      Java编程语言中的常量(有时称为类型代码),用于标识通用SQL类型BIGINT

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

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

        

      JDBC类型BIGINT表示-92233720368547758089223372036854775807之间的64位有符号整数值。

      [ deletia — outdated ]
           

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

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

      

    哪种货币更理想?

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

  2.   

    如果我在PreparedStatement::setLong列上使用BIGINT会怎样?

    这正是设置BIGINT参数值的方式。正如java.sql.PreparedStatement::setLong(int, long)所述:

      

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

  3.   

    这也引出了一个问题,如果我在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的范围内,您不应该注意到任何不良影响(除了丢失小数部分)。