How to handle the loss of precision on JDBC numeric types due to grouping functions

百般思念 提交于 2019-12-22 08:08:29

问题


Oracle (and some other DB's) have a datatype NUMBER, with which one can optionally set the precision and scale.

Suppose the below query:

SELECT agent_code, 
AVG (opening_amt)
FROM customer 
GROUP BY agent_code;

If both fields in above query were defined as NUMBER(12,0), the result in JDBC is indeed that for agent_code, but on "AVG(opening_amt)" both precision and scale return 0 (via java.sql.ResultSetMetaData.getPrecision(col) and java.sql.ResultSetMetaData.getScale(col) .

That's basically the same as NUMBER, without any precision or scale specification, and according to oracle, would equal NUMBER(38,12).

The above loss of precision gives me a problem to determine if the sql type should be converted to Double or Integer.

So, I was wondering if this is actually a bug in Oracle's JDBC driver, or how this should be handled? (and no, using BigDecimal as corresponsting java type is not an option for me).


回答1:


This is speculation based on similar behaviour in the Postgres driver postgresql-9.4-1204-jdbc42.jar.

For an unspecified NUMERIC the database doesn't seem to store any particular information on the precision and scale of the column. This allows the database to internally store the value in any way it seems fit. From https://www.postgresql.org/docs/current/static/datatype-numeric.html

without any precision or scale creates a column in which numeric values of any precision and scale can be stored, up to the implementation limit on precision (up to 131072 digits before the decimal point; up to 16383 digits after the decimal point)

Since the driver doesn't know what the implementation specific maximum of the server is, it can't return the actual values. It returns 0 to indicate that it doesn't know the actual values, and doesn't want to make any educated guesses.

Seems like the situation is the same with Oracle. The max precision may be higher, but portability is guaranteed only up to 38 digits.

Numbers of virtually any magnitude can be stored and are guaranteed portable among different systems operating Oracle Database, up to 38 digits of precision.

As for solving the issue in the question, like StanislavL indicated you can force the value to a specific precision/scale by casting.




回答2:


I think you can cast to any desired type

CAST(AVG(opening_amt) AS DECIMAL(12,2))

See the example

The SQL AVG() function returns the average value with default decimal places. The CAST() is used to increase or decrease the decimal places of a value. The CAST() function is much better at preserving the decimal places when converting decimal and numeric data types. The 'AS DECIMAL' followed by the format specification is used with CAST() for making a numeric value to a specific decimal place value.



来源:https://stackoverflow.com/questions/45855174/how-to-handle-the-loss-of-precision-on-jdbc-numeric-types-due-to-grouping-functi

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!