Я пытаюсь создать clob из строки> 4000 символов (предоставленной в переменной связывания file_data) для использования в предикате Oracle SELECT ниже:
myQuery=
select *
from dcr_mols
WHERE flexmatch(ctab,:file_data,'MATCH=ALL')=1;
Если я добавлю TO_CLOB () в раунд file_data, он выйдет из пресловутого предела Oracle 4k для varchar (это хорошо для строк <4k). Ошибка (в SQL Developer):
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
Сама функция немного сложна, но суть в том, что 2-й параметр должен быть clob. Поэтому мой вопрос заключается в том, как преобразовать переменную Java String bind_variable, содержащую более 4000 символов, в clob в sql (или Java).
Я попробовал метод ниже (который работает при вставке сгустков) в Java (Spring boot 2), используя:
MapSqlParameterSource parameters = new MapSqlParameterSource();
parameters.addValue("file_data", fileDataStr,Types.CLOB);
jdbcNamedParameterTemplate.query(myQuery,parameters,…
Этот метод должен работать, но он терпит неудачу с конвертированной ошибкой flexmatch, которая является FYI:
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"
Обратите внимание, что я использую SpringBoot 2, но я не могу получить какой-либо метод, использующий OracleConnection (полученный из моего объекта Spring NamedParametersJdbcTemplate) для работы (даже с clobs <4k), поэтому я подозреваю, что сделал что-то глупое. Я пробовал:
@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}
Обратите внимание, что это нормально работает, если я иду в старое учебное заведение и использую не пружинное соединение плюс PreparedStatement, у которого есть метод 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();
Но я бы предпочел решение Spring 2 на Java или Sql. Любая помощь, предложения приветствуются.
flexmatch()
функции? Я хотел бы видеть необходимость в этом. Честно говоря, я никогда не использовал большие значения в качестве параметров вWHERE
предложении. Я использовал ихINSERT
и извлек их используяSELECT
. Ваш случай отличается.Ответы:
Поток это. Вы не можете просто вставить огромное значение в оператор SQL.
Вам нужно будет:
INSERT
оператор (используя EMPTY_BLOB ()? ... не совсем помню).Это стандартный способ работы с массивными данными в Oracle. Там много примеров.
Получение массивных данных (
BLOB
иCLOB
типов) работает аналогично. Просто используйте InputStreams в этом случае.источник
Читая документацию по API «BIOVIA Direct», на странице 27 есть интересный пример, фрагмент которого приведен ниже:
Он использует уже загруженный CLOB. Поэтому я полагаю, что достаточно приличным решением было бы загрузить CLOB в вашу таблицу (или предварительно загрузить их все), а затем просто использовать их.
Шаг № 1 - Загрузите ваш CLOB в таблицу:
И используйте свой Java-код для выполнения вставки CLOB (возможно, с использованием потоков), как показано в другом ответе (множество примеров в Интернете). Например, вставьте содержание данных мол с ID =
123
.Шаг № 2 - Запустите ваш запрос, используя уже загруженный файл mol:
Вы можете установить
:id
параметр для123
использования загруженного ранее файла (или любого другого).источник
Вы можете вызвать свою старую функцию моды следующим образом. создать класс для обработки ResultSet
и вызовите ваш запрос, используя JdbcTemplate в вашем методе
источник
Мне пришлось вернуться к использованию PreparedStatement, но я немного улучшил нормальную реализацию, получив соединение от Spring и используя Apache Commons BeanListHandler для сопоставления ResultSet с объектом List.
источник
Вы можете объявить fileDataStr как CLOB, используя con, который является соединением
а затем использовать его, как показано ниже
Также, если вы используете SID вместо имени службы в строке подключения, попробуйте изменить свой файл свойств, как показано ниже
источник