2009-01-27 10 views
5

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:Méthode cohérente d'insertion de la colonne TEXT dans la base de données Informix à l'aide de JDBC et ODBC

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

mais cela ne fonctionne pas dans JDBC et je suis arrivé erreur:

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

Je recherchais un tel problème et a trouvé des messages de 2003:

http://groups.google.com/group/comp.databases.informix/browse_thread/thread/4dab38472e521269?ie=UTF-8&oe=utf-8&q=Informix+jdbc+%22A+blob+data+type+must+be+supplied+within+this%22

J'ai modifié mon code pour utiliser PreparedStatement. Maintenant, il fonctionne avec JDBC, mais ODBC quand j'essayer d'utiliser PreparedStatement je me suis erreur:

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

table de test a été créé 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 du code pour les deux pilotes?

Version info:

  • Serveur: IBM Informix Dynamic Server Version 11.50.TC2DE
  • Client:
    • pilote ODBC 3.50.TC3DE
    • IBM Informix JDBC Driver pour IBM Informix Dynamic Server 3.50.JC3DE
+0

http://stackoverflow.com/questions/1074364/informix-7-3-isql-insert-statement-text-blob-clob-field-insert-error Peut-être que cela éclaircira votre situation comme elle l'a fait le mien – CheeseConQueso

Répondre

5

Tout d'abord, êtes-vous sûr de vouloir utiliser un type Informix TEXT? Le type est une nuisance à utiliser, en partie à cause des problèmes que vous rencontrez. Il est antérieur à tout ce qui concerne les grands objets dans n'importe quelle norme SQL (TEXT n'est toujours pas dans SQL-2003 - bien que des structures approximativement équivalentes, CLOB et BLOB, le soient). Et la fonctionnalité des blobs BYTE et TEXT n'a pas été changée depuis - oh, disons 1996, bien que je soupçonne qu'il est possible de choisir une date antérieure, comme 1991.

En particulier, combien de données prévoyez-vous de stocker? dans les colonnes TEXT? Votre exemple montre la chaîne 'insert'; c'est, je présume, beaucoup plus petit que vous utiliseriez vraiment. Vous devez savoir qu'une colonne BYTE ou TEXT utilise un descripteur de 56 octets dans la table plus une page séparée (ou un ensemble de pages) pour stocker les données réelles. Donc, pour des chaînes minuscules comme ça, c'est une perte d'espace et de bande passante (car les données pour les objets BYTE ou TEXT seront expédiées entre le client et le serveur séparément du reste de la ligne). Si votre taille ne dépasse pas 32 Ko, vous devriez utiliser LVARCHAR au lieu de TEXT. Si vous utilisez des tailles de données supérieures, alors BYTE ou TEXT ou BLOB ou CLOB sont des alternatives sensées, mais vous devriez regarder la configuration des espaces blob (pour BYTE ou TEXT) ou des espaces blob intelligents (pour BLOB ou CLOB). Vous pouvez, et êtes, en utilisant TEXT IN TABLE, plutôt que dans un espace blob; sachez que cela a un impact sur vos logs logiques alors que l'utilisation d'un espace blob ne les affecte pas autant.L'une des fonctionnalités que j'ai fait campagne pendant 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 gens comme vous. Je n'ai pas encore réussi à le classer par ordre de priorité avant les autres changements qui doivent être faits. Bien sûr, vous devez savoir que la taille maximale d'une instruction SQL est de 64 Ko, vous pouvez donc créer une instruction SQL trop grande si vous ne faites pas attention; les espaces réservés (points d'interrogation) dans le SQL empêchent normalement que cela soit un problème - et l'augmentation de la taille d'une instruction SQL est une autre demande de fonctionnalité pour laquelle j'ai fait campagne, mais un peu moins ardemment. OK, en supposant que vous ayez de bonnes raisons d'utiliser le TEXTE ... et ensuite. Je ne sais pas ce que Java (le pilote JDBC) fait en coulisses - à part trop - mais il est juste de parier qu'il faut une structure de localisateur TEXT et que le paramètre est envoyé dans le bon format. Il semble que le pilote ODBC ne vous gâte pas avec 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 être traités différemment à nouveau). Mais vous pouvez créer et remplir une structure de localisateur (loc_t ou ifx_loc_t de locator.h - qui peut ne pas être dans le répertoire ODBC, il est dans $ INFORMIXDIR/incl/esql par défaut) et le passer 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 disponible pour ODBC. Vous devrez peut-être consulter le manuel du pilote Informix ODBC pour le trouver, cependant.

+0

Merci pour votre réponse. La colonne TEXT est utilisée car le projet a démarré lorsqu'il n'y avait pas de colonne LVARCHAR côté serveur (IDS7.2) et côté client (SQLLinks depuis Delphi4). Je pense que je vais convertir les colonnes TEXT à LVARCHAR lorsque la mise à niveau côté client à Delphi plus récent avec les pilotes dbExpress. –