Сравнение строк версий в базе данных
![топ 100 блогов](/media/images/default.jpg)
Сегодня попалась интересная задача: в таблице (пусть она называется soft) в базе есть строковый столбец "версия по" - version, в котором хранятся значения типа 7.0, 6.25, 8.4.1 и т.д. Задача была следующая - нужно было выбрать все строки, версия которых меньше либо равна заданной (реализовать нужно было на оракле). Первым делом я попробовал просто сравнивать строки:
SELECT * FROM soft WHERE version < ?;
Результат был почти тем, что требовалось: выбирались реально
нужные строки, до тех пор пока я не ввел 10.0 —оказалось, что
строка 7.3 больше (про сравнение строк можно почитать в
интернете).
После этого, я увидел первый очевидный вариант — разделить строку
точкой и отдельно сравнивать секции, но для этого нужно создавать
одну storage function для разбиения строки и вторую для сравнения.
Такой вариант я оставил как запасной — хотелось найти что-то проще,
желательно одним сравнением. После недолгого раздумия вариант
нашелся.
Решение проблемы
В оракле есть много встроенных функций, так же как и в любой другой субд. И эти функции можно использовать не по их прямому назначению — именно так я и поступил. Для сравнения я использовал функцию TO_DATE(). Итоговый вариант получился таким:
SELECT * FROM soft WHERE TO_DATE(version,'HH.MI.SS') < TO_DATE(?,'HH.MI.SS');
Мою задачу такая конструкция замечательно решила, т.к. в базе нет версий типа 25.61.61 — с такой конструкцией будет ошибка, т.к. часы не могут быть больше 23, а минуты и секунды больше 59. Но для таких случаев можно использовать другой формат: есть секунды после полуночи (SSSSS), день года (DDD). Сначала я думал, что мой формат не будет работать со строками типа 10 или 8.0, но оказалось что оракл сам подставляет нули в нужные секции.
Минусы данного подхода
- Ограничение, заданное форматом (часы не могут быть больше 23). По этому нужно заранее знать, в какую секцию отвести максимальный размер,
- Нужно заранее знать максимальное число секций (если ввести 6.2.1.15 в моем варианте будет ошибка).
|
</> |