Problema con Informix JDBC, SOLDI e separatore decimale in valori letterali stringa
Domanda
Ho un problema con JDBC applicazione che utilizza il tipo di dati MONEY.Quando inserisco in DENARO colonna:
insert into _money_test (amt) values ('123.45')
Ho avuto eccezione:
Character to numeric conversion error
Lo stesso SQL funziona da Windows nativo applicazione che utilizza il driver ODBC.Io vivo in Polonia e avere la traduzione polacca e nel mio paese virgola separa la parte decimale del numero, così ho provato:
insert into _money_test (amt) values ('123,45')
E ha funzionato.Ho controllato che in PreparedStatement devo usare il dot separatore: 123.45
.E, naturalmente, posso utilizzare:
insert into _money_test (amt) values (123.45)
Ma il codice è "generale", importazione dei dati da file csv, era sicuro di mettere il numero in stringa letterale.
Come forza di JDBC per uso DBMONEY (o semplicemente dot) nei letterali?
La mia workstation è WinXP.Ho ODBC e JDBC Informix client in versione 3.50 TC5/JC5.Ho impostato DBMONEY solo punto:
DBMONEY=.
EDIT:
Codice di Test in Jython:
import sys
import traceback
from java.sql import DriverManager
from java.lang import Class
Class.forName("com.informix.jdbc.IfxDriver")
QUERY = "insert into _money_test (amt) values ('123.45')"
def test_money(driver, db_url, usr, passwd):
try:
print("\n\n%s\n--------------" % (driver))
db = DriverManager.getConnection(db_url, usr, passwd)
c = db.createStatement()
c.execute("delete from _money_test")
c.execute(QUERY)
rs = c.executeQuery("select amt from _money_test")
while (rs.next()):
print('[%s]' % (rs.getString(1)))
rs.close()
c.close()
db.close()
except:
print("there were errors!")
s = traceback.format_exc()
sys.stderr.write("%s\n" % (s))
print(QUERY)
test_money("com.informix.jdbc.IfxDriver", 'jdbc:informix-sqli://169.0.1.225:9088/test:informixserver=ol_225;DB_LOCALE=pl_PL.CP1250;CLIENT_LOCALE=pl_PL.CP1250;charSet=CP1250', 'informix', 'passwd')
test_money("sun.jdbc.odbc.JdbcOdbcDriver", 'jdbc:odbc:test', 'informix', 'passwd')
Risultati quando si esegue i soldi letterale del punto e virgola:
C:\db_examples>jython ifx_jdbc_money.py
insert into _money_test (amt) values ('123,45')
com.informix.jdbc.IfxDriver
--------------
[123.45]
sun.jdbc.odbc.JdbcOdbcDriver
--------------
there were errors!
Traceback (most recent call last):
File "ifx_jdbc_money.py", line 16, in test_money
c.execute(QUERY)
SQLException: java.sql.SQLException: [Informix][Informix ODBC Driver][Informix]Character to numeric conversion error
C:\db_examples>jython ifx_jdbc_money.py
insert into _money_test (amt) values ('123.45')
com.informix.jdbc.IfxDriver
--------------
there were errors!
Traceback (most recent call last):
File "ifx_jdbc_money.py", line 16, in test_money
c.execute(QUERY)
SQLException: java.sql.SQLException: Character to numeric conversion error
sun.jdbc.odbc.JdbcOdbcDriver
--------------
[123.45]
Soluzione 2
Ho risolto questo problema utilizzando PreparedStatement.Penso che il "Carattere numerico di errore di conversione" è un bug in Informix driver JDBC.
In altri database che uso spesso, PostgreSQL, non c'è nessuna differenza se eseguo la query tramite native driver JDBC o via JDBC-ODBC bridge.Ho trovato che PostgreSQL non accettano il formato numerico 123.45
.PostgreSQL accetta il valore letterale di stringa con dot, ma questo punto è gestita come separatore delle migliaia.L'unico correttamente accettato valore letterale di stringa in cui la virgola separa la parte decimale.
MODIFICA:
Esso può essere risolto impostando DBMONEY=.
sul lato server, quindi tutte le connessioni ODBC, JDBC) funzionerà con tale impostazione.
Altri suggerimenti
Il Informix JDBC di tipo di dati di mappatura documentazione dice quanto segue:
java.math.BigDecimal SOLDI (p, s) 1
In questo modo, è necessario utilizzare java.math.BigDecimal
anziché java.lang.String
per rappresentare il valore, PreparedStatement#setBigDecimal()
per impostare il valore e ResultSet#getBigDecimal()
per ottenere il valore.
È possibile "convertire" da String
a BigDecimal
da solo di passaggio come argomento del costruttore . Il contrario può essere fatto chiamando il toString()
metodo BigDecimal
.