【问题标题】:Inserting unsigned 64-bit number into BigInt MySQL column using Java and JDBC使用 Java 和 JDBC 将无符号 64 位数字插入 BigInt MySQL 列
【发布时间】:2013-02-20 19:30:58
【问题描述】:

我搜索了这个问题的答案,但只找到了模糊的答案。这是问题所在: 我在 MySQL 中有一个示例表: 我的表 时间时间戳 数据 BigInt(20) 无符号

选择数据字段,以便它可以接受 2^64 最大值:18446744073709551616(20 位,因此 BigInt(20))。

我有一个包含无符号 64 位整数的 csv 文件。

现在我使用 Java 和 JDBC 来插入这些数据并遇到问题,因为 Java 没有无符号长。所以我尝试只传递字符串 - 但它失败了。

st = conn.prepareStatement("INSERT INTO pawan_table (mytime, data) VALUES(?, ?)");
st.setTimestamp(1, new Timestamp(86400000+i*1000));
st.setString(2, "18446744073709551616");
st.execute();

我也尝试过 Java 中的 BigInteger 类 - 但 JDBC 没有采用该类型的方法。我只能将 BigInteger 转换为已签名的“long”,这不是我想要的。例如:

BigInteger bi = new BigInteger(string_from_csv_file);
st.setLong(2, bi.longValue());

有趣的是 MySQL Workbench 可以插入这些数据——但它是用 c# 编写的!我需要用Java编写我的代码!

Java 程序员如何在 MySQL BigInt(20) 列中插入无符号 64 位数字?

【问题讨论】:

  • 您是否尝试过使用st.setLong(2, 18446744073709551616L);
  • 这将导致 Java 编译错误,因为它大于 LONG_MAX。我刚刚测试了它,它确实给出了编译错误。
  • 那么,你不能使用 Java 来做到这一点。

标签: java mysql jdbc unsigned


【解决方案1】:

您或许可以使用PreparedStatement.setObject 实现此目的。有一个变体接受指定值类型的参数:您可以传入 BigIntegerjava.sql.Types.BIGINT 并查看是否有效。

如果失败,那么您可以创建一个实现 SQLData 的辅助类并将其传递给 setObject

免责声明:我没有尝试过任何这些;它基于对 javadocs 的快速浏览。

【讨论】:

  • 感谢您的提示。此解决方案不起作用,因为 JDBC 驱动程序尝试将值转换为已签名的“long”。我将发布有效和无效的解决方案。
【解决方案2】:

所以这里是解决方案:

如果你不使用 prepare 语句而只是使用字符串 SQL 语句插入,你不必担心,因为 JDBC 只是将你的语句移动到 MySQL 服务器并且 MySQL 服务器可以正确地将字符串解析为无符号 64 数字(BigInt- 20).

如果您使用准备语句,那么您就有麻烦了。如果你这样做:

BigInteger bi = new BigInteger("18446744073709551615"); // max unsigned 64-bit number
statement.setObject(2, bi, Types.BIGINT);
statement.execute();

你会得到一个 MySqlDataTruncation 异常,因为 JDBC 想要将它截断为有符号长。

如果你这样做:

BigInteger bi = new BigInteger(new Long(Long.MAX_VALUE).toString());
statement.setObject(2, bi, Types.BIGINT);
statement.execute();

这将起作用,因为该值在 Java 的有符号长整数范围内。

所以总是有效的解决方法是:

BigInteger bi = new BigInteger("18446744073709551615"); // max unsigned 64-bit number
statement.setString(2, bi.toString());
statement.execute();

您最终将数据作为字符串传递并让 MySQL 服务器正确解析它。

有人应该修复 JDBC 驱动程序,因为无符号 64 位数字不断出现在许多统计应用程序中。

【讨论】:

  • 在你的问题中你说statement.setString(2, "18446744073709551616");失败了。这与statement.setString(2, bi.toString()) 有何不同?你能显示bi.toString 返回的内容吗?我很想看看有什么区别,因为这种形式的工作原理很奇怪。
  • 截至目前,我收到此解决方案的com.mysql.jdbc.MysqlDataTruncation: Data truncation: Out of range value for column '<column_name>' at row 1 错误。
【解决方案3】:

如果数据类型是 BIGINT UNSIGNED,这适用于 MySQL 后端。

以这种方式存储号码:

PreparedStatement statement = conn.prepareStatement("INSERT INTO Speeds (downSpeed) VALUES (?)");
statement.setObject(1, spd.downSpeed, Types.BIGINT);

使用原始的 getObject() 调用进行检索:

BigInteger downSpeed = (BigInteger) rs.getObject("downSpeed");

我尝试使用rs.getObject("downSpeed",BigInteger.class),但这给了我一个不受支持的转换错误。

注意 BIGINT UNSIGNED 类型可以存储的最大数字是 1.8 *10^9。见这里:MySQL DataTypes

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-11-10
    • 2015-06-20
    • 2022-01-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多