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

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

24 дек. 2013 г.

Аббревиатуры из названий

В нашей серьезной организации все отделы должны иметь аббревиатурные названия, непонятные стороннему человеку (сиречь потенциальному шпиёну). Должны, но не обязаны. Поэтому у нескольких отделов таких аббревиатур нет. При переносе справочника на другой сервер пришлось озадачиться автоматической генерацией аббревиатур из названий отделов. Разумеется, помогли регулярные выражения. Приведенный ниже пример формирует аббревиатуры из названий отделов, выбрасывая союз " и " и тире из названий, как ненужные.

select
    -- переводим строку в верхний регистр
    upper(
        -- удаляем пробелы, схлопывая оставшиеся буквы в аббревиатуру
        regexp_replace(
            -- удаляем сформированные последовательности из исходной строки
            regexp_replace(
                rs_name,
                -- формируем шаблон типа (<динамическая последовательность1> | <динамическая последовательность2>[|...] | <фиксированная последовательность1>[|...])
                '('||
                -- убираем размноженные перечислители, заменяя их на одиночные
                regexp_replace(
                    -- убираем лишний перечислитель из начала предложения
                    regexp_replace(
                        -- убираем начальные буквы из каждого слова в предложении, заменяя их на перечислители "|"
                        regexp_replace(
                            rs_name,
                            '(^|\s)\w',
                            '|'
                        ),
                        '^[|]+',
                        null
                    ),
                    '[|][|]+',
                    '|'
                )||
                -- добавляем блок фиксированных последовательностей " и "
                '|\s+и\s+|\s*-]s*)',
                null
            ),
            '\s',
            null
        )
    )
from
    (
        select regexp_replace(rs_name, '(Радио|радио)(навигационн|локационн|астрономическ|вещательн)''\1 \2') rs_name, rs_abbr from DIC_RADIOSERVICE t
    ) t

Приведенный алгоритм также учитывает некоторые общепринятые сокращения отдельных слов, таких как: радионавигационная - РН, а не Р, радиолокационная - РЛ, а не Р, радиоастрономическая - РА, но не Р, радиовещательная - РВ, но не Р. Для этого в исходное название между "Радио" и остатком названия службы вставляется пробел, чтобы в результате получилось бы правильное сокращение.

5 дек. 2013 г.

Очередной "шедевр" формирования результирующего набора из строки с разделителями

Ковырялся в коде старого приложения на предмет его анализа и наткнулся на "мощный алгорим", формирующий результирующий набор строк из строки с разделителями, например из такой: "1,2,3,4,5,6,7,8,9,10,a,b,c,d,e,f":

with src as (SELECT ','||'1,2,3,4,5,6,7,8,9,10,a,b,c,d,e,f'||',' str from dual)
select 
level lvl
trim(substr(Src.Str,instr(Src.Str,',',1,level)+chunk, 
instr (Src.Str,',',1,level+1)-instr(Src.Str,',',1,level)-1)) op_num
from 
src
connect by 
rownum<=(length(Src.Str)-length(replace(Src.Str,',')))-1

Код, конечно, работает, но:
1. В этом коде реально неудобно разбираться
2. Этот код не учитывает наличие пробелов или каких-либо "лишних символов" между разделителями, а по идее - должен

Варианты альтернативного исполнения:

1. Конвейерная (pipelined) функция
2. Функция, возвращающая массив
3. Regexp'ы (пример есть у меня в разделе "Сравнение строк по сигнатурам".

PS. Я бы вот так вот написал:

with params as (select '\s*([^,]+)\s*(,|$)' pattern,'1,2,3,4,5,6,7,   8,  9    ,10,,12, a, bb, ccc , dddd' string from dual)
select 
regexp_substr(params.string, params.pattern, 1level'i',1chunk 
from 
params 
connect by
regexp_substr(params.string, params.pattern, 1level'i',1is not null