У меня есть этот сценарий, похоже, что MySQL принимает наибольшее десятичное значение и пытается привести другие значения к этому.
Проблема в том, что этот запрос генерируется внешней библиотекой, поэтому я не могу контролировать этот код, по крайней мере, на этом уровне. У вас есть идея, как это исправить?
SELECT 20 AS x
UNION SELECT null
UNION SELECT 2.2;
+------+
| x |
+------+
| 9.9 | -- why from 20 to 9.9
| NULL |
| 2.2 |
+------+
ожидаемый результат
+------+
| x |
+------+
| 20 | -- or 20.0, doesn't matter really in my case
| NULL |
| 2.2 |
+------+
Добавляя больше контекста, я использую Entity Framework 6 с библиотекой расширений http://entityframework-extensions.net/ для сохранения изменений в пакетах, в частности, метода context.BulkSaveChanges (); эта библиотека создает запросы с использованием «select union» ,
SELECT 20 UNION SELECT null UNION SELECT 40 UNION SELECT 4.3;
работает отличноОтветы:
Похоже, ошибка для меня, и я могу подтвердить это загадочное поведение в:
Если возможно, вы можете привести целое число к двойному:
или сначала убедитесь, что у вас есть двойное значение:
Дальнейшие наблюдения после прочтения комментариев в ответе Эвана Кэрролла
Хорошо, использование значений int не приводит к ошибке.
ОШИБКА: похоже, что вывод десятичный (2,1)
Ошибка не изолирована от интерфейса командной строки, она также существует для python2-mysql-1.3.12-1.fc27.x86_64:
Как ни странно, ошибка исчезает, если нулевое значение перемещается первым или последним:
Если ноль помещен первым, результирующий тип является десятичным (20,1). Если ноль помещен, последний получающийся тип является десятичным (3,1)
Ошибка также исчезает, если в объединение добавляется еще одна ветка:
результирующий тип десятичный (20,1)
добавление еще одного нуля в середину сохраняет ошибку:
Но добавление нуля в начале исправляет это:
Как и ожидалось, приведение первого значения к десятичному (3,1) работает.
Наконец, явное приведение к десятичному (2,1) приводит к той же ошибке, но с предупреждением:
источник
SELECT CAST(20 AS DECIMAL) AS x UNION SELECT NULL UNION SELECT 2.2;
20
как020
. Поведение одинаково в MariaDB 10.2 и в MySQL 8.0 . Очень похоже, что длина литерала влияет на тип комбинированного столбца. В любом случае, это определенно ошибка в моей книге.Ошибка MDEV-15999
Ошибка MDEV-15999, поданная dbdemon, сообщила об этом. Это было исправлено в 10.3.1.
Странная природа MySQL / MariaDB
Из документов,
В этом случае они примиряются
decimal
иinteger
путем преобразования целого числа в объект,decimal
который не может его содержать. Я знаю, что это ужасно, но в равной степени ужасно и то, что это так тихо ведет себя.Который, кажется, прокладывает путь для этой проблемы.
источник
SELECT cast(20 as signed) UNION SELECT null UNION SELECT 2.2 ;
дает тот же (9,9) неправильный результат. Но если мы используем «без опрыскивания» там все идет хорошо. ПойдиSELECT -20 UNION SELECT null UNION SELECT 2.2 ;
работает правильно, как иSELECT 20. UNION SELECT null UNION SELECT 2.2 ;
2.2
но слишком узок для хранения20
. Вы можете увидеть это, изменив последнее предложение select наCAST(2.2 AS DECIMAL(10,2))
, которое дает20.0
в качестве первой строки (неявно работающийCAST(20 AS DECIMAL(10,2))
).2.2
. Если вы попробуете,select 20000 union select null union select 2.22
вы получите9999.99
, вdecimal(6,2)
. Это всегда одна цифра, слишком короткая, чтобы держать значениеNULL
значение в середине, он вычислит точность 1 короткое.