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

Mic*_*las 5 informix odbc jdbc

当我尝试通过JDBC向Informix TEXT列插入一些数据时,我遇到了问题.在ODBC中,我可以像这样简单地运行SQL:

INSERT INTO test_table (text_column) VALUES ('insert')
Run Code Online (Sandbox Code Playgroud)

但这在JDBC中不起作用,我收到错误:

617: A blob data type must be supplied within this context.
Run Code Online (Sandbox Code Playgroud)

我搜索了这个问题,并从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]
Run Code Online (Sandbox Code Playgroud)

测试表创建时使用:

CREATE TABLE _text_test (id serial PRIMARY KEY, txt TEXT)
Run Code Online (Sandbox Code Playgroud)

用于测试两个驱动程序的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')
Run Code Online (Sandbox Code Playgroud)

JDBC或ODBC中是否有任何设置为两个驱动程序提供一个版本的代码?

版本信息:

  • 服务器:IBM Informix Dynamic Server版本11.50.TC2DE
  • 客户:
    • ODBC驱动程序3.50.TC3DE
    • IBM Informix JDBC驱动程序,用于IBM Informix Dynamic Server 3.50.JC3DE

Jon*_*ler 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驱动程序手册才能找到它.