J'ai ce scénario, il semble que MySQL prenne la plus grande valeur décimale et essaie de convertir les autres valeurs en cela.
Le problème est que cette requête est générée par une bibliothèque externe, donc je n'ai pas de contrôle sur ce code, à ce niveau au moins. Avez-vous une idée de comment résoudre ce problème?
SELECT 20 AS x
UNION SELECT null
UNION SELECT 2.2;
+------+
| x |
+------+
| 9.9 | -- why from 20 to 9.9
| NULL |
| 2.2 |
+------+
résultat attendu
+------+
| x |
+------+
| 20 | -- or 20.0, doesn't matter really in my case
| NULL |
| 2.2 |
+------+
Ajoutant plus de contexte, j'utilise Entity Framework 6 avec une bibliothèque d'extensions http://entityframework-extensions.net/ pour enregistrer les modifications par lots, en particulier la méthode context.BulkSaveChanges () ;, cette bibliothèque crée des requêtes en utilisant "select union" .
SELECT 20 UNION SELECT null UNION SELECT 40 UNION SELECT 4.3;
fonctionne bienRéponses:
Cela ressemble à un bug pour moi et je peux confirmer ce comportement déroutant dans:
Si possible, vous pouvez convertir la valeur entière en double:
ou assurez-vous que vous avez d'abord la valeur double:
Observations supplémentaires après lecture des commentaires dans la réponse d'Evan Carroll
Ok, l'utilisation de valeurs int ne semble pas produire l'erreur.
ERREUR: Il semble que la sortie soit décimale (2,1)
L'erreur n'est pas isolée de l'interface de ligne de commande, elle existe également pour python2-mysql-1.3.12-1.fc27.x86_64:
Curieusement, l'erreur disparaît si null est déplacé en premier ou en dernier:
Si null est placé en premier, le type résultant est décimal (20,1). Si null est placé, le dernier type résultant est décimal (3,1)
L'erreur disparaît également si une autre jambe est ajoutée à l'union:
type décimal résultant (20,1)
l'ajout d'un autre null au milieu conserve l'erreur:
Mais l'ajout d'un null au début le corrige:
Comme prévu, la conversion de la première valeur en décimal (3,1) fonctionne.
Enfin, la conversion explicite en décimal (2,1) produit la même erreur mais avec un avertissement:
la source
SELECT CAST(20 AS DECIMAL) AS x UNION SELECT NULL UNION SELECT 2.2;
20
as020
. Le comportement est le même dans MariaDB 10.2 et dans MySQL 8.0 . Ressemble beaucoup à la longueur du littéral qui affecte le type de la colonne combinée. En tout cas, c'est définitivement un bug dans mon livre.Bogue MDEV-15999
Le bogue MDEV-15999 déposé par dbdemon l'a signalé. Il a depuis été corrigé dans 10.3.1.
Nature étrange de MySQL / MariaDB
Depuis les documents,
Dans ce cas, ils se réconcilient
decimal
etinteger
en promouvant l'entier à undecimal
qui ne peut pas le contenir. Je sais que c'est horrible, mais tout aussi horrible est ce comportement silencieux comme ça.Ce qui semble ouvrir la voie à ce problème.
la source
SELECT cast(20 as signed) UNION SELECT null UNION SELECT 2.2 ;
produit le même (9,9) mauvais résultat. Mais si nous utilisons "unisgned", tout se passe bien. Allez comprendre ...SELECT -20 UNION SELECT null UNION SELECT 2.2 ;
fonctionne correctement aussi, tout commeSELECT 20. UNION SELECT null UNION SELECT 2.2 ;
2.2
mais est trop étroit pour être conservé20
. Vous pouvez le voir en remplaçant la dernière clause select parCAST(2.2 AS DECIMAL(10,2))
, qui donne20.0
comme première ligne (en cours d'exécution impliciteCAST(20 AS DECIMAL(10,2))
).2.2
. Si vous essayez,select 20000 union select null union select 2.22
vous obtenez9999.99
, dans undecimal(6,2)
. C'est toujours un chiffre trop court pour contenir la valeurNULL
valeur au milieu, elle calcule la précision de 1 short.