Проблема с объединением целых чисел с потоком (десятичная)

У меня есть этот сценарий, похоже, что 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 /, чтобы сохранить изменения в партиях, в частности контекст метода.BulkSaveChanges () ;, эта библиотека создает запросы, используя «select union».

10 голосов | спросил ngcbassman 24 AMpTue, 24 Apr 2018 08:06:40 +030006Tuesday 2018, 08:06:40

2 ответа


8

Похож на ошибку, и я могу подтвердить это недоумение:

10.2.14-MariaDB

Если возможно, вы можете применить целочисленное значение к double:

SELECT cast(20 as double) UNION SELECT null UNION SELECT 2.2;

или убедитесь, что у вас есть двойное значение:

SELECT 2.2 UNION SELECT null UNION SELECT 22;

Дальнейшие наблюдения после прочтения комментариев в ответе @ Эвана Кэрролла

select 20 union select null union select 2;
+------+
| 20   |
+------+
|   20 |
| NULL |
|    2 |
+------+

Хорошо, использование значений int не приводит к ошибке.

select 20 union select null union select 9.0;
+------+
| 20   |
+------+
| 9.9  |
| NULL |
| 9.0  |
+------+

ОШИБКА: Кажется, что вывод десятичен (2,1)

create table tmp as select * from (select 20 as x 
                                   union 
                                   select null 
                                   union 
                                   select 9.0) as t

describe tmp;
+-------+--------------+------+-----+---------+-------+
| Field | Type         | Null | Key | Default | Extra |
+-------+--------------+------+-----+---------+-------+
| x     | decimal(2,1) | YES  |     | NULL    |       |
+-------+--------------+------+-----+---------+-------+

Ошибка не изолирована от интерфейса командной строки, она существует и для python2-mysql-1.3.12-1.fc27.x86_64:

>>> import MySQLdb
>>> db = MySQLdb.connect(host="localhost", user="*****", passwd="*****", db="test") 
>>> cur = db.cursor()
>>> cur.execute("SELECT 20 union select null union select 2.2")
3L
>>> for row in cur.fetchall() :
...     print row
... 
(Decimal('9.9'),)
(None,)
(Decimal('2.2'),)

Как ни странно, ошибка исчезает, если нуль перемещается первым или последним:

select null union select 20 union select 9.0;
select 20 union select 9.0 union select null;

+------+
| NULL |
+------+
| NULL |
| 20.0 |
| 9.0  |
+------+

Если сначала поместить нуль, итоговый тип будет десятичным (20,1). Если null помещен, последний итоговый тип является десятичным (3,1)

Ошибка также исчезает, если в объединение добавляется другая нога:

select 20 union select 6 union select null union select 9.0;
+------+
| 20   |
+------+
| 20.0 |
| 6.0  |
| NULL |
| 9.0  |
+------+

итоговый тип десятичного числа (20,1)

добавление другого нуля в середину сохраняет ошибку:

select 20 union select null union select null union select 9.0;
+------+
| 20   |
+------+
| 9.9  |
| NULL |
| 9.0  |
+------+

Но добавление нулевого значения в начале исправляет его:

select null union select 20 union select null union select null union select 9.0;
+------+
| NULL |
+------+
| NULL |
| 20.0 |
| 9.0  |
+------+

Как и ожидалось, срабатывает первое значение десятичного числа (3,1).

Наконец, явно приведение к десятичной (2,1) дает ту же ошибку, но с предупреждением:

select cast(20 as decimal(2,1));
+--------------------------+
| cast(20 as decimal(2,1)) |
+--------------------------+
| 9.9                      |
+--------------------------+
1 row in set, 1 warning (0.00 sec)
ответил Lennart 24 AMpTue, 24 Apr 2018 09:11:26 +030011Tuesday 2018, 09:11:26
5

Ошибка MDEV-15999

Ошибка MDEV-15999 , поданная dbdemon сообщил об этом. Это было исправлено в 10.3.1.

Странный характер MySQL /MariaDB

Из документов,

  

Имена столбцов из первого оператора SELECT используются как имена столбцов для возвращаемых результатов. Выбранные столбцы, перечисленные в соответствующих позициях каждого оператора SELECT, должны иметь одинаковый тип данных. (Например, первый столбец, выбранный первым оператором, должен иметь тот же тип, что и первый столбец, выбранный другими операторами.)

     

Если типы данных соответствующих столбцов SELECT не совпадают, типы и длины столбцов в UNION учитывают значения, полученные всеми SELECT заявления.

В этом случае они сверяют decimal и integer, продвигая целое число до decimal, которое не может содержать его. Я знаю, что это ужасно, но так же ужасно, что это так тихо ведет себя.

SELECT CAST(20 AS decimal(2,1));
+--------------------------+
| CAST(20 AS decimal(2,1)) |
+--------------------------+
|                      9.9 |
+--------------------------+

Что, похоже, проложит путь для этой проблемы.

ответил Evan Carroll 24 AMpTue, 24 Apr 2018 09:38:33 +030038Tuesday 2018, 09:38:33

Похожие вопросы

Популярные теги

security × 330linux × 316macos × 2827 × 268performance × 244command-line × 241sql-server × 235joomla-3.x × 222java × 189c++ × 186windows × 180cisco × 168bash × 158c# × 142gmail × 139arduino-uno × 139javascript × 134ssh × 133seo × 132mysql × 132