Записки жертвы высоких технологий

    Здравствуйте! Мой блог посвящен в большей своей части моей профессиональной деятельности на поприще использования технологий ORACLE для разработки баз данных OLTP и OLAP хранилищ данных. В заметках я периодически размещаю разнообразные SQL, PL/SQL и Java скрипты написанные мной и не только мной, ссылки на интересные источники в сети либо другую полезную информацию, которая каким либо образом касается моей работы с замечательными продуктами компании ORACLE.
    Вы можете связаться со мной по контактному емейлу, если у вас есть какие-либо вопросы, связанные с разработкой баз данных на основе продуктов ORACLE, буду рад помочь вам, если это будет в моих силах.

12 июл. 2019 г.

Работа со значениями типа LONG длиной до 4000 байт без использования PL/SQL

Как известно, со значениями типа LONG работа в ORACLE не особенно приветствуется. Точнее не приветствуется до той степени, что поддержка типа LONG в SQL практически отсутствует и значения для обработки могут быть обработаны только средствами клиентского ПО либо средствами PL/SQL.
Тем не менее, существует достаточно известный способ, с помощью которого все же можно воспользоваться значениями типа LONG непосредственно в SQL. Единственное ограничение этого способа - максимальная длина значений типа LONG должна быть не больше максимальной разрешенной длины SQL типа VARCHAR2, т.е. не более чем 4000 байт.
Приводимый мной пример в принципе дает понимание этого метода. Мне нужно было достать из системного словаря информацию о максимально возможных значениях ключа партиционирования таблицы по каждой из имеющихся партиций.

select partition_name, high_value from user_tab_partitions where table_name = '<ИМЯ_ТАБЛИЦЫ>'


Запрос крайне прост, но в SQL невозможно без определенных процедур воспользоваться значением HIGH_VALUE, так как оно имеет тип LONG. По "классике" нужно написать PL/SQL процедуру, которая преобразует тип LONG в VARCHAR2 по ROWID строки, но этот метод достаточно трудоемок и приводит к тому, что запрос при выполнении начинает переключать контекст выполнения с SQL в PL/SQL и обратно, что накладно.

Альтернативный метод таков:

with q_xml as (select dbms_xmlgen.getxmltype('select partition_name, high_value from user_tab_partitions where table_name = ''<ИМЯ_ТАБЛИЦЫ>''') xml from dual)
select
    z.*
from
    q_xml,
    xmltable('/ROWSET/ROW' passing q_xml.xml columns partition_name varchar2(64) path 'PARTITION_NAME', high_value varchar2(1024) path 'HIGH_VALUE' ) z

Запрос, конечно, становится более сложным, чем исходный, но тем не менее отпадает потребность в написании PL/SQL функции.