Программирование >>  Oracle 

1 ... 153 154 155 [ 156 ] 157 158 159 ... 469


Глава 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);



1 ... 153 154 155 [ 156 ] 157 158 159 ... 469

© 2006 - 2025 pmbk.ru. Генерация страницы: 0
При копировании материалов приветствуются ссылки.
Яндекс.Метрика