使用JDBC和ODBC将TEXT列插入Informix数据库的一致方法

时间:2009-01-27 12:51:13

标签: jdbc odbc informix

当我尝试将一些数据插入Informix TEXT列时,我遇到了问题 通过JDBC。在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+supplied+within+this%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 Dynamic Server版本11.50.TC2DE
  • 客户端:
    • ODBC驱动程序3.50.TC3DE
    • 用于IBM Informix Dynamic Server 3.50.JC3DE的IBM Informix JDBC驱动程序

1 个答案:

答案 0 :(得分:5)

首先,您确定要使用Informix TEXT类型吗?该类型使用起来很麻烦,部分原因是您遇到的问题。它针对大型对象预先约定任何SQL标准中的任何内容(TEXT仍然不在SQL-2003中 - 尽管大致相同的结构,CLOB和BLOB都是)。而BYTE和TEXT blob的功能自那以后就没有改变 - 哦,让我们说1996年,虽然我怀疑有一个案例可以选择更早的日期,比如1991年。

特别是,您计划在TEXT列中存储多少数据?您的示例显示字符串'insert';也就是说,我认为,比实际使用的要小得多。您应该知道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'定位器'结构并且正确地输出参数格式。似乎ODBC驱动程序并没有让你沉迷于类似的诡计。

在我通常工作的ESQL / C中,代码必须以不同的方式处理BYTE和TEXT(并且BLOB和CLOB必须再次处理不同)。但是您可以创建并填充定位器结构(locator.h中的loc_t或ifx_loc_t - 可能不在ODBC目录中;默认情况下位于$ INFORMIXDIR / incl / esql中)并将其传递给ESQL / C代码作为SQL语句中相关占位符的宿主变量。原则上,可能有一种可用于ODBC的并行方法。但是,您可能必须查看Informix ODBC驱动程序手册才能找到它。