|
Программирование >> Oracle
Пакет DBMS LOB 1611 Функция substr Небольшое примечание относительно функции substr, предлагаемой в пакете DBMS LOB. Все остальные реализации функции substr, с которыми мне приходилось сталкиваться ( в том числе в языках SQL и PL/SQL), принимают следующие аргументы, в указанном порядке: substr(стpoкa, с какого свола, сколько сволов) ; Так что substr(hello, 3, 2) даст в результате строку - третий и четвертый символы (начиная с символа 3 выбрать 2 символа). В функции DBMS LOB.SUBSTR, однако, порядок параметров другой: dbms lob.substr(большой объект, сколько символов, с какого символа) Поэтому аналогичный вызов функции substr из пакета DBMS LOB вернет строку ell. Небольшой тестовый пример подтверждает это: tkyte@TKYTE816> create table t (str varchar2(10), lob clob); Table created. tkyte@TKYTE816>insert into t values (hello, hello); I row created. tkyte@TKYTE816> select substr(str, 3, 2), 2 dbms lob.substr(lob, 3, 2) lob 3 from t SU LOB II ell Я постоянно передаю аргументы не в том порядке. Это - одна из тех вещей, о кото-р1х надо помнить! Оператор SELECT FOR UPDATE в языке Java Чтобы изменить большой (не временный) объект в базе данных, строка, содержащая его, должна быть заблокирована соответствующим сеансом. Обычно это не учитывают те, кто пишет программы на языке Java/JDBC. Рассмотрим представленную далее небольшую программу на Java. Она: вставляет запись (поэтому резонно предположить, что эта запись заблокирована); читает локатор только что созданного большого объекта; пытается использовать этот локатор большого объекта в процедуре DBMS LOB.WRITEAPPEND. При выполнении этой Java-программы всегда выдается сообщение об ошибке: java Test java.sql.SQLException: ORA-22920: row containing the LOB value is not locked ORA-06512: at SYS.DBMS LOB , line 715 ORA-06512: at line 1 1612 Приложение А Оказывается, вставленный большой объект больше не заблокирован сеансом. Это печальный побочный эффект стандартного режима поддержки транзакций протокола JDBC - по умолчанию транзакции не поддерживаются! Фиксация выполняется немедленно после каждого оператора. Если в следующем приложении не добавить вызов conn.setAutoCommit (false); сразу же после getConnection, оно не будет работать. строка кода (по моему мнению) должна быть первой после любого подключения в программе, использующей интерфейс JDBC! import java.sql.*; import java.io.*; import oracle.jdbc.driver.*; import oracle.sql.*; Для выполнения этого приложения нужна следующая таблица: create table demo (id int primary key, theBlob blob); class Test { public static void main (String args []) throws SQLException , FileNotFoundException, IOException DriverManager.registerDriver (new oracle.jdbc.driver.OracleDriverO); Connection conn = DriverManager.getConnection ( jdbc:oracle:thin:@aria:1521:ora8i , scott , tiger ); Если хотите, чтобы программа сработала, уберите комментарий со следующей строки! conn.setAutoCoamit(false); Statement stmt - conn.createStatement(); Вставляем в таблицу пустой BLOB При первом вызове создадим его. stmt.execute ( insert into demo (id,theBlob) + values (l,empty blob()) ); Теперь прочитаем его, чтобы можно было загрузить данные. ResultSet rset = stmt.executeQuery ( SELECT theBlob + FROM demo + where id = 1 ); if(rset.next()) Получить BLOB для загрузки. ElOB l mapBB = ((OracleResultSet)rset).getBLOB(l); Вот данные, которые мы в него загрузим. File binaryFile - new File( /tmp/binary.dat ); FilelnputStream instream = new FileInputStream(binaryFile); Мы будем загружать примерно по 32 Кбайт за раз. Это максимальный фрагмент, поддерживаем1й пакетом dbms lob (ограничение яз1ка PL/SQL). Пакет DBMS LOB 1613 int chunk = 32000; byte[] l buffer = new byte[chunk]; int l nread = 0; / / Используем простую процедуру writeappend для добавления фрагмента файла в конец BLOB-бьекта. OracleGallableStatement cstmt = (OracleGallableStatement)conn.prepareGall ( begin dbms lob.writeappend( :1, :2, :3 ); end; ); Читаем и записываем, пока не загрузим весь файл. cstmt.registerOutParameter(1, OracleTypes.BLOB); while ((l nread= instream.read(l buffer)) != -1) cstmt.setBLOB(1, l mapBLOB); cstmt.setInt(2, l nread); cstmt.setBytes(3, l buffer); cstmt.executeUpdate(); l mapBLOB=cstmt.getBLOB(l); / / Закрываем входной файл и завершаем оператор. instream.close(); cstmt.close(); / / Завершаем остальные операторы. rset.close(); stmt.close(); conn.close (); Это общее ограничение протокола JDBC, влияющее, в частности, и на работу с большими объектами. Я не знаю, сколько разработчиков с удивлением обнаруживало, что интерфейс по умолчанию автоматически фиксирует транзакцию - это ведь должно делать приложение. Этого могут ожидать только разработчики, ранее использовавшие интерфейс ODBC! Аналогичное действие выполняет протокол ODBC в стандартном для него режиме автоматической фиксации. Преобразования Часто пользователи хранят данные в объектах типа BLOB, но иногда нужно представить их как данные типа CLOB. Типичный пример: в столбец типа BLOB загружены двоичные и текстовые данные, и необходимо проанализировать текст. Анализировать данные типа BLOB сложно, поскольку сервер постоянно пытается преобразовать их в шестнадцатиричное представление, что нежелательно. В других случаях имеются данные типа LONG или LONG RAW, которые хотелось бы обрабатывать как данные типов CLOB или BLOB, поскольку функциональные возможности обработки этих типов намного превосходят те, что поддерживаются для типов LONG и LONG RAW.
|
© 2006 - 2025 pmbk.ru. Генерация страницы: 0
При копировании материалов приветствуются ссылки. |