Согласованный метод вставки столбца TEXT в базу данных Informix с использованием JDBC и ODBC.

StackOverflow https://stackoverflow.com/questions/483284

  •  20-08-2019
  •  | 
  •  

Вопрос

У меня есть проблема, когда я пытаюсь вставить некоторые данные в текстовый столбец Informix через 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+ поставляется+в+этом%22

Я изменил свой код, чтобы использовать ReadedStatement.Теперь он работает с JDBC, но в ODBC, когда я пытаюсь использовать PrectStatement, я получил ошибку:

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 JDBC для IBM Informix Dynamic Server 3.50.JC3DE
Это было полезно?

Решение

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

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

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

Хорошо, если у вас есть веские причины использовать ТЕКСТ... что дальше.Мне неясно, что Java (драйвер JDBC) делает за кулисами (кроме слишком многого), но можно поспорить, что он замечает, что необходима структура «локатора» TEXT, и отправляет параметр в правильном виде. формат.Похоже, что драйвер ODBC не балует вас подобными махинациями.

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

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top