将CLOB插入Oracle数据库

我的问题是:你怎么解决ORA-01704: string literal too longCLOB插入(或在查询中做任何事情)时ORA-01704: string literal too long错误?

我想要这样的查询:

 INSERT ALL INTO mytable VALUES ('clob1') INTO mytable VALUES ('clob2') --some of these clobs are more than 4000 characters... INTO mytable VALUES ('clob3') SELECT * FROM dual; 

当我尝试使用实际值但我得到ORA-01704: string literal too long了。 这很明显,但是如何插入clobs(或者使用clob执行任何语句)?

我试过看这个问题 ,但我认为它没有我想要的东西。 我拥有的clobs在List ,我遍历它们来制作语句。 我的代码如下:

 private void insertQueries(String tempTableName) throws FileNotFoundException, DataException, SQLException, IOException { String preQuery = " into " + tempTableName + " values ('"; String postQuery = "')" + StringHelper.newline; StringBuilder inserts = new StringBuilder("insert all" + StringHelper.newline); List readQueries = getDomoQueries(); for (String query : readQueries) { inserts.append(preQuery).append(query).append(postQuery); } inserts.append("select * from dual;"); DatabaseController.getInstance().executeQuery(databaseConnectionURL, inserts.toString()); 

}

 public ResultSet executeQuery(String connection, String query) throws DataException, SQLException { Connection conn = ConnectionPool.getInstance().get(connection); Statement stmt = conn.createStatement(); ResultSet rs = stmt.executeQuery(query); conn.commit(); ConnectionPool.getInstance().release(conn); return rs; } 

你正在变得复杂。

对列表中的每个clob使用PreparedStatement和addBatch():

 String sql = "insert into " + tempTableName + " values (?)"; PreparedStatement stmt = connection.prepareStatement(sql); for (String query : readQueries) { stmt.setCharacterStream(1, new StringReader(query), query.lenght()); stmt.addBatch(); } stmt.exececuteBatch(); 

没有乱转字符串,文字的长度没有问题,不需要创建临时clobs。 而且大多数可能与使用单个INSERT ALL语句一样快。

如果您使用的是当前驱动程序(> 10.2),那么我认为setCharacterStream()调用和Reader的创建也不是必需的。 一个简单的setString(1, query)很可能也会起作用。

您需要使用绑定变量,而不是使用字符串连接来构建SQL语句。 从安全性,性能和健壮性的角度来看,这将是有益的,因为它将降低SQL注入攻击的风险,减少Oracle花费在SQL语句上进行硬分析所花费的时间,并将消除那里的潜力是字符串中的一个特殊字符,它导致生成无效的SQL语句(即单引号)。

我希望你想要的东西

 private void insertQueries(String tempTableName) throws FileNotFoundException, DataException, SQLException, IOException { String preQuery = " into " + tempTableName + " values (?)" + StringHelper.newline; StringBuilder inserts = new StringBuilder("insert all" + StringHelper.newline); List readQueries = getDomoQueries(); for (String query : readQueries) { inserts.append(preQuery); } inserts.append("select * from dual"); Connection conn = ConnectionPool.getInstance().get(connection); PreparedStatement pstmt = conn.prepareStatement( inserts); int i = 1; for (String query : readQueries) { Clob clob = CLOB.createTemporary(conn, false, oracle.sql.CLOB.DURATION_SESSION); clob.setString(i, query); pstmt.setClob(i, clob); i = i + 1; } pstmt.executeUpdate(); } 

BLOB(二进制大对象)和CLOB(字符大对象)是特殊的数据类型,可以以对象或文本的forms保存大块数据。 Blob和Clob对象将对象的数据作为流保存到数据库中。

一段代码示例:

 public class TestDB { public static void main(String[] args) { try { /** Loading the driver */ Class.forName("com.oracle.jdbc.Driver"); /** Getting Connection */ Connection con = DriverManager.getConnection("Driver URL","test","test"); PreparedStatement pstmt = con.prepareStatement("insert into Emp(id,name,description)values(?,?,?)"); pstmt.setInt(1,5); pstmt.setString(2,"Das"); // Create a big CLOB value...AND inserting as a CLOB StringBuffer sb = new StringBuffer(400000); sb.append("This is the Example of CLOB .."); String clobValue = sb.toString(); pstmt.setString(3, clobValue); int i = pstmt.executeUpdate(); System.out.println("Done Inserted"); pstmt.close(); con.close(); // Retrive CLOB values Connection con = DriverManager.getConnection("Driver URL","test","test"); PreparedStatement pstmt = con.prepareStatement("select * from Emp where id=5"); ResultSet rs = pstmt.executeQuery(); Reader instream = null; int chunkSize; if (rs.next()) { String name = rs.getString("name"); java.sql.Clob clob = result.getClob("description") StringBuffer sb1 = new StringBuffer(); chunkSize = ((oracle.sql.CLOB)clob).getChunkSize(); instream = clob.getCharacterStream(); BufferedReader in = new BufferedReader(instream); String line = null; while ((line = in.readLine()) != null) { sb1.append(line); } if (in != null) { in.close(); } // this is the clob data converted into string String clobdata = sb1.toString(); } } catch (Exception e) { e.printStackTrace(); } } } 

来自Oracle文档

您必须牢记以下自动切换大数据的输入模式。 有三种输入模式,如下所示:直接绑定,流绑定和LOB绑定。

对于PL / SQL语句

setBytes和setBinary流方法对小于32767字节的数据使用直接绑定。

setBytes和setBinaryStream方法对大于32766字节的数据使用LOB绑定。

setString,setCharacterStream和setAsciiStream方法对数据库字符集中小于32767字节的数据使用直接绑定。

setString,setCharacterStream和setAsciiStream方法对数据库字符集中大于32766字节的数据使用LOB绑定。

存在于oracle.jdbc.OraclePreparedStatement接口中的setBytesForBlob和setStringForClob方法对任何数据大小使用LOB绑定。

以下是将文件内容放入PLSQL过程的输入CLOB参数的示例:

  public int fileToClob( FileItem uploadFileItem ) throws SQLException, IOException { //for using stmt.setStringForClob method, turn the file to a big String FileItem item = uploadFileItem; InputStream inputStream = item.getInputStream(); InputStreamReader inputStreamReader = new InputStreamReader( inputStream ); BufferedReader bufferedReader = new BufferedReader( inputStreamReader ); StringBuffer stringBuffer = new StringBuffer(); String line = null; while((line = bufferedReader.readLine()) != null) { //Read till end stringBuffer.append(line); stringBuffer.append("\n"); } String fileString = stringBuffer.toString(); bufferedReader.close(); inputStreamReader.close(); inputStream.close(); item.delete(); OracleCallableStatement stmt; String strFunction = "{ call p_file_to_clob( p_in_clob => ? )}"; stmt= (OracleCallableStatement)conn.prepareCall(strFunction); try{ SasUtility servletUtility = sas.SasUtility.getInstance(); stmt.setStringForClob(1, fileString ); stmt.execute(); } finally { stmt.close(); } }