java - statement - ¿Dónde está mi personaje inválido(ORA-00911)
preparedstatement java update (2)
Estoy tratando de insertar CLOB
s en una base de datos (ver pregunta relacionada ). No puedo entender lo que está mal. Tengo una lista de aproximadamente 85 clobos que quiero insertar en una tabla. Incluso cuando inserto solo la primera clob obtengo ORA-00911: invalid character
. No puedo descifrar cómo obtener la declaración de PreparedStatement
antes de que se ejecute, por lo que no puedo estar 100% seguro de que sea correcta, pero si lo hice correctamente, debería verse exactamente así:
insert all
into domo_queries values (''select
substr(to_char(max_data),1,4) as year,
substr(to_char(max_data),5,6) as month,
max_data
from dss_fin_user.acq_dashboard_src_load_success
where source = ''''CHQ PeopleSoft FS'''''')
select * from dual;
En última instancia, esta instrucción insert all
tendría mucho into
, por lo que simplemente no hago una instrucción de insert
regular. No veo un personaje inválido allí, ¿verdad? (Ah, y ese código anterior funciona bien cuando lo ejecuto en mi herramienta de desarrollador sql ). Y si elimino el punto y coma en PreparedStatement
, arroja un error ORA-00933: SQL command not properly ended
.
En cualquier caso, aquí está mi código para ejecutar la consulta (y los valores de las variables para el ejemplo anterior).
public ResultSet executeQuery(String connection, String query, QueryParameter... params) throws DataException, SQLException {
// query at this point = "insert all
//into domo_queries values (?)
//select * from dual;"
Connection conn = ConnectionPool.getInstance().get(connection);
PreparedStatement pstmt = conn.prepareStatement(query);
for (int i = 1; i <= params.length; i++) {
QueryParameter param = params[i - 1];
switch (param.getType()) { //The type in the example is QueryParameter.CLOB
case QueryParameter.CLOB:
Clob clob = CLOB.createTemporary(conn, false, oracle.sql.CLOB.DURATION_SESSION);
clob.setString(i, "''" + param.getValue() + "''");
//the value of param.getValue() at this point is:
/*
* select
* substr(to_char(max_data),1,4) as year,
* substr(to_char(max_data),5,6) as month,
* max_data
* from dss_fin_user.acq_dashboard_src_load_success
* where source = ''''CHQ PeopleSoft FS''''
*/
pstmt.setClob(i, clob);
break;
case QueryParameter.STRING:
pstmt.setString(i, "''" + param.getValue() + "''");
break;
}
}
ResultSet rs = pstmt.executeQuery(); //Obviously, this is where the error is thrown
conn.commit();
ConnectionPool.getInstance().release(conn);
return rs;
}
¿Hay algo que me pierda a lo grande?
En lo alto de mi cabeza, ¿puedes intentar usar el operador ''q'' para la cadena literal
algo como
insert all
into domo_queries values (q''[select
substr(to_char(max_data),1,4) as year,
substr(to_char(max_data),5,6) as month,
max_data
from dss_fin_user.acq_dashboard_src_load_success
where source = ''CHQ PeopleSoft FS'']'')
select * from dual;
Tenga en cuenta que las comillas simples de su predicado no se escapan, y la cadena se encuentra entre q ''[...]''.
Si usa el literal de cadena exactamente como nos lo ha mostrado, el problema es el ;
personaje al final. No puede incluir eso en la cadena de consulta en las llamadas JDBC.
Como está insertando solo una fila, un INSERT
regular debería estar bien incluso cuando inserte varias filas. Usar una declaración por lotes es probable que sea más eficiente. No es necesario INSERT ALL
. Además, no necesitas el clob temporal y todo eso. Puede simplificar su método a algo como esto (suponiendo que obtuve los parámetros correctos):
String query1 = "select substr(to_char(max_data),1,4) as year, " +
"substr(to_char(max_data),5,6) as month, max_data " +
"from dss_fin_user.acq_dashboard_src_load_success " +
"where source = ''CHQ PeopleSoft FS''";
String query2 = ".....";
String sql = "insert into domo_queries (clob_column) values (?)";
PreparedStatement pstmt = con.prepareStatement(sql);
StringReader reader = new StringReader(query1);
pstmt.setCharacterStream(1, reader, query1.length());
pstmt.addBatch();
reader = new StringReader(query2);
pstmt.setCharacterStream(1, reader, query2.length());
pstmt.addBatch();
pstmt.executeBatch();
con.commit();