Ich versuche, aus einer Zeichenfolge von> 4000 Zeichen (in der Bindevariablen file_data enthalten) einen Clob zu erstellen, der in einem der folgenden Oracle SELECT-Prädikate verwendet wird:
myQuery=
select *
from dcr_mols
WHERE flexmatch(ctab,:file_data,'MATCH=ALL')=1;
Wenn ich TO_CLOB () round file_data hinzufüge, verfehlt dies das berüchtigte Oracle 4k-Limit für einen Varchar (es ist in Ordnung für <4k-Strings). Der Fehler (in SQL Developer) ist:
ORA-01460: unimplemented or unreasonable conversion requested
01460. 00000 - "unimplemented or unreasonable conversion requested"
Zu Ihrer Information Die Flexmatch-Funktion wird zum Suchen von Molekülen verwendet und hier beschrieben: http://help.accelrysonline.com/ulm/onelab/1.0/content/ulm_pdfs/direct/developers/direct_2016_developersguide.pdf
Die Funktion selbst ist etwas kompliziert, aber das Wesentliche ist, dass der 2. Parameter ein Clob sein muss. Meine Frage ist also, wie ich eine Java-Zeichenfolge bind_variable mit über 4000 Zeichen in einen Clob in SQL (oder Java) konvertiere.
Ich habe die folgende Methode (die beim Einfügen von Clobs funktioniert) in Java (Spring Boot 2) mit folgenden Methoden ausprobiert:
MapSqlParameterSource parameters = new MapSqlParameterSource();
parameters.addValue("file_data", fileDataStr,Types.CLOB);
jdbcNamedParameterTemplate.query(myQuery,parameters,…
Diese Methode sollte funktionieren, schlägt jedoch mit einem überlasteten Flexmatch-Fehler fehl, der zu Ihrer Information lautet:
SQL state [99999]; error code [29902]; ORA-29902: error in executing ODCIIndexStart() routine\nORA-20100:
MDL-0203: Unable to read from CLOB (csfrm=1, csid=873):
ORA-22922: nonexistent LOB value\nMDL-0021: Unable to copy LOB to string\nMDL-1051: Molstructure search query is not a valid molecule\nMDL-0976:
Molecule index search initialization failed\nORA-06512: at \"C$MDLICHEM80.MDL_MXIXMDL\", line 329\nORA-06512: at \"C$MDLICHEM80.MDL_MXIXMDL\", line 309\n; nested exception is java.sql.SQLException:
ORA-29902: error in executing ODCIIndexStart() routine\nORA-20100: MDL-0203: Unable to read from CLOB (csfrm=1, csid=873):
ORA-22922: nonexistent LOB value\nMDL-0021: Unable to copy LOB to string\nMDL-1051: Molstructure search query is not a valid molecule\nMDL-0976:
Molecule index search initialization failed\nORA-06512: at \"C$MDLICHEM80.MDL_MXIXMDL\", line 329\nORA-06512: at \"C$MDLICHEM80.MDL_MXIXMDL\", line 309\n"
Beachten Sie, dass ich SpringBoot 2 verwende, aber mit einer OracleConnection (die von meinem Spring NamedParametersJdbcTemplate-Objekt erhalten wurde) keine Methode zum Arbeiten (auch bei Clobs <4k) erhalten kann. Ich vermute also, dass ich etwas Dummes getan habe. Ich habe es versucht:
@Autowired
NamedParameterJdbcTemplate jdbcNamedParameterTemplate;
OracleConnection conn = this.jdbcNamedParameterTemplate.getJdbcTemplate().getDataSource().getConnection().unwrap(OracleConnection.class);
Clob myClob = conn.createClob();
myClob.setString( 1, fileDataStr);
MapSqlParameterSource parameters = new MapSqlParameterSource();
parameters.addValue("file_data", myClob,Types.CLOB);
application.properties:
spring.datasource.url=jdbc:oracle:thin:@//${ORA_HOST}:${ORA_PORT}/${ORA_SID}
spring.datasource.username=${ORA_USER}
spring.datasource.password=${ORA_PASS}
Beachten Sie, dass es gut funktioniert, wenn ich in die alte Schule gehe und eine Nicht-Feder-Verbindung sowie ein PreparedStatement verwende, das eine setClob () -Methode hat:
OracleDataSource ods = new OracleDataSource();
String url ="jdbc:oracle:thin:@//" + ORA_HOST +":"+ORA_PORT +"/"+ORA_SID;
ods.setURL(url);
ods.setUser(user);
ods.setPassword(passwd);
Connection conn = ods.getConnection();
Clob myClob=conn.createClob();
PreparedStatement ps = conn.prepareStatement("select dcr_number from dcr_mols WHERE flexmatch(ctab,?,'MATCH=ALL')=1");
myClob.setString(1,myMol);
ps.setClob(1,myClob);
ResultSet rs =ps.executeQuery();
Aber ich würde eine Spring 2-Lösung in Java oder SQL bevorzugen. Jede Hilfe, Vorschläge geschätzt.
flexmatch()
Funktion hinweisen ? Ich würde gerne die Notwendigkeit dafür sehen. Ehrlich gesagt habe ich in derWHERE
Klausel nie große Werte als Parameter verwendet . Ich habe sie in verwendetINSERT
und ich habe sie mit abgerufenSELECT
. Ihr Fall ist anders.Antworten:
Streame es. Sie können nicht einfach einen großen Wert in eine SQL-Anweisung einfügen.
Sie müssen:
INSERT
Anweisung ein (mit EMPTY_BLOB ()? ... nicht ganz erinnern).Dies ist die Standardmethode für den Umgang mit massiven Daten in Oracle. Viele Beispiele da draußen.
Das Abrufen umfangreicher Daten (
BLOB
undCLOB
Typen) funktioniert auf die gleiche Weise. Verwenden Sie in diesem Fall einfach InputStreams.quelle
Wenn Sie die Dokumentation der API "BIOVIA Direct" lesen, finden Sie auf Seite 27 ein interessantes Beispiel, Auszug unten:
Es wird ein bereits geladenes CLOB verwendet. Daher denke ich, dass eine ausreichend gute Lösung darin besteht, das CLOB in eine Tabelle von Ihnen zu laden (oder sie alle im Voraus vorzuladen) und sie dann einfach zu verwenden.
Schritt 1 - Laden Sie Ihren CLOB in eine Tabelle:
Verwenden Sie Ihren Java-Code, um die CLOB-Einfügung (wahrscheinlich mithilfe von Streams) durchzuführen, wie in einer anderen Antwort gezeigt (viele Beispiele im Internet). Fügen Sie beispielsweise Ihren Mol-Dateninhalt mit ID = ein
123
.Schritt 2 - Führen Sie Ihre Abfrage mit der bereits geladenen mol-Datei aus:
Sie können den
:id
Parameter so einstellen123
, dass er die zuvor geladene Datei (oder eine andere) verwendet.quelle
Sie können Ihre alte Modefunktion so nennen. Erstellen Sie eine Klasse für das ResultSet
und rufen Sie Ihre Abfrage mit der JdbcTemplate in Ihrer Methode auf
quelle
Ich musste wieder ein PreparedStatement verwenden, aber ich habe die normale Implementierung ein wenig verbessert, indem ich die Verbindung von Spring abgerufen und Apache Commons BeanListHandler verwendet habe, um das ResultSet einer Objektliste zuzuordnen
quelle
Sie können fileDataStr mit con als Verbindung deklarieren
und dann benutze es wie unten
Wenn Sie in Ihrer Verbindungszeichenfolge die SID anstelle des Dienstnamens verwenden, ändern Sie die Eigenschaftendatei wie unten beschrieben
quelle