如何将字节数组插入 Informix blob

Posted

技术标签:

【中文标题】如何将字节数组插入 Informix blob【英文标题】:How to insert byte array into Informix blob 【发布时间】:2014-03-26 13:07:30 【问题描述】:

我应该如何将大字节数组插入 Informix blob 列?现在我有疑问:

INSERT INTO TABLE (COLUMN1, COLUMN2, COLUMN3, COLUMN4, COLUMN_BLOB)
    VALUES(?, ?, ?, ?, ?)

抛出一个非常奇怪的异常:

org.sqlproc.engine.SqlProcessorException: SQL '  INSERT INTO TABLE (COLUMN1, COLUMN2, COLUMN3, COLUMN4, COLOMN_BLOB   )   VALUES(?, ?, ?, ?, ?)'. org.springframework.jdbc.BadSqlGrammarException: PreparedStatementCallback; bad SQL grammar []; nested exception is java.sql.SQLException: The specified table (into) is not in the database.
Caused by: java.sql.SQLException: The specified table (into) is not in the database.
    at com.informix.jdbc.IfxSqli.a(IfxSqli.java:3545)
    at com.informix.jdbc.IfxSqli.E(IfxSqli.java:3871)
    at com.informix.jdbc.IfxSqli.dispatchMsg(IfxSqli.java:2661)
    at com.informix.jdbc.IfxSqli.receiveMessage(IfxSqli.java:2577)
    at com.informix.jdbc.IfxSqli.executeFastPath(IfxSqli.java:5981)
    at com.informix.jdbc.IfxSqli.executeFastPath(IfxSqli.java:5892)
    at com.informix.jdbc.IfxSmartBlob.IfxLoColInfo(IfxSmartBlob.java:306)
    at com.informix.jdbc.IfxSmBlob.i(IfxSmBlob.java:787)
    at com.informix.jdbc.IfxSmBlob.a(IfxSmBlob.java:520)
    at com.informix.jdbc.IfxResultSet.b(IfxResultSet.java:291)
    at com.informix.jdbc.IfxStatement.c(IfxStatement.java:1275)
    at com.informix.jdbc.IfxPreparedStatement.executeUpdate(IfxPreparedStatement.java:418)
    at org.apache.commons.dbcp.DelegatingPreparedStatement.executeUpdate(DelegatingPreparedStatement.java:105)
    at org.apache.commons.dbcp.DelegatingPreparedStatement.executeUpdate(DelegatingPreparedStatement.java:105)
    at org.sqlproc.engine.spring.SpringQuery$9.doInPreparedStatement(SpringQuery.java:454)
    at org.sqlproc.engine.spring.SpringQuery$9.doInPreparedStatement(SpringQuery.java:448)
    at org.springframework.jdbc.core.JdbcTemplate.execute(JdbcTemplate.java:587)
    ... 44 more
Caused by: java.sql.SQLException: ISAM error: no record found.
    at com.informix.util.IfxErrMsg.getSQLException(IfxErrMsg.java:412)
    at com.informix.jdbc.IfxSqli.E(IfxSqli.java:3876)
    ... 59 more

我正在使用sqlProcessor,它使用准备好的语句将 blob 插入表中:

@Override
public void set(PreparedStatement st, int index, Object value) throws SQLException 
    byte[] bytes = (byte[]) value;
    st.setBytes(index, bytes);

DDL:

CREATE TABLE table1 (
  COLUMN1 BIGINT ,
  COLUMN2 VARCHAR(30) ,
  COLUMN3 INTEGER ,
  COLUMN4 INTEGER ,
  COLUMN_BLOB blob 
);

Informix 服务器是在 AIX 7.1 上运行的 Informix 12.10。

更新

好的,我解决了第一个问题。 sql 以空格开头,这对于informix 来说可能是个问题。但现在我有另一个例外:

Caused by: org.springframework.jdbc.UncategorizedSQLException: PreparedStatementCallback; uncategorized SQLException for SQL []; SQL state [IX000]; error code [-9810]; Smart-large-object error.; nested exception is java.sql.SQLException: Smart-large-object error.
    at org.springframework.jdbc.support.AbstractFallbackSQLExceptionTranslator.translate(AbstractFallbackSQLExceptionTranslator.java:83)
    at org.springframework.jdbc.support.AbstractFallbackSQLExceptionTranslator.translate(AbstractFallbackSQLExceptionTranslator.java:80)
    at org.springframework.jdbc.support.AbstractFallbackSQLExceptionTranslator.translate(AbstractFallbackSQLExceptionTranslator.java:80)
    at org.springframework.jdbc.core.JdbcTemplate.execute(JdbcTemplate.java:603)
    at org.sqlproc.engine.spring.SpringQuery.updateWithoutGenKeys(SpringQuery.java:448)
    at org.sqlproc.engine.spring.SpringQuery.update(SpringQuery.java:293)
    ... 42 more
Caused by: java.sql.SQLException: Smart-large-object error.
    at com.informix.util.IfxErrMsg.getSQLException(IfxErrMsg.java:412)
    at com.informix.jdbc.IfxSqli.a(IfxSqli.java:3549)
    at com.informix.jdbc.IfxSqli.E(IfxSqli.java:3871)
    at com.informix.jdbc.IfxSqli.dispatchMsg(IfxSqli.java:2661)
    at com.informix.jdbc.IfxSqli.receiveMessage(IfxSqli.java:2577)
    at com.informix.jdbc.IfxSqli.executeFastPath(IfxSqli.java:5981)
    at com.informix.jdbc.IfxSqli.executeFastPath(IfxSqli.java:5892)
    at com.informix.jdbc.IfxSmartBlob.IfxLoCreate(IfxSmartBlob.java:376)
    at com.informix.jdbc.IfxSmBlob.i(IfxSmBlob.java:790)
    at com.informix.jdbc.IfxSmBlob.a(IfxSmBlob.java:520)
    at com.informix.jdbc.IfxResultSet.b(IfxResultSet.java:291)
    at com.informix.jdbc.IfxStatement.c(IfxStatement.java:1275)
    at com.informix.jdbc.IfxPreparedStatement.executeUpdate(IfxPreparedStatement.java:418)
    at org.apache.commons.dbcp.DelegatingPreparedStatement.executeUpdate(DelegatingPreparedStatement.java:105)
    at org.apache.commons.dbcp.DelegatingPreparedStatement.executeUpdate(DelegatingPreparedStatement.java:105)
    at org.sqlproc.engine.spring.SpringQuery$9.doInPreparedStatement(SpringQuery.java:454)
    at org.sqlproc.engine.spring.SpringQuery$9.doInPreparedStatement(SpringQuery.java:448)
    at org.springframework.jdbc.core.JdbcTemplate.execute(JdbcTemplate.java:587)
    ... 44 more
Caused by: java.sql.SQLException: Smart Large Objects: No sbspace number specified.
    at com.informix.util.IfxErrMsg.getSQLException(IfxErrMsg.java:412)
    at com.informix.jdbc.IfxSqli.E(IfxSqli.java:3876)
    ... 59 more

【问题讨论】:

你能在没有最后一个 BLOB 列的情况下插入数据吗?还向我们展示如何定义此列。你用的是哪种BLOB?使用CREATE TABLE、两列和INSERT 创建简单示例。向我们展示 Informix 版本和 JDBC 驱动程序版本。 ddl 已更新。当我想念 blobl 列插入工作正常时,当我想添加只是 blol 异常时是一样的 平台和版本是什么意思?我正在使用 informix db 12.10 版 这就是我的意思:哪个版本的 Informix 服务器(您说的 12.10),哪个版本的 Informix JDBC 驱动程序(可能是 CSDK 4.10 附带的版本)以及您在哪个操作系统上运行它?我不是 JDBC 专家,但给出的错误消息(加上省略 BLOB 列时它起作用的事实)表明存在严重错误;我建议联系您的支持渠道(最终是 IBM/Informix 技术支持)寻求建议。 嗯我不确定。 AIX 7.1 这可以是你想要的吗? 【参考方案1】:

我创建了类似的表和简单的 Jython 程序,用于测试插入 BLOB 列并从中进行选择。

作为测试数据,我使用了带有史努比卡通的 GIF 文件 :-)

#!/usr/bin/env jython
# -*- coding: utf8 -*-

import time

from java.sql import DriverManager
from java.lang import Class
from java.io import FileInputStream
from java.io import ByteArrayOutputStream

Class.forName("com.informix.jdbc.IfxDriver")

"""
create table _blob_test_so (
    id serial,
    txt varchar(30),
    column_blob blob
);
"""

def test_blob_insert(db):
    print('inserting gif picture into blob table...')
    blob = FileInputStream('snoopy_comics20121023.gif')
    insert_stmt = db.prepareStatement("INSERT INTO _blob_test_so (txt, column_blob) VALUES (?, ?)")
    insert_stmt.setString(1, 'test %s' % (time.strftime('%Y-%m-%d %H:%M:%S')))
    insert_stmt.setBinaryStream(2, blob)
    #insert_stmt.setBytes(2, [0, 1, 2, 3])
    rec_cnt = insert_stmt.executeUpdate()
    blob.close()
    print('records changed: %d' % (rec_cnt))

def test_blob_select(db):
    print('selecting data from blob table...')
    pstm = db.prepareStatement("SELECT id, txt, column_blob FROM _blob_test_so")
    rs = pstm.executeQuery()
    while (rs.next()):
        id = rs.getInt(1)
        txt = rs.getString(2)
        image_stream = rs.getBinaryStream(3)
        fout = ByteArrayOutputStream()
        while 1:
            b = image_stream.read()
            if b < 0:
                break
            fout.write(b)
        arr = fout.toByteArray()
        fname_out = 'test_%s.gif' % (id)
        print('%d:%s: fname: %s %d [b]' % (id, txt, fname_out, len(arr)))
        f = open(fname_out, 'wb')
        f.write(arr)
        f.close()

def test_version(db):
    try:
        dbmi = db.getMetaData();
        print('-' * 10)
        print("JDBC driver version is '%s'; major: %s; minor: %s" % (dbmi.getDriverVersion(), dbmi.getDriverMajorVersion(), dbmi.getDriverMinorVersion()));
        c = db.createStatement()
        rs = c.executeQuery("SELECT FIRST 1 DBINFO('version','full') FROM systables")
        while (rs.next()):
            print("Server version: '%s'" % (rs.getString(1)))
    except:
        print("there were errors!")
        s = traceback.format_exc()
        sys.stderr.write("%s\n" % (s))


db = DriverManager.getConnection('jdbc:informix-sqli://test-informix/test:informixserver=ol_testifx;DB_LOCALE=pl_PL.CP1250;CLIENT_LOCALE=pl_PL.CP1250;charSet=CP1250', 'informix', 'informix')
test_version(db)
test_blob_insert(db)
test_blob_select(db)

我在 java1.7.0_51 上使用 Jython 2.5.3。在我的环境中它运行良好。它报告说我使用:

JDBC driver version is '4.10.JC2DE'; major: 4; minor: 10
Server version: 'IBM Informix Dynamic Server Version 11.50.FC4    '

它会创建与snoopy_comics20121023.gif 相同的test_*.gif 文件。

所以我的结论是你的环境有问题。我怀疑 JDBC 驱动程序。

【讨论】:

检查我的更新。我正在使用 setBytes 存储 blob 没有 setBinaryStream 作为你 当我将 setBinaryStream() 更改为 insert_stmt.setBytes(2, [0, 1, 2, 3]) 时,它仍然有效。当然,现在我没有收到 GIF 文件,但结果文件包含 os 4 个字节:00 01 02 03 按要求。很快:对我有用。 我还是觉得 JDBC 驱动有问题。见:informix.questionfor.info/q_informix_57173.html【参考方案2】:

根据我的经验,当没有定义临时 sb-space 时会发生这种情况。

这里有一个关于如何创建 sb-space 的示例:

onspaces -c -S sbddbs -p /infentw/sbdbs01.dat -o 0 -s 1000000
onbar -b -F

还必须添加到 $ONCONFIG:

SBSPACENAME     sbddbs       # Default smartblob space name

最后你必须重启informix服务器。

onmode -ky; oninit -v

【讨论】:

以上是关于如何将字节数组插入 Informix blob的主要内容,如果未能解决你的问题,请参考以下文章

如何在 informix 中插入 blob 或 clob 列

如何将字节数组(即 byte[])保存到 Azure Blob 存储?

使用语句在表中插入java字节数组

以字节数组和二进制 (BLOB) 存储图像之间的区别以及哪个更快

如何用 Linq 插入字节数组数据?

如何通过移位将字节插入数组?