02июн Большие объекты в СУРБД ORACLE. BLOB, CLOB

BLOB, CLOB – это внутренние большие объекты. Основные правила работы с этими объектами:

  • В основу работы с этими объектами положена транзакция, то есть любое изменение может быть зафиксировано или отменено.
  • Фактическое значение столбца LOB может храниться как часть строки таблицы, либо отдельно. Если длина столбца LOB больше 4000 байт, значение автоматически переносится в другое место.
  • Есть три состояния большого объекта: может быть пустым, может иметь значение null, может иметь какое-то конкретное значение. NULL – нет ни локатора ни значения у объекта. Пустой объект – имеется локатор, но он указывает на пустое место в базе данных.
  • Переменные и атрибуты объекта LOB могут играть роль промежуточного хранилища для локаторов LOB, указывающих на реальное значение в базе данных. То есть только столбец таблицы может содержать значение объекта LOB. Переменная Lob не представляет никакого фактического значения. Переменная содержит только локатор, соответствующий столбцу lob в базе данных.
  • У каждого LOB–столбца есть отдельный локатор и отдельное значение. То есть, если вы lob–столбцу присваиваете значение другого Lob-столбца, то этот столбец получает новое значение и новый локатор.
  • Непротиворечивость чтения внутренних больших объектов обеспечивается с помощью собственных механизмов многовариантности.

Давайте посмотрим на некоторые примеры. Предположим, мы имеем табличку

CREATE TABLE DEMO (ID       INTEGER,  THEBLOB  BLOB)

Для инициализации больших объектов существуют следующие встроенные функции:

  function EMPTY_CLOB return clob;
  function EMPTY_BLOB return blob;
Эти функции создают пустой локатор.
insert into demo values (1,empty_blob()));

Сделаем выборку

declare
the_id integer;
the_blob blob;
begin
SELECT   ID, THEBLOB into the_id, the_blob FROM DEMO where rownum=1;
end;

Так вот - в этом примере переменная the_blob получает локатор из столбца типа blob. Самого значения эта переменная не содержит, а содержит только указатель на местонахождение этого значения в базе данных.

А в следующем примере мы вставим новую строку в таблицу

declare
the_id integer;
the_blob blob;
begin
SELECT   ID, THEBLOB into the_id,the_blob FROM DEMO where rownum=1;
insert into demo values (2,the_blob);
end;

Теперь две строки имеют идентичное содержимое поля theblob, значения хранятся в разных местах, на которые указывают их отдельные локаторы.

Работа с внутренними большим объектами похожа на работу с другими типами данных, но подход ORACLE совершенно другой: доступ к ним реализуется через локаторы. Поэтому возникают некоторые проблемы в вопросе непротиворечивости чтения больших объектов.

Когда столбец внутреннего большого объекта меняет своё значение, предыдущее его значение не сохраняется в сегменте отката, как это происходит для других типов данных. Происходит все иначе: в пространстве, которое выделено для lob появляются дополнительные страницы, на которых и сохраняются предыдущие значения lob. Вывод: непротиворечивость чтения внутренних больших объектов достигается посредством их собственных механизмов многовариантности.

Обращаю ваше внимание, что все манипуляции с внутренними большими объектами производятся на основе транзакции. Когда транзакция, в которой прошла модификация Lob, зафиксирована, то дальнейшее использование соответствующего локатора становится некорректным. Локатор необходимо выбрать снова.

Давайте, углубимся в детали и посмотрим пример.

Когда локатор большого объекта выбрать в переменную lob, то это локатор становится согласованным по чтению. То есть, значение lob будет всегда таким, каким оно было на момент выбора локатора. Другими словами, когда локатор lob помещается в переменную, он получает СОБСТВЕННОЕ ПРЕДСТАВЛЕНИЕ значения lob.

В pl/sql возможны два способа обновления столбца внутреннего большого объекта: оператором update и пакетом dbms_lob. При использовании пакета dbms_lob, обновляемый локатор позволяет видеть результаты обновления. Чего нельзя сказать об операторе update. Чтобы увидеть новое значение, нужно по-новому выбрать обновленный столбец или использовать update с предложением returning .

А теперь пример с комментариями:

SQL> declare
  2  the_id integer;
  3  the_blob1 blob;
  4  the_blob2 blob;
  5  begin
  6  -- выбираем локатор согласованный по чтению
  7  SELECT   ID, THEBLOB into the_id,the_blob1 FROM DEMO where id=1;
  8  -- создадим еще один новый локатор согласованный по чтению
  9  the_blob2:=the_blob1;
 10  -- после следующего оператора записи с id=1 и id=21 будут иметь одинаковое значение столбца blob.
 11  update demo set theblob=the_blob2 where id=21;
 12  --после следующего оператора запись с id=1 буде иметь локатор чистый для столбца lob 
 13  update demo set theblob=empty_blob() where id=1;
 14  -- но мы еще можем видеть старое значение этого столбца. Поэтому создадим новую запись с эти значением
 15  insert into demo values ( 33,the_blob1) returning theblob into the_blob2;
 16  -- после этого оператора получем согласованный по чтению локатор в the_blob2
 17  
 18  delete FROM DEMO where id=1;
 19  --удаляем запись с  id=1, но все равно мы ещё можем получить значение столбца lob
 20  insert into demo values ( 44,the_blob1);
 21  commit;
 22  end;
 23  /

PL/SQL procedure successfully completed.

В этом примере наглядно показано, что при манипуляциях с большими внутренними объектами не следует читать или записывать их непосредственно, все манипуляции нужно реализовывать через локаторы.

Работать с внешними большими объектами можно с помощью пакета dbms_lob (см. нашу соответствующую статью).

Комментарии (0)



Новый комментарий

Имя
Электронная почта
 
Ваш сайт
Защита от спама: укажите сумму 5 + 2
   
 

Поиск по блогам



Подпишись на RSS:

RSS - Подписаться на блог



Читателям


Рекомендую к прочтению





Разделы блога



Последние публикации



Последние коментарии