web-dev-qa-db-de.com

Wo ist mein ungültiger Charakter (ORA-00911)

Ich versuche, CLOB in eine Datenbank einzufügen (siehe verwandte Frage ). Ich kann nicht genau herausfinden, was los ist. Ich habe eine Liste von ungefähr 85 Klumpen, die ich in eine Tabelle einfügen möchte. Selbst wenn ich nur den ersten Klumpen einfüge, bekomme ich ORA-00911: invalid character. Ich kann nicht herausfinden, wie ich die Anweisung aus der PreparedStatement herausholen kann, bevor sie ausgeführt wird. Daher kann ich nicht 100% sicher sein, dass sie richtig ist. Wenn ich sie jedoch richtig verstanden habe, sollte sie genau so aussehen Dies:

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;

Letztendlich ist dies insert all Anweisung hätte eine Menge into, weshalb ich einfach keine reguläre insert Anweisung mache. Ich sehe dort kein ungültiges Zeichen, oder? (Oh, und der obige Code funktioniert einwandfrei, wenn ich ihn in meinem SQL-Entwicklertool ausführe.) Und wenn ich das Semikolon in der PreparedStatement, wirft es ein ORA-00933: SQL command not properly ended Error.

In jedem Fall ist hier mein Code zum Ausführen der Abfrage (und die Werte der Variablen für das obige Beispiel).

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;
}

Gibt es irgendetwas, das ich gerade vermisse, große Zeit?

64
kentcdodds

Wenn Sie das Zeichenfolgenliteral genau so verwenden, wie Sie es uns gezeigt haben, liegt das Problem beim ; Zeichen am Ende. Sie dürfen dies nicht in die Abfragezeichenfolge in den JDBC-Aufrufen aufnehmen.

Da Sie nur eine einzelne Zeile einfügen, sollte ein reguläres INSERT auch dann in Ordnung sein, wenn Sie mehrere Zeilen einfügen. Die Verwendung einer Batch-Anweisung ist wahrscheinlich in jedem Fall effizienter. Kein Bedarf für INSERT ALL. Außerdem brauchst du nicht den temporären Lappen und das alles. Sie können Ihre Methode auf so etwas vereinfachen (vorausgesetzt, ich habe die Parameter richtig eingestellt):

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();
156

Können Sie versuchen, den Operator 'q' für das Zeichenfolgenliteral zu verwenden?

so etwas wie

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;

Beachten Sie, dass die einfachen Anführungszeichen Ihres Prädikats nicht maskiert werden und die Zeichenfolge zwischen q '[...]' steht.

6
user507484