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 中是否有任何设置为两个驱动程序提供一个版本的代码?

版本信息:

  • 服务器:IBM Informix 动态服务器版本 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,那么您应该考虑使用 LVARCHAR 而不是 TEXT。如果您将使用高于此的数据大小,那么 BYTE 或 TEXT 或 BLOB 或 CLOB 是明智的选择,但是您应该考虑配置 blob 空间(用于 BYTE 或 TEXT)或智能 blob 空间(用于 BLOB 或 CLOB)。您可以并且正在使用 TEXT IN TABLE,而不是在 blob 空间中;请注意,这样做会影响您的逻辑日志,而使用 blob 空间不会对它们产生任何影响。

大约十年来我一直在宣传的功能之一是能够将 SQL 语句中的字符串文字作为 TEXT 文字(或 BYTE 文字)传递。这部分是因为像你这样的人的经历。我还没有成功地将其优先于需要进行的其他更改。当然,您需要注意 SQL 语句的最大大小为 64 KB 文本,因此如果您不小心,可能会创建太大的 SQL 语句;SQL 中的占位符(问号)通常可以防止这是一个问题——增加 SQL 语句的大小是我一直在争取的另一个功能请求,但不那么热情。

好的,假设您有充分的理由使用 TEXT ......下一步是什么。我不清楚 Java(JDBC 驱动程序)在幕后做了什么——除了太多——但可以肯定的是,它注意到需要一个 TEXT 'locator' 结构并且正在以正确的方式传送参数格式。看来 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 回答