2010-07-16 8 views
6

Esta instrucción SQL funciona si lo ejecuto desde mi cliente de Oracle (SQL Developer):para insertarse después de Identificación INSERT ... SELECT en Oracle

insert into Person (Name) select 'Bob' from dual 

También funciona si emitirlo a través de la primavera JDBC, sin utilizando un KeyHolder:

final PreparedStatementCreator psc = new PreparedStatementCreator() { 

    @Override 
    public PreparedStatement createPreparedStatement(Connection con) 
     throws SQLException 
    { 
     return con.prepareStatement(
       "insert into Person (Name) select 'Bob' from dual"); 
    } 
}; 
jdbcOperations.update(psc); 

Sin embargo tengo que usar una llave-con el fin de obtener el ID de la fila recién insertada. Si altero el código anterior para usar una llave-de la siguiente manera:

final KeyHolder keyHolder = new GeneratedKeyHolder(); 
final PreparedStatementCreator psc = new PreparedStatementCreator() { 

    @Override 
    public PreparedStatement createPreparedStatement(Connection con) 
     throws SQLException 
    { 
     return con.prepareStatement(
      "insert into Person (Name) select 'Bob' from dual", 
      new String[] {"PersonID"}); 
    } 
}; 
jdbcOperations.update(psc, keyHolder); 

... entonces me sale este error:

Exception in thread "main" org.springframework.jdbc.BadSqlGrammarException: PreparedStatementCallback; bad SQL grammar []; nested exception is java.sql.SQLSyntaxErrorException: ORA-00933: SQL command not properly ended 
    at org.springframework.jdbc.support.SQLExceptionSubclassTranslator.doTranslate(SQLExceptionSubclassTranslator.java:94) 
    at org.springframework.jdbc.support.AbstractFallbackSQLExceptionTranslator.translate(AbstractFallbackSQLExceptionTranslator.java:72) 
    at org.springframework.jdbc.support.AbstractFallbackSQLExceptionTranslator.translate(AbstractFallbackSQLExceptionTranslator.java:80) 
    at org.springframework.jdbc.core.JdbcTemplate.execute(JdbcTemplate.java:602) 
    at org.springframework.jdbc.core.JdbcTemplate.update(JdbcTemplate.java:842) 
    at au.com.bisinfo.codecombo.logic.ImportServiceImpl.insertLoginRedirectRule(ImportServiceImpl.java:107) 
    at au.com.bisinfo.codecombo.logic.ImportServiceImpl.runImport(ImportServiceImpl.java:68) 
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) 
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39) 
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25) 
    at java.lang.reflect.Method.invoke(Method.java:597) 
    at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:309) 
    at org.springframework.aop.framework.ReflectiveMethodInvocation.invokeJoinpoint(ReflectiveMethodInvocation.java:183) 
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:150) 
    at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:110) 
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172) 
    at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:202) 
    at $Proxy8.runImport(Unknown Source) 
    at au.com.bisinfo.codecombo.ui.Main.main(Main.java:39) 
Caused by: java.sql.SQLSyntaxErrorException: ORA-00933: SQL command not properly ended 
    at oracle.jdbc.driver.T4CTTIoer.processError(T4CTTIoer.java:439) 
    at oracle.jdbc.driver.T4CTTIoer.processError(T4CTTIoer.java:395) 
    at oracle.jdbc.driver.T4C8Oall.processError(T4C8Oall.java:802) 
    at oracle.jdbc.driver.T4CTTIfun.receive(T4CTTIfun.java:436) 
    at oracle.jdbc.driver.T4CTTIfun.doRPC(T4CTTIfun.java:186) 
    at oracle.jdbc.driver.T4C8Oall.doOALL(T4C8Oall.java:521) 
    at oracle.jdbc.driver.T4CPreparedStatement.doOall8(T4CPreparedStatement.java:205) 
    at oracle.jdbc.driver.T4CPreparedStatement.executeForRows(T4CPreparedStatement.java:1008) 
    at oracle.jdbc.driver.OracleStatement.doExecuteWithTimeout(OracleStatement.java:1307) 
    at oracle.jdbc.driver.OraclePreparedStatement.executeInternal(OraclePreparedStatement.java:3449) 
    at oracle.jdbc.driver.OraclePreparedStatement.executeUpdate(OraclePreparedStatement.java:3530) 
    at oracle.jdbc.driver.OraclePreparedStatementWrapper.executeUpdate(OraclePreparedStatementWrapper.java:1350) 
    at org.apache.commons.dbcp.DelegatingPreparedStatement.executeUpdate(DelegatingPreparedStatement.java:105) 
    at org.apache.commons.dbcp.DelegatingPreparedStatement.executeUpdate(DelegatingPreparedStatement.java:105) 
    at org.springframework.jdbc.core.JdbcTemplate$3.doInPreparedStatement(JdbcTemplate.java:844) 
    at org.springframework.jdbc.core.JdbcTemplate$3.doInPreparedStatement(JdbcTemplate.java:1) 
    at org.springframework.jdbc.core.JdbcTemplate.execute(JdbcTemplate.java:586) 
    ... 15 more 

Fwiw, todo está bien si hago un INSERT ... VALORES vez de un INSERT ... SELECT (aunque esto no me ayuda, ya que necesito para seleccionar cosas):

final KeyHolder keyHolder = new GeneratedKeyHolder(); 
final PreparedStatementCreator psc = new PreparedStatementCreator() { 

    @Override 
    public PreparedStatement createPreparedStatement(Connection con) 
     throws SQLException 
    { 
     return con.prepareStatement(
      "insert into Person (Name) values ('Bob')", 
      new String[] {"PersonID"}); 
    } 
}; 
jdbcOperations.update(psc, keyHolder); 

que estoy usando:

  • primavera JDBC 3.0.3.RELEASE
  • controlador JDBC: Versión ojdbc6.jar 11.2.0.1.0
  • RDBMS: Oracle9i versión 9.2.0.5.0 - Producción
  • Commons-DBCP 1,4

NB mi aplicación necesita usar SQL estándar para permanecer db-neutral, lo que descarta cualquier SQL específico de Oracle (no seleccionaré desde "dual" en la vida real).

Gracias por cualquier ayuda.

Respuesta

1

java.sql.Connection.prepareStatement(java.lang.String, int) interfaz es clara

Creates a default PreparedStatement object that has the capability to retrieve auto-generated keys

Así que usted está utilizando el método equivocado. Trate

return con.prepareStatement(
     "insert into Person (Name) select 'Bob' from dual", 
     Statement.RETURN_GENERATED_KEYS); 

lugar

+0

Ese método es uno de los tres que puede devolver las claves generadas, el otro dos siendo prepareStatement (String, int []) y prepareStatement (String, String []). Estoy usando el último, que IME es el correcto para Oracle. Aún así, intentaré su sugerencia y le contaré cómo va. –

+0

@Andrew Swan Tienes razón. ¡Gracias! Pero avíseme La salida –

0

¿Qué tal

INSERT INTO blah b (blah1, blah2, blah3) 
VALUES (?, ?, ?) RETURNING b.id INTO ?"; 
+0

No puedo usar INSERTAR ... VALORES porque necesito seleccionar cosas. Además, no quiero usar RETURNING .. INTO porque AFAIK es específico de Oracle. –

1

Esta función no está soportada por Oracle controlador JDBC

+1

Eso es lo que estoy adivinando; ¿Tiene una referencia para esto? –

Cuestiones relacionadas