I am constructing a database where I need to store currency values. I am storing the currency values as cents ($100.00 = 10000 ¢). So, I decided against using INT to store the currency values (a signed int is limited to storing $21,474,836.48).
I saw that MySQL has two other similar types: BIGINT and LONG.
After researching and not being able to figure out the difference, I made an arbitrary decision to use BIGINT. But then when I went to write the 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
There is no PreparedStatement::setBigInt() method. The only PreparedStatement methods that exist are setInt(), setLong(), and setBigDecimal.
So, then I reversed my decision and decided to use LONG instead, but when I went to write the same code, I noticed this:
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());
So the PreparedStatement does not have a setBigInt (or setBigInteger) method, and the java.sql.Types package does not contain a LONG enum.
The questions are:
BIGINT and LONG on the MySQL level? Which is more ideal for storing currencies?PreparedStatement::setLong on a BIGINT column?PreparedStatement::setBigDecimal on a BIGINT column? EDIT/UPDATE:
My apologies for the bad question. I had no idea that MySQL doesn't even have LONG datatypes. In part because the data modeler I am using to construct my database (MySQL's own: MySQL Workbench) does allow you to set LONG as a datatype. However, when you forward engineer the database, it changes the LONG to BIGINT.

(picture from MySQL Workbench datamodeler which I'm using to assist the construction of my DB).
What is the difference between
BIGINTandLONGon the MySQL level?
java.sql.Types.BIGINT is defined as:
The constant in the Java programming language, sometimes referred to as a type code, that identifies the generic SQL type
BIGINT.
Under Integer Types, the MySQL manual documents that its BIGINT datatype is an 8-byte (i.e. 64-bit) integer. The Java primitive datatype long (and its associated wrapper class java.lang.Long) also represents an 8-byte integer.
Consequently, as documented under Mapping SQL and Java Types:
The JDBC type
BIGINTrepresents a 64-bit signed integer value between-9223372036854775808and9223372036854775807.[ deletia — outdated ]The recommended Java mapping for the
BIGINTtype is as a Javalong.
There is no LONG constant within java.sql.Types, nor does MySQL have a LONG datatype.
Which is more ideal for storing currencies?
Neither. Store the dollar amount as a discrete decimal value using the NUMERIC fixed-point datatype. If you insist on storing the cent amount in an integer type, the "correct" answer depends merely on the anticipated range of values that you wish to support.
What would happen if I use
PreparedStatement::setLongon aBIGINTcolumn?
That is exactly how one should set the value of a BIGINT parameter. As documented under java.sql.PreparedStatement::setLong(int, long):
The driver converts this to an SQL
BIGINTvalue when it sends it to the database.
That also begs the question, what happens if I use
PreparedStatement::setBigDecimalon aBIGINTcolumn?
As documented under java.sql.PreparedStatement::setBigDecimal(int, java.math.BigDecimal):
The driver converts this to an SQL
NUMERICvalue when it sends it to the database.
So, Java will send your value to MySQL as a NUMERIC (fixed-point decimal) datatype. MySQL will then perform type conversion as described under Type Conversion in Expression Evaluation: e.g. if you are simply storing the value in a BIGINT column, the value will be cast to a BIGINT for storage. Provided that the value is in range for a BIGINT, you shouldn't notice any ill-effect (except loss of the fractional part).
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With