Limite de taille dans un WHERE

Avatar du membre
Administrateur PHPfrance
Administrateur PHPfrance | 13231 Messages

08 janv. 2007, 17:41

Bonjour à tous,

Au cours de mon travail, je suis tombé sur un bug que je juge bizarre.

J'ai une table 'entree' qui contient, comme clé primaire, un champ 'id_entree' définie comme telle :

Code : Tout sélectionner

`id_entree` bigint(20) unsigned NOT NULL default '0'
(Je met toujours un default ... même si c'est inutile ;) )

Dans cette colonne, à chaque insertion, je génère un identifiant aléatoire qui peut varier entre 17 et 20 digits.

Le traitement que j'applique dessus commence par un

Code : Tout sélectionner

SELECT * FROM entree LIMIT 0, 50000
qui fonctionne parfaitement, qui me remonte toutes les valeurs, y compris l'id_entree.
Or, après ce traitement, j'ai un DELETE unitaire de cette forme

Code : Tout sélectionner

DELETE FROM entree WHERE id_entree = '....'
Et, ici, je me suis rendu compte que si j'encadre mon id par des ', tous id > 19 digits commençant par '64...' n'est pas supprimé. Je n'arrive pas à le sélectionner non plus :-k

Dès que j'enlève les ', plus de soucis, SELECT et DELETE fonctionnent parfaitement :shock:

Je me demandais donc si quelqu'un pouvait m'expliquer pourquoi :?:

PS : pour le bug, pas de soucis, j'ai réduit la génération aléatoire entre 15 et 18 digit, ce qui est encore quelques centaines de fois supérieure à ce qui peut se trouver simultanément dans la table ...
Connaître son ignorance est la meilleure part de la connaissance
Pour un code lisible : n'hésitez pas à sauter des lignes et indenter

twitter - site perso - Github - Zend Certified Engineer

Administrateur PHPfrance
Administrateur PHPfrance | 3088 Messages

08 janv. 2007, 17:47

C'est un bug intéressant, si tu ne trouves pas la réponse ça vaut peut-être le coup de le soumettre. En attendant, je le note pour plus tard quand on me demandera pourquoi il faut pas mettre de guillemets autour des nombres :lol:

Petit nouveau ! | 5 Messages

08 janv. 2007, 18:31

je suppose que à partir du moment ou tu entoure ton nombre par des quotes, tu déclenche une conversion implicite en un type inférieur à bigint, d'où arrondi au plafond... (au lieu d'une erreur qui serait plus logique)

à propos de logique, y'a une raison pour laquelle tu entoure les chiffres de quote? déjà... default '0' au lieu de default 0 (qui sert à rien non plus mais bon) :lol:

Avatar du membre
Administrateur PHPfrance
Administrateur PHPfrance | 13231 Messages

08 janv. 2007, 18:46

Il me semble que du point de vue de la norme SQL ANSI, il est possible d'entourer un entier par des '.
Dans un point de vue de compatibilité ascendante (il est possible que ce chiffre soit remplacé par un UUID) j'ai préféré écrire les requêtes comme ça pour pas avoir à me le retaper ensuite.

Sinon, pour le "default '0'", comme je l'ai indiqué, je donne TOUJOURS une valeur par défaut. L'expérience m'a appris que la base d'un bug, c'est la suffisance du développeur. La confiance absolue en ce qu'il a fait. Et cette expérience ne m'a jamais porté préjudice.
Dans ce cas, je sais que si, pour une raison x ou y (un autre développeur qui change la primary key ou le NOT NULL par exemple), je maitrise encore ce qui se passe dans cette colonne.

Et puis, un point pour moi, le "default '0'", c'est de cette manière que le génère PMA ;)
Connaître son ignorance est la meilleure part de la connaissance
Pour un code lisible : n'hésitez pas à sauter des lignes et indenter

twitter - site perso - Github - Zend Certified Engineer

ViPHP
ViPHP | 1996 Messages

10 janv. 2007, 23:41

Bonsoir, je ne suis pas spécialiste mais je pense avoir eu le même problème. En y regardant de plus près, j'ai eu l'impression que, si je reprends ton exemple :

Code : Tout sélectionner

DELETE FROM entree WHERE id_entree = '....'
le moteur exécutait de la sorte :

Code : Tout sélectionner

DELETE FROM entree WHERE id_entree = "'"...."'"
Une sorte de protection, ceci me changeait tout... Néanmoins, be careful, je débute...
It is nice to be important but it is more important to be nice
http://www.aureuswebfactory.fr

Mammouth du PHP | 1885 Messages

11 janv. 2007, 03:12

As-tu essayé en retirant les guillemets simples? Peut-être qu'il convertir ta chaine en INTEGER et non en bigint().
La programmation est l'expression de la poésie d'un programmeur
Génération PHP

ViPHP
ViPHP | 1380 Messages

11 janv. 2007, 09:25

BIGINT et un type de colonne sur 8 octets. En conséquence, la valeur max est de (2^64)-1 soit 18446744073709551615

Avec un entier non signé de 20 chiffres commençant par 64, tu dépasses la valeur maximum pour ce type de colonne. Lors dun INSERT d'une valeur trop élévée, MySQL ne se plaindra pas, il te mettra la valeur max soit 18446744073709551615.

Code : Tout sélectionner

INSERT INTO b (col1) VALUES (18446744073709551616) INSERT INTO b (col1) VALUES (99999999999999999999)
Produiront tous deux un insert de la valeur entière 18446744073709551615

Si tu dois stocker des nombres plus élévés, il faudra te tourner vers les types chaîne.
ripat

ViPHP
ViPHP | 1961 Messages

11 janv. 2007, 09:49

Bonjour,

Pourquoi ne pas stocker la valeur dans une colonne de type DECIMAL (20, 0) UNSIGNED ?

Une info assez parlante.
Deux choses sont infinies, l'Univers et la sottise humaine!!
Mais je ne suis pas sur de ce que j'affirme au sujet de l'Univers.

A. Einstein

Avatar du membre
Administrateur PHPfrance
Administrateur PHPfrance | 13231 Messages

11 janv. 2007, 10:11

@Xenon_54 : Effectivement, c'est la base de mon soucis. Je ne comprend pas pourquoi les guillemets déclenchent une erreur quand j'ai un entier > 6 400 000 000 000 000 000 (19 digits)

@Ripat : les nombres commencent à déconner bien avant cette limite puisqu'avec 19 digits commençant par "64...", l'insert se passe bien, j'ai bien la bonne valeur en base de données, mais tout select avec des ' autour de la valeur ne retourne rien :-k

@Ajoloca : Effectivement, je garde cette solution sous le coude. Mais j'ai déjà diminué la taille maximale et j'ai finit le développement de ce projet. J'en toucherais mot à mon chef pour la prochaine conception sur ce projet ;)

En tout cas, merci à vous pour vos réponses et vos conseils :pouce:
Connaître son ignorance est la meilleure part de la connaissance
Pour un code lisible : n'hésitez pas à sauter des lignes et indenter

twitter - site perso - Github - Zend Certified Engineer