Metodo coerente di inserimento della colonna TEXT nel database Informix utilizzando JDBC e ODBC

StackOverflow https://stackoverflow.com/questions/483284

  •  20-08-2019
  •  | 
  •  

Domanda

Ho dei problemi quando provo ad inserire alcuni dati nella colonna TEXT di Informix tramite JDBC. In ODBC posso semplicemente eseguire SQL in questo modo:

INSERT INTO test_table (text_column) VALUES ('insert')

ma questo non funziona in JDBC e ho ricevuto un errore:

617: A blob data type must be supplied within this context.

Ho cercato questo problema e ho trovato messaggi del 2003:

http://groups.google.com/group/comp.database.informix/browse_thread/ filetto / 4dab38472e521269 ie = UTF-8 amp? &; oe = utf-8 amp &; q = Informix + jdbc +% 22A + blob + dati + tipo + deve + essere + fornita + all'interno + questo% 22

Ho modificato il mio codice per utilizzare PreparedStatement. Ora funziona con JDBC, ma in ODBC quando provo ad usare PreparedStatement ho ricevuto un errore:

Error: [Informix][Informix ODBC Driver][Informix]
Illegal attempt to convert Text/Byte blob type.
[SQLCode: -608], [SQLState: S1000]

La tabella di test è stata creata con:

CREATE TABLE _text_test (id serial PRIMARY KEY, txt TEXT)

Codice Jython per testare entrambi i driver:

# for Jython 2.5 invoke with --verify
# beacuse of bug: http://bugs.jython.org/issue1127

import traceback
import sys
from com.ziclix.python.sql import zxJDBC

def test_text(driver, db_url, usr, passwd):
    arr = db_url.split(':', 2)
    dbname = arr[1]
    if dbname == 'odbc':
        dbname = db_url
    print "\n\n%s\n--------------" % (dbname)
    try:
        connection = zxJDBC.connect(db_url, usr, passwd, driver)
    except:
        ex = sys.exc_info()
        s = 'Exception: %s: %s\n%s' % (ex[0], ex[1], db_url)
        print s
        return
    Errors = []
    try:
        cursor = connection.cursor()
        cursor.execute("DELETE FROM _text_test")
        try:
            cursor.execute("INSERT INTO _text_test (txt) VALUES (?)", ['prepared', ])
            print "prepared insert ok"
        except:
            ex = sys.exc_info()
            s = 'Exception in prepared insert: %s: %s\n%s\n' % (ex[0], ex[1], traceback.format_exc())
            Errors.append(s)
        try:
            cursor.execute("INSERT INTO _text_test (txt) VALUES ('normal')")
            print "insert ok"
        except:
            ex = sys.exc_info()
            s = 'Exception in insert: %s: %s\n%s' % (ex[0], ex[1], traceback.format_exc())
            Errors.append(s)
        cursor.execute("SELECT id, txt FROM _text_test")
        print "\nData:"
        for row in cursor.fetchall():
            print '[%s]\t[%s]' % (row[0], row[1])
        if Errors:
            print "\nErrors:"
            print "\n".join(Errors)
    finally:
        cursor.close()
        connection.commit()
        connection.close()


#test_varchar(driver, db_url, usr, passwd)
test_text("sun.jdbc.odbc.JdbcOdbcDriver", 'jdbc:odbc:test_db', 'usr', 'passwd')
test_text("com.informix.jdbc.IfxDriver", 'jdbc:informix-sqli://169.0.1.225:9088/test_db:informixserver=ol_225;DB_LOCALE=pl_PL.CP1250;CLIENT_LOCALE=pl_PL.CP1250;charSet=CP1250', 'usr', 'passwd')

C'è qualche impostazione in JDBC o ODBC per avere una versione di codice per entrambi i driver?

Informazioni sulla versione:

  • Server: IBM Informix Dynamic Server versione 11.50.TC2DE
  • Cliente:
    • Driver ODBC 3.50.TC3DE
    • Driver JDBC di IBM Informix per IBM Informix Dynamic Server 3.50.JC3DE
È stato utile?

Soluzione

Prima di tutto, sei davvero sicuro di voler usare un tipo di TEXT Informix? Il tipo è un fastidio da usare, in parte a causa dei problemi che stai affrontando. Anticipa qualsiasi cosa in qualsiasi standard SQL rispetto agli oggetti di grandi dimensioni (TEXT non è ancora in SQL-2003, anche se lo sono strutture approssimativamente equivalenti, CLOB e BLOB). E la funzionalità dei BLOB BYTE e TEXT non è cambiata da allora - oh, diciamo 1996, anche se sospetto che ci sia un motivo per scegliere una data precedente, come il 1991.

In particolare, quanti dati hai intenzione di archiviare nelle colonne TEXT? Il tuo esempio mostra la stringa 'insert'; cioè, presumo, molto più piccolo di quello che useresti davvero. È necessario essere consapevoli del fatto che una colonna BYTE o TEXT utilizza un descrittore a 56 byte nella tabella più una pagina separata (o un insieme di pagine) per memorizzare i dati effettivi. Quindi, per stringhe così piccole, è uno spreco di spazio e larghezza di banda (perché i dati per gli oggetti BYTE o TEXT verranno spediti tra client e server separatamente dal resto della riga). Se le dimensioni non superano i 32 KB circa, è consigliabile utilizzare LVARCHAR anziché TEXT. Se si utilizzano dimensioni di dati superiori a quelle indicate, BYTE o TEXT o BLOB o CLOB sono alternative sensate, ma è necessario cercare di configurare gli spazi BLOB (per BYTE o TEXT) o gli spazi BLOB intelligenti (per BLOB o CLOB). Puoi, e stai usando TEXT IN TABLE, piuttosto che in uno spazio BLOB; tenere presente che ciò influisce sui log logici, mentre l'utilizzo di uno spazio BLOB non influisce in alcun modo su di essi.

Una delle caratteristiche che sto promuovendo da circa un decennio è la possibilità di passare letterali di stringa in istruzioni SQL come letterali TEXT (o letterali BYTE). Ciò è in parte dovuto all'esperienza di persone come te. Non sono ancora riuscito a stabilire le priorità prima di altre modifiche che devono essere apportate. Naturalmente, devi essere consapevole che la dimensione massima di un'istruzione SQL è di 64 KB di testo, quindi potresti creare un'istruzione SQL troppo grande se non stai attento; i segnaposto (punti interrogativi) nell'SQL normalmente impediscono che ciò costituisca un problema - e aumentare le dimensioni di un'istruzione SQL è un'altra richiesta di funzionalità per la quale ho fatto una campagna, ma un po 'meno ardentemente.

OK, supponendo che tu abbia validi motivi per usare TEXT ... e poi. Non sono chiaro cosa stia facendo Java (il driver JDBC) dietro le quinte - a parte troppo - ma è una buona scommessa che sta notando che è necessaria una struttura 'localizzatore' TEXT e sta spedendo il parametro nel modo corretto formato. Sembra che il driver ODBC non ti stia indulgendo con shenanigans simili.

In ESQL / C, dove lavoro normalmente, il codice deve trattare BYTE e TEXT in modo diverso da tutto il resto (e BLOB e CLOB devono essere trattati di nuovo in modo diverso). Ma puoi creare e popolare una struttura di localizzatore (loc_t o ifx_loc_t da locator.h - che potrebbe non essere nella directory ODBC; è in $ INFORMIXDIR / incl / esql di default) e passarlo al codice ESQL / C come variabile host per il segnaposto pertinente nell'istruzione SQL. In linea di principio, esiste probabilmente un metodo parallelo disponibile per ODBC. Tuttavia, potrebbe essere necessario consultare il manuale del driver ODBC Informix per trovarlo.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top