Как стать автором
Обновить

Полноценный 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.: В принципе, так можно любую шаблонную замену организовать. Странно, что не нашел подобные примеры.
Теги:
Хабы:
Данная статья не подлежит комментированию, поскольку её автор ещё не является полноправным участником сообщества. Вы сможете связаться с автором только после того, как он получит приглашение от кого-либо из участников сообщества. До этого момента его username будет скрыт псевдонимом.