طريقة متسقة لإدراج عمود 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

لقد قمت بتغيير الكود الخاص بي لاستخدام PreparedStatement.الآن يعمل مع JDBC ، ولكن في ODBC عندما أحاول استخدام reparedstatement ، حصلت على خطأ:

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
هل كانت مفيدة؟

المحلول

أولاً، هل أنت متأكد حقًا من أنك تريد استخدام نوع Informix TEXT؟يعد استخدام هذا النوع أمرًا مزعجًا، ويرجع ذلك جزئيًا إلى المشكلات التي تواجهها.إنه يسبق أي شيء في أي معيار SQL فيما يتعلق بالكائنات الكبيرة (لا يزال النص غير موجود في SQL-2003 - على الرغم من أن الهياكل المكافئة تقريبًا، CLOB وBLOB، موجودة).ولم يتم تغيير وظيفة BYTE وTEXT blobs منذ ذلك الحين - لنفترض عام 1996، على الرغم من أنني أظن أن هناك سببًا لاختيار تاريخ سابق، مثل عام 1991.

على وجه الخصوص، ما مقدار البيانات التي تخطط لتخزينها في أعمدة TEXT؟يوضح المثال الخاص بك السلسلة "إدراج"؛وهذا، على ما أعتقد، أصغر بكثير مما ستستخدمه حقًا.يجب أن تدرك أن أعمدة BYTE أو TEXT تستخدم واصفًا بحجم 56 بايت في الجدول بالإضافة إلى صفحة منفصلة (أو مجموعة من الصفحات) لتخزين البيانات الفعلية.لذلك، بالنسبة للسلاسل الصغيرة مثل هذه، يعد ذلك مضيعة للمساحة وعرض النطاق الترددي (لأن البيانات الخاصة بكائنات BYTE أو TEXT سيتم شحنها بين العميل والخادم بشكل منفصل عن بقية الصف).إذا كان حجمك لن يتجاوز حوالي 32 كيلو بايت، فيجب عليك التفكير في استخدام LVARCHAR بدلاً من TEXT.إذا كنت ستستخدم أحجام بيانات أعلى من ذلك، فإن BYTE أو TEXT أو BLOB أو CLOB هي بدائل معقولة، ولكن يجب عليك النظر في تكوين إما مساحات blob (لـ BYTE أو TEXT) أو مساحات blob الذكية (لـ BLOB أو CLOB).يمكنك استخدام TEXT IN TABLE، وليس في مساحة blob؛انتبه إلى أن القيام بذلك يؤثر على سجلاتك المنطقية بينما استخدام مساحة blob لا يؤثر عليها كثيرًا.

إحدى الميزات التي قمت بحملتها منذ عقد من الزمن أو نحو ذلك هي القدرة على تمرير القيم الحرفية للسلسلة في عبارات SQL كنصوص حرفية (أو أحرف BYTE).ويرجع ذلك جزئيًا إلى تجربة الأشخاص مثلك.لم أنجح بعد في تحديد أولوياتها قبل التغييرات الأخرى التي يجب إجراؤها.بالطبع، عليك أن تدرك أن الحد الأقصى لحجم عبارة SQL هو 64 كيلو بايت نص، لذا يمكنك إنشاء عبارة SQL كبيرة جدًا إذا لم تكن حذرًا؛عادةً ما تمنع العناصر النائبة (علامات الاستفهام) في SQL أن تكون هذه مشكلة - كما أن زيادة حجم عبارة SQL هو طلب ميزة آخر كنت أقوم بحملة من أجله، ولكن بحماس أقل قليلاً.

حسنًا، بافتراض أن لديك أسبابًا وجيهة لاستخدام TEXT...ماذا بعد.لست واضحًا ما الذي تفعله Java (برنامج تشغيل JDBC) خلف الكواليس - بصرف النظر عن الكثير - ولكن من الرهان العادل أنها تلاحظ أن هناك حاجة إلى بنية "محدد موقع" النص وتقوم بشحن المعلمة بالشكل الصحيح شكل.يبدو أن برنامج تشغيل 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