如何将字节数组插入 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 存储?