Mam taki scenariusz, wygląda na to, że MySQL pobiera największą wartość dziesiętną i próbuje dorzucić inne wartości.
Problem polega na tym, że to zapytanie jest generowane przez bibliotekę zewnętrzną, więc nie mam kontroli nad tym kodem, przynajmniej na tym poziomie. Czy masz jakiś pomysł, jak to naprawić?
SELECT 20 AS x
UNION SELECT null
UNION SELECT 2.2;
+------+
| x |
+------+
| 9.9 | -- why from 20 to 9.9
| NULL |
| 2.2 |
+------+
Spodziewany wynik
+------+
| x |
+------+
| 20 | -- or 20.0, doesn't matter really in my case
| NULL |
| 2.2 |
+------+
Dodając więcej kontekstu, używam Entity Framework 6 z biblioteką rozszerzeń http://entityframework-extensions.net/ do zapisywania zmian w partiach, a konkretnie metody kontekstu.BulkSaveChanges () ;, ta biblioteka tworzy zapytania używając „select union” .
SELECT 20 UNION SELECT null UNION SELECT 40 UNION SELECT 4.3;
działa dobrzeOdpowiedzi:
Wygląda mi to na błąd i mogę potwierdzić to zagadkowe zachowanie w:
Jeśli to możliwe, możesz rzucić liczbę całkowitą na podwójną:
lub upewnij się, że najpierw masz podwójną wartość:
Dalsze spostrzeżenia po przeczytaniu komentarzy w odpowiedzi @Evan Carroll
Ok, użycie wartości int nie wydaje się powodować błędu.
BŁĄD: Wydaje się, że dane wyjściowe są dziesiętne (2,1)
Błąd nie jest izolowany dla interfejsu wiersza poleceń, istnieje również dla python2-mysql-1.3.12-1.fc27.x86_64:
Co dziwne, błąd znika, jeśli null zostanie przesunięty pierwszy lub ostatni:
Jeśli null zostanie umieszczony jako pierwszy, wynikowy typ jest dziesiętny (20,1). Jeśli zostanie wstawiona wartość null, ostatni wynikowy typ jest dziesiętny (3,1)
Błąd znika również, jeśli do związku zostanie dodana kolejna noga:
wynikowy typ dziesiętny (20,1)
dodanie kolejnego pustego miejsca w środku zachowuje błąd:
Ale dodanie null na początku naprawia to:
Zgodnie z oczekiwaniami działa rzutowanie pierwszej wartości na dziesiętną (3,1).
Wreszcie jawne rzutowanie na dziesiętne (2,1) powoduje ten sam błąd, ale z ostrzeżeniem:
źródło
SELECT CAST(20 AS DECIMAL) AS x UNION SELECT NULL UNION SELECT 2.2;
20
as020
. Zachowanie jest takie samo w MariaDB 10.2 i MySQL 8.0 . Wygląda bardzo podobnie, jak długość literału wpływa na typ połączonej kolumny. W każdym razie jest to zdecydowanie błąd w mojej książce.Błąd MDEV-15999
Zgłoszono ten błąd MDEV-15999 zgłoszony przez dbdemon . Od tego czasu został naprawiony w 10.3.1.
Dziwna natura MySQL / MariaDB
Z dokumentów
W tym przypadku uzgadniają
decimal
iinteger
promując liczbę całkowitą do wartości,decimal
która nie może jej zawierać. Wiem, że to okropne, ale równie okropne jest to, że tak cicho się zachowuje.Co wydaje się torować drogę dla tego problemu.
źródło
SELECT cast(20 as signed) UNION SELECT null UNION SELECT 2.2 ;
daje ten sam (9.9) zły wynik. Ale jeśli użyjemy „nieprzygotowanego”, wszystko pójdzie dobrze. Idź rysunek ...SELECT -20 UNION SELECT null UNION SELECT 2.2 ;
działa również poprawnie, podobnie jakSELECT 20. UNION SELECT null UNION SELECT 2.2 ;
2.2
ale jest zbyt wąski, aby go pomieścić20
. Można to zobaczyć, zmieniając ostatnią klauzulę select naCAST(2.2 AS DECIMAL(10,2))
, która daje20.0
jako pierwszy wiersz (domyślnie uruchomionyCAST(20 AS DECIMAL(10,2))
).2.2
. Jeśli spróbujeszselect 20000 union select null union select 2.22
dostać9999.99
, wdecimal(6,2)
. Jest zawsze o jedną cyfrę za krótka, aby pomieścić wartośćNULL
wartość na środku, oblicza precyzję 1 krótką.