![]() |
|
Программирование >> Oracle
Глава 9 Загрузка больших объектов Давайте рассмотрим некоторые методы загрузки данных в большие объекты. Речь идет не о столбцах типа LONG или LONG RAW, а о более предпочтительных типах BLOB и CLOB. Эти типы данных появились в Oracle 8.0 и предоставляют намного больше возможностей для работы, чем устаревшие типы LONG и LONG RAW. Мы изучим два метода загрузки данных в эти столбцы - с помощью SQLLDR и процедур на PL/SQL. Существуют и другие, например потоки Java, программирование на Рго*С и использование непосредственно функционального интерфейса OCI. В главе 18 рассматривается, как выгружать большие объекты с помощью Рго*С. Загрузка большого объекта будет выполняться аналогично, но вместо вызова EXEC SQL READ придется использовать EXEC SQL WRITE. Начнем с рассмотрения метода загрузки больших объектов с помощью PL/SQL, a затем опишем, как это сделать с помощью утилиты SQLLDR. Загрузка больших объектов с помощью PL/SQL Пакет DBMS LOB содержит подпрограмму LOADFROMFILE. Эта процедура позволяет использовать данные типа BFILE (представляющие файл в операционной системе) для наполнения столбцов типа BLOB или CLOB в базе данных. Чтобы можно было воспользоваться этой процедурой, необходимо создать в базе данных объект DIRECTORY. Этот объект позволит создавать объекты типа BFILE (и открывать их), ссылающиеся на файлы, существующие в файловой системе, к которой имеет доступ сервер баз данных. Последнее уточнение ( ... к которой имеет доступ сервер баз данных ) - ключевой момент при использовании PL/SQL для загрузки больших объектов. Пакет DBMS LOB работает на сервере. Он может обращаться только к тем файловым системам, к которым имеет доступ сервер. В частности, для пакета недоступна локальная файловая система рабочей станции, с которой вы обращаетесь к СУБД Oracle по сети. Нельзя с помощью PL/SQL загрузить большие объекты непосредственно с локальной машины, поскольку их нет на сервере. Итак, надо начать с создания объекта DIRECTORY в базе данных. Сделать это просто. Для примера я создам два каталога (на этот раз, примеры выполняются в среде ОС UNIX): ops$tkyte@DEV816> create or replace directory dir1 as /trap/; Directory created. ops$tkyte@DEV816> create or replace directory dir2 as /tmp/; Directory created. Пользователь, выполняющий эту операцию, должен обладать привилегией CREATE ANY DIRECTORY. Я создал два каталога, чтобы продемонстрировать общую проблему, связанную с регистром символов при работе с объектами-каталогами. При создании первого каталога, DIR1, сервер Oracle сохранил объект с именем в верхнем регистре, как принято по умолчанию. Во втором примере, DIR2, каталог создан с именем, ре- Загрузка данных 499 гистр символов в котором оставлен без изменений. Почему это существенно, будет показано ниже, при использовании объекта типа BFILE. Предположим, необходимо загрузить данные в столбец типа BLOB или CLOB. Это делается весьма просто, например: ops$tkyte@DEV816> create table demo 2 (id int primary key, 3 theClob clob Table created. ops$tkyte@DEV816> host echo Hello World\! > /tmp/test.txt ops$tkyte@DEV816> declare 2 l clob clob; 3 l bfile bfile; 4 begin 5 insert into demo values (1, empty dob()) 6 returning theclob into l clob; 8 l bfile := bfilename(DIR1 , test.txt); 9 dbms lob.fileopen(l bfile); 11 dbms lob.loadfromfile(l clob, l bfile, 12 dbms lob.getlength(l bfile)); 14 dbms lob.fileclose(l bfile); 15 end; 16 / PL/SQL procedure successfully completed. ops$tkyte@DEV816> select dbms lob.getlength(theClob) , theClob from demo 2 / DBMS LOB.GETLENGTH (THECLOB) THECLOB 13 Hello World! Интересно отметить, что если попытаться выполнить этот пример без изменений в Windows (поменяв, конечно, /tmp/ на каталог, соответствующий этой ОС), результат будет такой: tkyte@TKYTE816> select dbms lob.getlength(theClob), theClob from demo 2 / DBMS LOB.GETLENGTH(THECLOB) THECLOB 18 Hello Horld\! Длина данных получилась больше из-за того, что командный интерпретатор Windows обрабатывает апострофы и символы маскировки (\) не так, как в ОС UNIX, а признак конца строки здесь длиннее. Рассмотрим представленный выше код: 500 Глава 9 В строках 5 и 6 мы создали строку в таблице, задали столбцу типа CLOB значение EMPTY CLOB() и получили это значение - все это одним вызовом. Все большие объекты, за исключением временных, существуют в базе данных - мы не можем задать значение переменной типа LOB, не сославшись на временный большой объект или большой объект, уже находящийся в базе данных. Пустой объект EMPTY CLOB() - это не Null-значение типа CLOB; это непустой указатель на пустую структуру. При этом автоматически получается локатор LOB, указывающий на данные в заблокированной строке. Если бы это значение было выбрано без блокирования соответствующей строки, попытки записи в столбец завершились бы неудачно, поскольку перед записью большие объекты должны быть заблокированы (в отличие от других структурированных данных). При вставке строка, безусловно, блокируется. Если бы операция выполнялась с существующей строкой, ее пришлось бы выбирать с конструкцией FOR UPDATE для блокирования. В строке 8 создается объект типа BFILE. Обратите внимание, что имя каталога DIR1 задано в верхнем регистре - это принципиально важно, как будет показано ниже. Так необходимо делать потому, что функции BFILENAME передается имя объекта, а не сам объект. Поэтому необходимо убедиться, что имя для объекта задано в том регистре, в котором оно хранится в базе данных Oracle. В строке 9 открывается большой объект. Это позволит читать его. В строке 11 загружается все содержимое файла операционной системы /tmp/test.txt в только что вставленный большой объект, определяемый локатором. Мы используем функцию DBMS LOB.GETLENGTH для передачи подпрограмме LOADFROMFILE количества байтов, которые необходимо загрузить из файла BFILE (в данном случае грузится все). Наконец, в строке 14 открытый объект BFILE закрывается; все данные в столбец типа CLOB загружены. Если в представленном выше примере попытаться использовать dirl вместо DIR1, будет получено следующее сообщение об ошибке: ops$tkyte@DEV816> declare 2 l clob clob; 3 l bfile bfile; 4 begin 5 insert into demo values (1, empty clob()) 6 returning theclob into l clob; 7 8 l bfile := bfilename(dirl, test.txt); 9 dbms lob.fileopen(l bfile); 10 11 dbms lob.loadfromfile(l clob, l bfile, 12 dbms lob.getlength(l bfile)); 13 14 dbms lob.fileclosed(l bfile);
|
© 2006 - 2025 pmbk.ru. Генерация страницы: 0
При копировании материалов приветствуются ссылки. |