Méthode cohérente d'insertion d'une colonne TEXT dans la base de données Informix à l'aide de JDBC et ODBC

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

  •  20-08-2019
  •  | 
  •  

Question

J'ai un problème lorsque j'essaie d'insérer des données dans la colonne Informix TEXT via JDBC. Dans ODBC, je peux simplement exécuter SQL comme ceci:

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

mais cela ne fonctionne pas dans JDBC et j'ai une erreur:

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

J'ai recherché ce problème et trouvé des messages de 2003:

http://groups.google.com/group/comp.databases.informix/browse_thread/ thread / 4dab38472e521269? ie = UTF-8 & amp; oe = utf-8 & amp; q = Informix + jdbc +% 22A + objet blob + type + doit + être + fourni + dans + ce% 22

J'ai changé mon code pour utiliser PreparedStatement. Maintenant, cela fonctionne avec JDBC, mais dans ODBC, lorsque j'essaie d'utiliser PreparedStatement, j'ai l'erreur:

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

La table de test a été créée avec:

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

Code Jython pour tester les deux pilotes:

# 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')

Existe-t-il un paramètre dans JDBC ou ODBC pour avoir une version de code pour les deux pilotes?

Informations sur la version:

  • Serveur: IBM Informix Dynamic Server version 11.50.TC2DE
  • Client:
    • Pilote ODBC 3.50.TC3DE
    • Pilote JDBC IBM Informix pour IBM Informix Dynamic Server 3.50.JC3DE
Était-ce utile?

La solution

Tout d’abord, êtes-vous vraiment sûr de vouloir utiliser un type Informix TEXT? Le type est une nuisance à utiliser, en partie à cause des problèmes que vous rencontrez. Cela précède tout ce qui, dans n'importe quel standard SQL, concerne les gros objets (TEXT n'est toujours pas dans SQL-2003 - bien que des structures à peu près équivalentes, CLOB et BLOB, le soient). Et la fonctionnalité des blobs BYTE et TEXT n’a pas été modifiée depuis - oh, disons 1996, bien que je suppose qu’il soit judicieux de choisir une date antérieure, comme 1991.

En particulier, combien de données comptez-vous stocker dans les colonnes TEXT? Votre exemple montre la chaîne 'insert'; c'est, je suppose, beaucoup plus petit que ce que vous utiliseriez vraiment. Vous devez savoir qu'une colonne BYTE ou TEXT utilise un descripteur de 56 octets dans le tableau plus une page séparée (ou un ensemble de pages) pour stocker les données réelles. Ainsi, pour de petites chaînes de ce type, il s’agit d’un gaspillage d’espace et de bande passante (car les données des objets BYTE ou TEXT seront envoyées séparément entre le client et le serveur du reste de la ligne). Si votre taille ne dépasse pas environ 32 Ko, vous devriez envisager d'utiliser LVARCHAR au lieu de TEXT. Si vous souhaitez utiliser des tailles de données supérieures à cette valeur, BYTE ou TEXT ou BLOB ou CLOB sont des alternatives judicieuses, mais vous devriez envisager de configurer des espaces blob (pour BYTE ou TEXT) ou des espaces blob intelligents (pour BLOB ou CLOB). Vous pouvez et utilisez TEXT IN TABLE plutôt que dans un blob; Sachez que cela a un impact sur vos journaux logiques, alors que l'utilisation d'un espace blob n'a aucun impact sur eux.

L’une des fonctionnalités que je fais campagne depuis une dizaine d’années est la possibilité de transmettre des littéraux de chaîne dans des instructions SQL en tant que littéraux TEXT (ou littéraux BYTE). C'est en partie à cause de l'expérience de personnes comme vous. Je n'ai pas encore réussi à le hiérarchiser avant d'autres changements à apporter. Bien entendu, vous devez savoir que la taille maximale d'une instruction SQL est de 64 Ko. Vous pouvez donc créer une instruction SQL trop volumineuse si vous ne faites pas attention. Les espaces réservés (points d'interrogation) dans le code SQL empêchent normalement que ce soit un problème - et l'augmentation de la taille d'une instruction SQL est une autre demande de fonctionnalité pour laquelle je fais campagne, mais un peu moins ardemment.

OK, en supposant que vous ayez de bonnes raisons d'utiliser TEXT ... et ensuite. Je ne sais pas ce que Java (le pilote JDBC) fait dans les coulisses - à part trop - mais il y a fort à parier qu'il est conscient qu'une structure de "localisateur" TEXT est nécessaire et qu'elle envoie le paramètre dans le fichier correct. format. Il semble que le pilote ODBC ne vous laisse pas tenter par des manigances similaires.

Dans ESQL / C, où je travaille normalement, le code doit traiter BYTE et TEXT différemment de tout le reste (et BLOB et CLOB doivent à nouveau être traités différemment). Mais vous pouvez créer et remplir une structure de localisateur (loc_t ou ifx_loc_t à partir de locator.h - qui ne figure peut-être pas dans le répertoire ODBC; il se trouve dans $ INFORMIXDIR / incl / esql par défaut) et transmettez-le au code ESQL / C comme variable hôte pour l’espace réservé pertinent dans l’instruction SQL. En principe, il existe probablement une méthode parallèle pour ODBC. Vous devrez peut-être consulter le manuel du pilote Informix ODBC pour le trouver, cependant.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top