Saya mencoba membuat clob dari string> 4000 chars (disediakan dalam variabel bind file_data) untuk digunakan dalam predikat Oracle SELECT di bawah ini:
myQuery=
select *
from dcr_mols
WHERE flexmatch(ctab,:file_data,'MATCH=ALL')=1;
Jika saya menambahkan TO_CLOB () round file_data ia gagal membatasi Oracle 4k yang terkenal untuk varchar (tidak apa-apa untuk string <4k). Kesalahan (dalam SQL Developer) adalah:
ORA-01460: unimplemented or unreasonable conversion requested
01460. 00000 - "unimplemented or unreasonable conversion requested"
FYI Fungsi flexmatch digunakan untuk mencari molekul, dan dijelaskan di sini: http://help.accelrysonline.com/ulm/onelab/1.0/content/ulm_pdfs/direct/developers/direct_2016_developersguide.pdf
Fungsi itu sendiri agak rumit tetapi intinya adalah parameter ke-2 harus menjadi clob. Jadi pertanyaan saya adalah bagaimana cara mengonversi Java String bind_variable lebih dari 4000 chars ke clob di sql (atau Java).
Saya mencoba metode di bawah ini (yang berfungsi saat memasukkan gumpalan) di Java (Spring boot 2) menggunakan:
MapSqlParameterSource parameters = new MapSqlParameterSource();
parameters.addValue("file_data", fileDataStr,Types.CLOB);
jdbcNamedParameterTemplate.query(myQuery,parameters,…
Metode ini harus berfungsi tetapi gagal dengan kesalahan flexmatch terkonversi yang FYI adalah:
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"
Catatan saya menggunakan SpringBoot 2 tapi saya tidak bisa mendapatkan metode apa pun menggunakan OracleConnection (diperoleh dari objek Spring NamedParametersJdbcTemplate) saya untuk bekerja (bahkan pada clobs <4k), jadi saya curiga saya telah melakukan sesuatu yang bodoh. Saya sudah mencoba:
@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);
properti aplikasi:
spring.datasource.url=jdbc:oracle:thin:@//${ORA_HOST}:${ORA_PORT}/${ORA_SID}
spring.datasource.username=${ORA_USER}
spring.datasource.password=${ORA_PASS}
Catatan itu berfungsi dengan baik jika saya pergi ke sekolah lama dan menggunakan koneksi non spring plus PreparedStatement, yang memiliki metode setClob ():
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();
Tapi saya lebih suka solusi Spring 2 di Java atau Sql. Setiap bantuan, saran sangat dihargai.
flexmatch()
fungsi ini? Saya ingin melihat perlunya hal ini. Jujur, saya tidak pernah menggunakan nilai besar sebagai parameter dalamWHERE
klausa. Saya telah menggunakannyaINSERT
dan, saya mengambilnya menggunakanSELECT
. Kasing Anda berbeda.Jawaban:
Streaming itu. Anda tidak bisa hanya menempelkan nilai besar ke dalam pernyataan SQL.
Anda harus:
INSERT
pernyataan (menggunakan EMPTY_BLOB ()? ... tidak begitu ingat).Ini adalah cara standar untuk menangani data masif di Oracle. Banyak contoh di luar sana.
Mengambil data besar (
BLOB
danCLOB
tipe) bekerja dengan cara yang sama. Cukup gunakan InputStreams dalam kasus itu.sumber
Membaca dokumentasi API "BIOVIA Direct", ada contoh yang menarik di halaman 27, kutipan yang ditunjukkan di bawah ini:
Ini menggunakan CLOB yang sudah dimuat . Oleh karena itu saya kira solusi yang cukup layak adalah dengan memuat CLOB ke dalam tabel Anda (atau pra-muat semuanya di muka), dan kemudian gunakan saja.
Langkah # 1 - Muat CLOB Anda ke dalam tabel:
Dan gunakan kode Java Anda untuk melakukan penyisipan CLOB (mungkin menggunakan stream) seperti yang ditunjukkan dalam jawaban lain (banyak contoh di Internet). Misalnya, masukkan konten data mol Anda dengan ID =
123
.Langkah # 2 - Jalankan permintaan Anda, menggunakan file mol yang sudah dimuat:
Anda dapat mengatur
:id
parameter untuk123
menggunakan file yang Anda muat sebelumnya (atau yang lainnya).sumber
Anda dapat memanggil fungsi mode lama Anda seperti ini. buat Kelas untuk menangani ResultSet
dan panggil permintaan Anda menggunakan JdbcTemplate dalam metode Anda
sumber
Saya harus kembali menggunakan PreparedStatement, tetapi saya telah sedikit meningkatkan implementasi normal dengan mendapatkan koneksi dari Spring dan menggunakan apache commons BeanListHandler untuk memetakan ResultSet ke daftar objek
sumber
Anda dapat mendeklarasikan fileDataStr sebagai CLOB menggunakan con yang merupakan koneksi
dan kemudian gunakan seperti di bawah ini
Juga jika Anda menggunakan SID alih-alih nama Layanan di string koneksi Anda, coba ubah file properti Anda seperti di bawah ini
sumber