Pull to refresh

Полноценный upper (или lower) в SQLite при работе с unicode

Так случилось, что столкнулся с SQLite и, как и многие, уперся в непонимание им нашего родного юникода. Не работает UPPER, LOWER и LIKE, а без них иногда никуда.

Есть: cmd, sqlite3.exe и некая база данных.

Надо: Поменять регистр в тексте.

Ограничения: Кроме cmd и sqlite3.exe больше ничего нет. Создание и подключение функций тоже недоступно.

После примерно часа размышлений (на доселе незнакомом диалекте SQL) для upper родилась такая конструкция:

select
  t.test_text
, upper(
    (
        WITH RECURSIVE
        under_name(test_text, char, level) as 
            (select t.test_text, '', 0
            union
            select test_text, coalesce(lu.u,substr(test_text,level,1)), under_name.level+1
            from under_name
            left join (
                select 'А' as u, 'а' as l union select 'Б' as u, 'б' as l union select 'В' as u, 'в' as l union select 'Г' as u, 'г' as l union select 'Д' as u, 'д' as l union select 'Е' as u, 'е' as l union select 'Ё' as u, 'ё' as l union select 'Ж' as u, 'ж' as l union select 'З' as u, 'з' as l union select 'И' as u, 'и' as l union select 'Й' as u, 'й' as l union select 'К' as u, 'к' as l union select 'Л' as u, 'л' as l union select 'М' as u, 'м' as l union select 'Н' as u, 'н' as l union select 'О' as u, 'о' as l union select 'П' as u, 'п' as l union select 'Р' as u, 'р' as l union select 'С' as u, 'с' as l union select 'Т' as u, 'т' as l union select 'У' as u, 'у' as l union select 'Ф' as u, 'ф' as l union select 'Х' as u, 'х' as l union select 'Ц' as u, 'ц' as l union select 'Ч' as u, 'ч' as l union select 'Ш' as u, 'ш' as l union select 'Щ' as u, 'щ' as l union select 'Ь' as u, 'ь' as l union select 'Ы' as u, 'ы' as l union select 'Ъ' as u, 'ъ' as l union select 'Э' as u, 'э' as l union select 'Ю' as u, 'ю' as l union select 'Я' as u, 'я' as l
            ) lu on substr(test_text,level,1)=lu.l
            where level <= length(test_text)
        )
        select group_concat(char,'') from under_name
    )
) upper_text
from
(select 'Съешь ещё этих  мягких французских булок, да выпей же чаю. Test.' test_text) t

Т.е. substr'ом в цикле разбиваем текст на буквы, меняем по шаблону и склеиваем результат обратно в строчку через group_concat.

Может быть немного громоздко, но это работает. И довольно шустро. Для lower или like решается аналогично.

P.S.: В принципе, так можно любую шаблонную замену организовать. Странно, что не нашел подобные примеры.
Tags:
Hubs:
You can’t comment this publication because its author is not yet a full member of the community. You will be able to contact the author only after he or she has been invited by someone in the community. Until then, author’s username will be hidden by an alias.