6

JDBC 経由で Informix TEXT 列にデータを挿入しようとすると問題が発生します。ODBC では、次のように単純に SQL を実行できます。

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

しかし、これはJDBCでは機能せず、エラーが発生しました:

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

そのような問題を検索したところ、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+供給+以内+この%22

PreparedStatement を使用するようにコードを変更しました。現在は JDBC で動作しますが、ODBC で PreparedStatement を使用しようとするとエラーが発生しました:

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

テスト テーブルは次のように作成されました。

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

両方のドライバーをテストするための Jython コード:

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

JDBC または ODBC で、両方のドライバーに対して 1 つのバージョンのコードを使用するための設定はありますか?

バージョン情報:

  • サーバー: IBM Informix Dynamic Server バージョン 11.50.TC2DE
  • クライアント:
    • ODBC ドライバー 3.50.TC3DE
    • IBM Informix Dynamic Server 3.50.JC3DE 用の IBM Informix JDBC ドライバ
4

1 に答える 1

7

まず、本当に Informix TEXT タイプを使用したいですか? このタイプは、直面している問題の一部が原因で、使用するのが面倒です。ラージ オブジェクトに関しては、どの SQL 標準よりも古いものです (TEXT は SQL-2003 にはまだありませんが、CLOB と BLOB はほぼ同等の構造です)。そして、BYTE および TEXT blob の機能は、1996 年から変更されていませんが、1991 年のような以前の日付を選択するケースがあると思います。

特に、TEXT 列にどのくらいのデータを格納する予定ですか? あなたの例は、文字列「挿入」を示しています。つまり、実際に使用するよりもはるかに小さいと思います。BYTE 列または TEXT 列は、テーブル内の 56 バイトの記述子と、実際のデータを格納するための別のページ (またはページのセット) を使用することに注意してください。そのため、そのような小さな文字列の場合、スペースと帯域幅の無駄になります (BYTE または TEXT オブジェクトのデータは、行の残りの部分とは別にクライアントとサーバー間で送信されるため)。サイズが約 32 KB を超えない場合は、TEXT の代わりに LVARCHAR の使用を検討する必要があります。それ以上のデータ サイズを使用する場合は、BYTE、TEXT、BLOB、または CLOB が賢明な代替手段です。ただし、BLOB スペース (BYTE または TEXT の場合) またはスマート BLOB スペース (BLOB または CLOB の場合) の構成を検討する必要があります。BLOB スペースではなく、TEXT IN TABLE を使用できます。これを行うと、論理ログに影響が及ぶことに注意してください。一方、BLOB スペースを使用してもそれほど影響はありません。

私が 10 年ほどキャンペーンを行ってきた機能の 1 つは、SQL ステートメントで文字列リテラルを TEXT リテラル (または BYTE リテラル) として渡す機能です。その理由の一部は、あなたのような人々の経験によるものです。必要な他の変更よりも先に優先順位を付けることにまだ成功していません。もちろん、SQL ステートメントの最大サイズは 64 KB のテキストであることに注意する必要があります。そのため、注意を怠ると、SQL ステートメントが大きすぎる可能性があります。SQL のプレースホルダー (疑問符) は、通常、それが問題になるのを防ぎます。SQL ステートメントのサイズを大きくすることも、私がキャンペーンを行ってきた別の機能要求ですが、それほど熱心ではありません。

わかりました、TEXT を使用する正当な理由があると仮定して...次は何をしますか。Java (JDBC ドライバー) が舞台裏で何をしているのかはわかりませんが、多すぎることは別として、TEXT 'ロケーター' 構造が必要であり、パラメーターを正しい方法で送信していることに気付いていることは間違いありません。フォーマット。ODBC ドライバーは、同様の悪ふざけにあなたを甘やかしていないようです。

私が普段作業している ESQL/C では、コードは BYTE と TEXT を他のすべてのものとは異なる方法で処理する必要があります (また、BLOB と CLOB も別の方法で処理する必要があります)。ただし、ロケータ構造 (locator.h の loc_t または ifx_loc_t - ODBC ディレクトリにない場合があります。デフォルトでは $INFORMIXDIR/incl/esql にあります) を作成してデータを取り込み、それを ESQL/C コードにSQL ステートメント内の関連するプレースホルダーのホスト変数。原則として、ODBC で使用できる並列メソッドがおそらく存在します。ただし、Informix ODBC ドライバーのマニュアルを参照して見つける必要があるかもしれません。

于 2009-01-28T03:21:23.630 に答える