MySQL и тайпкастинг
Рубрика: MySQL | 17 September 2007, 15:36 |
Vadim Voituk
Так как MySQL производит автоматическую конверсию типов в тектсе SQL-запросов, расскажу немного о том, как можно этой конверсией управлять.
Предположим у нас есть 2 одинаковых даты, но в разных форматах:
’2007-07-01′ и ’20070701′.
Необходимо средствами БД (например в SQL-запросе) ставнить их на равенство:
Очевидно, что простым сравнением тут не обойдешься:
SELECT '2007-07-01' = '20070701'
#= 0
В данном случае MySQL считает оба значения строками и сравнивает их лексикографически. В итоге получаем 0.
Для указания того, что мы работаем не со строками а с датами, необходимо выполнить конверсию типов (или тайпкастинг).
Делается это с помощью функции CAST():
SELECT CAST('2007-07-01' AS DATE) = CAST('20070701' AS DATE);
#= 1
В случае когда MySQL “знает” тип одного из операндов, второй приводится к этому типу автоматически:
SELECT '2007-07-01' = CAST('20070701' AS DATE);
#= 1
Аналогичная ситуация наблюдается если слева будет указано поле таблицы – в таком случае второй операнд будет приводиться к типу этого поля.
Например:
SELECT myDatField FROM myTable LIMIT 1\G
myDatField=2007-07-01
SELECT myDatField=20070101 AS res FROM myTable LIMIT 1\G
res=1
Но такое поведение наблюдается только в случае, если не происходит автоматическа конвертация из CHAR в INT и наоборот.
Пример:
SELECT '20070701'=CAST('2007-07-01' AS DATE);
#=0
# но в то же время
SELECT '2007-07-01'=CAST('20070701' AS DATE)
#=1
Или же ещё один пример (IMHO более презентабельный):
SELECT CAST('20070101' AS DATE)=CAST('20070101' AS UNSIGNED INTEGER);
#= 0
# Тут вопросов быть не должно, т.к. слева получаем что-то вроде "2007-01-01"
# но при этом
SELECT CAST('10' AS SIGNED INTEGER)=CAST('10' AS CHAR);
#= 1
# тут уже имеем автоматическую CHAR<->INT конверсию
Стоит добавить что в результате конверсии типов (как явной так и неявной) возможно “выпадание” индекса из сценария запроса, что приводит к существенному понижению производительности.
Tweet
Занимательно.
Реально приходится обращать внимание на такие тонкости?
Про то, что в результате тайпкастинга из запроса выпадает индекс, уже и говорить неприлично – в сети об этом написано-перенаписано (да и по explain-у можно увидеть).
А вот в случае когда приходится сравнивать данные в разных форматах (даты), на это стоит ображать внимаение, т.к. не всегда параметрическое значение интерпретируется нужным образом. В принципе такое бывает нечасто, но бывает.