2016-01-26 2 views
3

У меня есть следующие функции:Почему CAST() не работает корректно в функциях MySQL?

CREATE FUNCTION test_rule (value TEXT, greater_than DECIMAL(10,4)) 
RETURNS BOOL 
RETURN greater_than IS NULL OR CAST(value AS DECIMAL(10,4)) > greater_than; 

Если я использую эту функцию с пустой строкой VOR value я получаю сообщение об ошибке:

SELECT test_rule('',10) 

(1366): Incorrect decimal value: '' for column '' at row -1

Но такое же выражение прекрасно работает без функции :

SELECT '' IS NULL OR CAST('' AS DECIMAL(10,4)) > 10 

0

Почему это?

Я использую версию MySQL 5.6.22

+0

Я пробовал оба выражения в Toad для MySQL (5.6.17), и они отлично работают. –

+0

Оба работают для меня, MySQL 5.6.28 – jonasfh

+0

Это очень странно. Интересно, имеет ли это какое-то отношение к [adminer] (www.adminer.org), которое я использовал для тестирования выше. –

ответ

1

Путь MySQL обрабатывает определенные преобразования данных также зависит от sql mode settings (см Строгий раздел Режим SQL, в частности) и CAST functions.

документация немного туманно о том, как эти ограничения применяются при оценке выражения, однако функция документации CAST упоминает, что

The SQL mode affects the result of conversion operations.

ОП говорилось в комментарии, что sql_mode установлен в STRICT_TRANS_TABLES, NO_ENGINE_SUBSTITUTION. STRICT_TRANS_TABLES означает, что строгий режим sql включен для транзакционных таблиц и, возможно, для операций с литыми.

'' (пустая строка) нельзя надлежащим образом наложить на число. Если строгий режим sql не включен, mysql генерирует предупреждение и оценивает '' со значением по умолчанию для данного числового типа - 0. Однако, если включен строгий режим sql, такое преобразование приводит к ошибке.

Вы можете изменить режим sql на глобальном уровне или уровне сеанса, установив соответствующее значение в переменную sql_mode.

Существует еще одно осложнение с сохраненными программами. Хранимые программы работают с SQL режимом настройки действует на compile time:

MySQL stores the sql_mode system variable setting in effect when a routine is created or altered, and always executes the routine with this setting in force, regardless of the current server SQL mode when the routine begins executing.

Если вы хотите различные хранимые процедуры для работы при различных настройках режима SQL, а затем

  1. отбросьте существующие сохраненные рутинные изменения
  2. sql до нужной настройки
  3. повторно создать сохраненную программу

Вы можете запросить настройку режима sql для любой хранимой процедуры, указав таблицу INFORMATION_SCHEMA.ROUTINES (столбец sql_mode).

Однако я бы рассмотрел возможность повторного написания кода в этом конкретном экземпляре, чтобы он проверял, равен ли параметр значения '' пустой строке, а не начинает играть с настройками режима sql. Проблема в том, что эти особые требования к настройке режима sql можно легко забыть или упустить из виду во время смены или миграции системы, а существующий код может начать бросать ошибки, и будет сложно перепрофилировать источник проблем.

+0

Спасибо. Я также попытался заставить мой код работать с пустыми строками '' ''first, но он все еще не прошел. Поэтому я сдался, и теперь у меня есть рабочее решение, где я создаю подпрограммы после 'SET SESSION sql_mode = '';'. Кажется, это трюк. –

+0

Затем убедитесь, что это правильно описано в коде и в руководстве по эксплуатации. Был случай, когда приложение было перенесено, но эти особенности не были отмечены. Было довольно болезненно отлаживать все хранимые процедуры и опознавать, из каких из них требуется другой режим настройки sql. – Shadow

Смежные вопросы