স্ট্রিং> 4 কে থেকে তৈরি প্রিকেটটিতে একটি ওরাকল ক্লোব ব্যবহার করুন


11

আমি নীচে ওরাকল সিলেক্ট প্রিডিকেটটিতে ব্যবহার করতে> 4000 চর (ফাইল_ডাটা বাইন্ড ভেরিয়েবলের সরবরাহ করা) এর স্ট্রিং থেকে একটি ক্লোব তৈরি করার চেষ্টা করছি:

myQuery=
select *
from dcr_mols
WHERE flexmatch(ctab,:file_data,'MATCH=ALL')=1;

যদি আমি TO_CLOB () রাউন্ড ফাইল_ডেটা যোগ করি তবে এটি কোনও ভারচারের জন্য কুখ্যাত ওরাকল 4k সীমা ব্যর্থ করে (এটি <4k স্ট্রিংয়ের জন্য ঠিক আছে)। ত্রুটিটি (এসকিউএল বিকাশকারীতে) হ'ল:

ORA-01460: unimplemented or unreasonable conversion requested
01460. 00000 -  "unimplemented or unreasonable conversion requested"

অবগতির জন্য flexmatch ফাংশন অণু অনুসন্ধানের জন্য ব্যবহার করা হয়, এবং একটি এখানে বর্ণিত হয়: http://help.accelrysonline.com/ulm/onelab/1.0/content/ulm_pdfs/direct/developers/direct_2016_developersguide.pdf

ফাংশনটি নিজেই কিছুটা জটিল তবে সংক্ষেপে ২ য় প্যারামিটারটি একটি চুল্লা হতে হবে। সুতরাং আমার প্রশ্নটি হল আমি কীভাবে 4000 এর বেশি অক্ষরের একটি জাভা স্ট্রিং বাইন্ড_ভেরিয়েবলকে স্কোলে (বা জাভা) একটি চকিতে রূপান্তর করব।

আমি জাভাতে (স্প্রিং বুট 2) নীচের পদ্ধতিটি ব্যবহার করেছি (যা ক্লোবগুলি সন্নিবেশ করার সময় কাজ করে):

MapSqlParameterSource parameters = new MapSqlParameterSource();
parameters.addValue("file_data", fileDataStr,Types.CLOB);
jdbcNamedParameterTemplate.query(myQuery,parameters,…

এই পদ্ধতিতে কাজ করা উচিত তবে এটি রূপান্তরিত ফ্লেক্সমেচ ত্রুটিতে যা ব্যর্থ হয় যা এফওয়াইআই:

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"

নোট করুন আমি স্প্রিংবুট 2 ব্যবহার করছি তবে আমি কাজ করতে (এমনকি আমার ক্লিপ <4 কে তেও) আমার ওরক্লিং নেমডপ্যারামিটারজেডবিসিটেম্পলেট অবজেক্ট থেকে প্রাপ্ত) কোনও ওরাকল সংযোগ ব্যবহার করে কোনও পদ্ধতি পেতে পারি না, তাই আমার সন্দেহ হয় যে আমি বোকা কিছু করেছি। আমি চেষ্টা করেছিলাম:

 @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);

অ্যাপ্লিকেশন.প্রাপ্তি:

spring.datasource.url=jdbc:oracle:thin:@//${ORA_HOST}:${ORA_PORT}/${ORA_SID}
spring.datasource.username=${ORA_USER}
spring.datasource.password=${ORA_PASS}

যদি আমি পুরানো স্কুলে যাই এবং একটি নন স্প্রিং সংযোগ প্লাস একটি প্রস্তুতিমূলক স্টেটমেন্ট ব্যবহার করি তবে এটি দুর্দান্ত কাজ করে নোট করুন: এতে সেটক্লাব () পদ্ধতি রয়েছে:

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

তবে আমি জাভা বা এসকিউএলে একটি স্প্রিং 2 সমাধান পছন্দ করব। কোন সহায়তা, পরামর্শ প্রশংসা।


এটি বেশ ভাল প্রশ্ন +1, আমি এখন পর্যন্ত যা করেছি তার থেকে আলাদা। আপনি কি flexmatch()ফাংশনটির জন্য API ডক্সটি নির্দেশ করতে পারেন ? আমি এটির প্রয়োজনটি দেখতে চাই। সত্য, আমি কখনও ক্লজটিতে প্যারামিটার হিসাবে বড় মান ব্যবহার করি নি WHERE। আমি এগুলিতে ব্যবহার করেছি INSERTএবং, আমি তাদের ব্যবহার করে পুনরুদ্ধার করেছি SELECT। আপনার কেস আলাদা।
ইমপ্লেয়ার

@The_mpaler প্রশ্নের মধ্যে ডক্সের একটি লিঙ্ক আছে। এটি কোনও এপিআই ভীত নয়, তবে আমাদের যা কিছু আছে তা। এটি খুব কুলুঙ্গি কাজ। প্রয়োজনটি হ'ল আমি একটি অণুর ডিজিটাল উপস্থাপনা অনুসন্ধান করছি এবং এটি করার জন্য আপনার বিশেষজ্ঞের ফাংশন প্রয়োজন। অর্থাত্ dcr_mols টেবিলটিতে আমার আগে থেকেই অণু বিদ্যমান।
ডিএস

আপনি কী ওরাকল সংস্করণ ব্যবহার করছেন?
areus

@areaus ojdbc6-11.2.1.0.1
ডিএস।

উত্তর:


5

এটি স্ট্রিম। আপনি কেবল একটি এসকিউএল স্টেটমেন্টে একটি বিশাল মান পেস্ট করতে পারবেন না।

আপনার প্রয়োজন হবে:

  • INSERTবিবৃতিতে একটি ফাঁকা বিএলএলবি (োকান (EMPTY_BLOB () ব্যবহার করছেন? ... বেশ মনে নেই)।
  • খালি ব্লবটির জন্য আউটপুট স্ট্রিম পান।
  • তারপরে ফাইলটি থেকে একটি ইনপুট স্ট্রিম পান। সম্পূর্ণ ফাইলটি মেমরিতে লোড করবেন না।
  • তারপরে বাফারিং ব্যবহার করে ইনপুট স্ট্রিম থেকে ব্লকগুলি আউটপুট স্ট্রিমে স্থানান্তর করুন। একটি 16 কেবি বাফার করা উচিত।
  • উভয় ধারা বন্ধ করুন।

এটি ওরাকলে বিশাল ডেটা নিয়ে কাজ করার মানক উপায়। উদাহরণ এখানে প্রচুর।

বিশাল ডেটা ( BLOBএবং CLOBপ্রকারগুলি) পুনরুদ্ধার একই পদ্ধতিতে কাজ করে। সেক্ষেত্রে কেবল ইনপুট স্ট্রিম ব্যবহার করুন।


@ থিম্পালার আমি একটি গাঁদা notোকাচ্ছি না। আমি কোনও ফাংশনগুলিতে একটি গামছা সরবরাহ করছি যা একটি নির্বাচনের প্রিডিকেটে ডাকা হয়
ডিএস।

1

"BIOVIA ডাইরেক্ট" এপিআই এর ডকুমেন্টেশন পড়া, 27 পৃষ্ঠায় একটি আকর্ষণীয় উদাহরণ রয়েছে, নীচের অংশে উদ্ধৃত হয়েছে:

select ...
from ...
where flexmatch(
ctab,
(select ctab from nostruct_table),
'all'
)=1

এটি ইতিমধ্যে লোড হওয়া সিএলওবি ব্যবহার করে । অতএব আমি একটি শালীন যথেষ্ট অনুমান সমাধান হ'ল সিএলওবিটি আপনার একটি টেবিলের মধ্যে লোড করা (বা সেগুলি আগেই লোড করা) এবং তারপরে কেবল সেগুলি ব্যবহার করুন।

পদক্ষেপ # 1 - আপনার সিএলবি একটি টেবিলে লোড করুন:

create table mol_file (
  id number(12) primary key not null,
  content clob
);

insert into mol_file (id, content) values (:id, :content);

এবং আপনার উত্তরে জাভা কোডটি ব্যবহার করুন CLOB সন্নিবেশ (সম্ভবত স্ট্রিম ব্যবহার করে) অন্য উত্তরে দেখানো হয়েছে (ইন্টারনেটে প্রচুর উদাহরণ)। উদাহরণস্বরূপ, আইডি = সহ আপনার মোল ডেটা সামগ্রী sertোকান 123

পদক্ষেপ # 2 - ইতিমধ্যে লোড হওয়া মোল ফাইলটি ব্যবহার করে আপনার ক্যোয়ারী চালান:

select *
from dcr_mols
WHERE flexmatch(
        ctab,
        (select content from mol_file where id = :id),
        'MATCH=ALL'
      ) = 1;

আপনি আগে লোড করা ফাইলটি (বা অন্য কোনও) ব্যবহার :idকরতে 123আপনি প্যারামিটার সেট করতে পারেন।


@ দ্য_পিমালার ধন্যবাদ, তবে বাদাম ফাটানোর জন্য এটি কিছুটা স্লেজহ্যামার আমাদের চালানোর জন্য প্রচুর প্রশ্ন রয়েছে এবং এটি কোডকে জটিল করে তুলবে এবং জিনিসগুলি ধীর করে দেবে। আমি আমার প্রশ্নটি একটি পুরানো স্কুল উত্তরের সাথে আপডেট করেছি, যা আরও ভাল কিছু না উঠলে আমি অনিচ্ছায় ব্যবহার করব।
ডিএস

1

আপনি আপনার পুরানো ফ্যাশন ফাংশনটিকে এভাবে কল করতে পারেন। রেজাল্টসেট হ্যান্ডেল করার জন্য একটি ক্লাস তৈরি করুন

 class MyPreparedStatementCallback implements PreparedStatementCallback {
    public Object doInPreparedStatement(PreparedStatement preparedStatement)
            throws SQLException, DataAccessException {
        ResultSet rs = preparedStatement.executeQuery();
        List result = new LinkedList();
        rs.close();
        return result;
    }
}

এবং আপনার পদ্ধতিতে JdbcTemplate ব্যবহার করে আপনার জিজ্ঞাসা কল করুন

 jdbcTemplate.execute(new PreparedStatementCreator() {
        @Override
        public PreparedStatement createPreparedStatement(Connection connection)

                throws SQLException, DataAccessException {

            PreparedStatement ps = connection.prepareStatement("select dcr_number from dcr_mols WHERE flexmatch(ctab,?,'MATCH=ALL')=1");
            Clob myClob =  connection.createClob();
            myClob.setString( 1, fileDataStr);
            MapSqlParameterSource parameters = new MapSqlParameterSource();
            parameters.addValue("file_data", myClob, Types.CLOB);
            ps.setClob(1,myClob);
            return ps;

        };
    }, new MyPreparedStatementCallback());

1

আমাকে একটি প্রস্তুতিমূলক স্টেটমেন্ট ব্যবহার করে ফিরে যেতে হয়েছিল, তবে স্প্রিং থেকে সংযোগ পেয়ে এবং অ্যাপাচি কমন্স বিয়ানলিস্টহ্যান্ডলারের সাহায্যে রেজাল্টসেটটিকে কোনও অবজেক্টের তালিকায় ম্যাপ করে আমি কিছুটা বাস্তবায়ন কিছুটা উন্নত করেছি improved

import org.apache.commons.dbutils.ResultSetHandler;
import org.apache.commons.dbutils.handlers.BeanListHandler;

@Autowired
NamedParameterJdbcTemplate  jdbcTemplate;

List<MyDao> myMethod(String fileData){
    String myQuery="select * from dcr_mols WHERE flexmatch(ctab,?,'MATCH=ALL')=1";

try {
    Connection conn =  this.jdbcTemplate.getJdbcTemplate().getDataSource().getConnection().unwrap(OracleConnection.class);   // Get connection from spring

    Clob myClob =  conn.createClob();   // Open a dB clob 
    myClob.setString( 1, fileData);     // add data to clob
    PreparedStatement ps = conn.prepareStatement(myQuery);
    ps.setClob(1,myClob);              // Add a clob into the PreparedStatement
    ResultSet rs =ps.executeQuery();   // Execute the prepared statement

    //ResultSetHandler<List<MyDao>> handler = new BeanListHandler<MyDao>(MyDao.class);   // Define the ResultSet handler
    ResultSetHandler<List<MyDao>> handler = new BeanListHandler<MyDao>(MyDao.class, new BasicRowProcessor(new GenerousBeanProcessor()));  // This is better than the above handler , because GenerousBeanProcessor removes the requirement for the column names to exactly match the java variables

    List<MyDao> myDaoList = handler.handle(rs);   // Map ResultSet to List of MyDao objects
    }catch (Exception e) {
        e.printStackTrace();
    }

return myDaoList;
}

0

আপনি ফাইলডাটাএসটিআর কে সিএলওবি হিসাবে সংযোগ হিসাবে ব্যবহার করে ঘোষণা করতে পারেন

java.sql.Clob fileDataStr = oracle.sql.CLOB.createTemporary
(con, false, oracle.sql.CLOB.DURATION_SESSION);

এবং তারপরে নীচের মতো এটি ব্যবহার করুন

 parameters.addValue("file_data", fileDataStr,Types.CLOB);

এছাড়াও আপনি যদি নিজের সংযোগ স্ট্রিংয়ে পরিষেবার নামের পরিবর্তে এসআইডি ব্যবহার করছেন তবে নীচের মতো আপনার সম্পত্তি ফাইলটি পরিবর্তন করার চেষ্টা করুন

spring.datasource.url=jdbc:oracle:thin:@//${ORA_HOST}:${ORA_PORT}:${ORA_SID}

ধন্যবাদ, তবে এটি খুব বিশ্রী। ডেটা যে কোনও আকারের হতে পারে তাই আমাকে খণ্ডগুলি তৈরি করতে ডায়নামিক এসকিএল ব্যবহার করতে হবে, আপনিও নিশ্চিত নন যে আপনি এই জাতীয় অংশগুলিতে একটি গিরা ভেঙে ফেলতে পারবেন।
ডিএস

ফাইলডাটাএসটিআর এর ধরণ কী
psaraj12

এটি একটি জাভা স্ট্রিং
ডিএস।

আপনি কি এটিকে CLOB হিসাবে এবং java.sql.Clob fileDataStr = oracle.sql.CLOB.createTemporary (কন, মিথ্যা, oracle.sql.CLOB.DURATION_SESSION) এর মতো ঘোষণা করতে পারেন;
psaraj12

কনড যেখানে সংযোগ রয়েছে সেখানে ফাইলডাটাএসটিআরকে সিএলওবি হিসাবে কীভাবে ঘোষণা করবেন মন্তব্য সম্পর্কে আমার উদাহরণ দেখুন
psaraj12
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.