插入的 123 应该是 NUMERIC(5,2) return 123 还是 123.00?
Should NUMERIC(5,2) return 123 or 123.00 for the inserted 123?
假设我们有一个带有 NUMERIC(5,2)
的 table 并且我们将 123
作为 BigDecimal
.
插入
当我们 select 返回值时 - 它应该是 123
(如我们插入的那样)还是 123.00
?
我在其中一个项目中从 HSQLDB 1.8.0.10 迁移到 2.3.3 时遇到了这个问题。
在 1.8.0.10 中,我得到了插入值的比例(123
表示插入的 123
)。
在 2.3.3 中,无论如何我都会得到列的比例(123.00
对于插入的 123
)。
我已经 reported this as a bug 但得到了以下回复:
But NUMERIC(5,2) means there is always 2 fractional digits no matter what you insert. Version 1.8 wasn't following the SQL Standard definition.
我不知道这是否正确,但我觉得这不符合逻辑。
我们真的应该在小数部分得到这些零吗,"no matter what"?
这是我的测试用例:
Connection conn = DriverManager.getConnection(...);
Statement stmt = conn.createStatement();
stmt.executeUpdate("create table test (value NUMERIC(5,2));");
String sql = "INSERT INTO test (value) VALUES(?)";
PreparedStatement pstmt = conn.prepareStatement(sql);
pstmt.setBigDecimal(1, BigDecimal.ONE);
pstmt.executeUpdate();
ResultSet rs = stmt.executeQuery("SELECT * FROM test");
while (rs.next()) {
Assert.assertEquals(BigDecimal.ONE, rs.getBigDecimal(1));
}
rs.close();
stmt.close();
conn.close();
当您将 123
插入 NUMERIC(5,2)
列时,正确的值应该是 123.00
。这是真的,因为对于数字,值总是被转换为具有目标数据类型的精度。在您的情况下,指定的精度为 5,您的比例为 2。只有比例为 0 的数字才是整数。
From SQL-1992 standard: 4.4.1 Characteristics of numbers
The scale is a
non-negative integer. A scale of 0 indicates that the number is an
integer.
[...]
Whenever an exact or approximate numeric value is assigned to a
data item or parameter representing an exact numeric value, an
approximation of its value that preserves leading significant dig-
its after rounding or truncating is represented in the data type
of the target. The value is converted to have the precision and
scale of the target. The choice of whether to truncate or round is
implementation-defined.
[...]
Whenever an exact or approximate numeric value is assigned to a
data item or parameter representing an approximate numeric value,
an approximation of its value is represented in the data type of
the target. The value is converted to have the precision of the
target.
想象一个 VARCHAR(50)
列,它将 return VARCHAR(3)
键入一个存储在其中的字符串,该字符串仅包含 3 个字符。那不是很奇怪吗?
上面的例子是有效的,因为如果我们 trim 值 123.00
到 123
它将不再是有效的 numeric(5,2)
数据类型。转换已就位,可让您插入该值而不会引发错误。
此外,在这种特殊情况下,您来自 2005.07.11
的 HSQL 1.8.0.1
的旧版本显然没有遵循 SQL 标准。从他们的 site:
上可以读到
HyperSQL 2 supports the dialect of SQL defined by SQL standards 92, 1999, 2003, 2008 and 2011. This means where a feature of the standard is supported, e.g. left outer join, the syntax is that specified by the standard text. Almost all syntactic features of SQL-92 up to Advanced Level are supported, as well as SQL:2011 core and many optional features of this standard.
假设我们有一个带有 NUMERIC(5,2)
的 table 并且我们将 123
作为 BigDecimal
.
当我们 select 返回值时 - 它应该是 123
(如我们插入的那样)还是 123.00
?
我在其中一个项目中从 HSQLDB 1.8.0.10 迁移到 2.3.3 时遇到了这个问题。
在 1.8.0.10 中,我得到了插入值的比例(123
表示插入的 123
)。
在 2.3.3 中,无论如何我都会得到列的比例(123.00
对于插入的 123
)。
我已经 reported this as a bug 但得到了以下回复:
But NUMERIC(5,2) means there is always 2 fractional digits no matter what you insert. Version 1.8 wasn't following the SQL Standard definition.
我不知道这是否正确,但我觉得这不符合逻辑。
我们真的应该在小数部分得到这些零吗,"no matter what"?
这是我的测试用例:
Connection conn = DriverManager.getConnection(...);
Statement stmt = conn.createStatement();
stmt.executeUpdate("create table test (value NUMERIC(5,2));");
String sql = "INSERT INTO test (value) VALUES(?)";
PreparedStatement pstmt = conn.prepareStatement(sql);
pstmt.setBigDecimal(1, BigDecimal.ONE);
pstmt.executeUpdate();
ResultSet rs = stmt.executeQuery("SELECT * FROM test");
while (rs.next()) {
Assert.assertEquals(BigDecimal.ONE, rs.getBigDecimal(1));
}
rs.close();
stmt.close();
conn.close();
当您将 123
插入 NUMERIC(5,2)
列时,正确的值应该是 123.00
。这是真的,因为对于数字,值总是被转换为具有目标数据类型的精度。在您的情况下,指定的精度为 5,您的比例为 2。只有比例为 0 的数字才是整数。
From SQL-1992 standard: 4.4.1 Characteristics of numbers
The scale is a non-negative integer. A scale of 0 indicates that the number is an integer.
[...]
Whenever an exact or approximate numeric value is assigned to a data item or parameter representing an exact numeric value, an approximation of its value that preserves leading significant dig- its after rounding or truncating is represented in the data type of the target. The value is converted to have the precision and scale of the target. The choice of whether to truncate or round is implementation-defined.
[...]
Whenever an exact or approximate numeric value is assigned to a data item or parameter representing an approximate numeric value, an approximation of its value is represented in the data type of the target. The value is converted to have the precision of the target.
想象一个 VARCHAR(50)
列,它将 return VARCHAR(3)
键入一个存储在其中的字符串,该字符串仅包含 3 个字符。那不是很奇怪吗?
上面的例子是有效的,因为如果我们 trim 值 123.00
到 123
它将不再是有效的 numeric(5,2)
数据类型。转换已就位,可让您插入该值而不会引发错误。
此外,在这种特殊情况下,您来自 2005.07.11
的 HSQL 1.8.0.1
的旧版本显然没有遵循 SQL 标准。从他们的 site:
HyperSQL 2 supports the dialect of SQL defined by SQL standards 92, 1999, 2003, 2008 and 2011. This means where a feature of the standard is supported, e.g. left outer join, the syntax is that specified by the standard text. Almost all syntactic features of SQL-92 up to Advanced Level are supported, as well as SQL:2011 core and many optional features of this standard.