Согласованный метод вставки столбца TEXT в базу данных Informix с использованием JDBC и ODBC - PullRequest
5 голосов
/ 27 января 2009

У меня проблема при попытке вставить некоторые данные в столбец 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 JDBC для IBM Informix Dynamic Server 3.50.JC3DE

1 Ответ

5 голосов
/ 28 января 2009

Прежде всего, вы действительно уверены, что хотите использовать тип Informix TEXT? Этот тип неудобен в использовании, отчасти из-за проблем, с которыми вы сталкиваетесь. Он предшествует чему-либо в любом стандарте SQL в отношении больших объектов (TEXT все еще отсутствует в SQL-2003 - хотя примерно эквивалентные структуры, CLOB и BLOB, есть). И функциональность BLTE и TEXT не изменилась с тех пор - о, скажем, в 1996 году, хотя я подозреваю, что есть возможность выбрать более раннюю дату, например 1991.

В частности, сколько данных вы планируете хранить в столбцах ТЕКСТ? Ваш пример показывает строку «вставить»; то есть, я полагаю, намного меньше, чем вы бы на самом деле использовали. Вы должны знать, что столбцы BYTE или TEXT используют 56-байтовый дескриптор в таблице плюс отдельную страницу (или набор страниц) для хранения фактических данных. Таким образом, для таких крошечных строк это пустая трата пространства и пропускной способности (поскольку данные для объектов BYTE или TEXT будут передаваться между клиентом и сервером отдельно от остальной части строки). Если ваш размер не превысит 32 КБ, вам следует использовать LVARCHAR вместо TEXT. Если вы будете использовать размеры данных выше этого, то БАЙТ, ТЕКСТ, БЛОБ или КЛОБ являются разумными альтернативами, но вам следует обратить внимание на настройку пространств BLOB-объектов (для BYTE или TEXT) или пространств интеллектуальных BLOB-объектов (для BLOB или CLOB). Вы можете и используете ТЕКСТ В ТАБЛИЦЕ, а не в пространстве больших двоичных объектов; Имейте в виду, что это влияет на ваши логические журналы, тогда как использование пространства больших двоичных объектов не оказывает на них никакого влияния.

Одной из функций, которую я проводил в течение десятилетия или около того, является возможность передавать строковые литералы в операторах SQL как литералы TEXT (или литералы BYTE). Это отчасти из-за опыта таких людей, как вы. Мне пока не удалось получить приоритет по сравнению с другими изменениями, которые необходимо внести. Конечно, вы должны знать, что максимальный размер оператора SQL составляет 64 КБ текста, поэтому вы можете создать слишком большой оператор SQL, если не будете осторожны; заполнители (вопросительные знаки) в SQL обычно предотвращают возникновение проблемы, а увеличение размера оператора SQL - это еще один запрос функции, за который я проводил кампанию, но чуть менее горячо.

ОК, при условии, что у вас есть веские причины для использования ТЕКСТА ... что дальше. Я не совсем понимаю, что делает Java (драйвер JDBC) за кулисами - не считая слишком многого - справедливо поспорить, что он замечает, что нужна структура TEXT 'locator' и отправляет параметр в правильном виде. формат. Похоже, что драйвер ODBC не балует вас подобными махинациями.

В ESQL / C, где я обычно работаю, код должен работать с BYTE и TEXT иначе, чем все остальное (а BLOB и CLOB должны снова обрабатываться по-разному). Но вы можете создать и заполнить структуру локатора (loc_t или ifx_loc_t из locator.h - которая может отсутствовать в каталоге ODBC; по умолчанию она находится в $ INFORMIXDIR / incl / esql) и передать ее в код ESQL / C в качестве переменная хоста для соответствующего заполнителя в операторе SQL. В принципе, для ODBC существует, вероятно, параллельный метод. Возможно, вам придется взглянуть на руководство по драйверу Informix ODBC, чтобы найти его.

...