Version complète: sur le forum Webmaster Hub : valeur minimum non existante
Webmaster Hub > Création et exploitation de Sites Internet > Les langages du Net > SQL
xorax
bonjour,

j'aimerais savoir comment inséré un enregistrement dont une colonne aurais la plus petite valeur non utilisé.

par exemple jai un auto_increment sur le chant id et j'ai cette table :
CODE
+----+---------+
| id | name    |
+----+---------+
|  1 | dog     |
|  2 | cat     |
|  3 | penguin |
|  4 | lax     |
|  5 | whale   |
|  6 | ostrich |
+----+---------+


j'éfface un enregistremnt au hazard, et j'ai ça :
CODE
+----+---------+
| id | name    |
+----+---------+
|  1 | dog     |
|  2 | cat     |
|  4 | lax     |
|  5 | whale   |
|  6 | ostrich |
+----+---------+


comment ajouter un nouvelle enregistrement qui aurait la valeur d'id non utilisé (ici 3) ??

tout ça sans pour autant lister une par une les valeur dans l'ordre croissant ce qui serait un peu lourd à mon goût.

Merci!
captain_torche
J'utilise un truc du même genre sur un de mes sites, mais pas un peu bidouillé.
Déjà, je ne touche pas au champ id, j'ai un autre champ, appelé numéro.
Lorsque je détruis une ligne, je récupère son numéro, et je décrémente tous les autres champs ayant un numéro supérieur
SQL
UPDATE table SET numero = numero-1 WHERE numero > numero_supprime

Ensuite, lors de l'insertion d'un nouveau champ, comme je n'utilise pas d'auto-incrément, je vérifie le numéro le plus élevé
SQL
SELECT MAX(numero) FROM table
, auquel je rajoute 1.
Je précise que je le fais sur une table contenant très peu d'enregistrements.
robinsonvendredi
Je suis de l'avis de Captain Torche : à ta place je ne toucherais pas aux ID des enregistrements gérés par le moteur SQL.

Si tu veux gérer une incrémentation bien à toi il existe des fonctions de séquence, selon les bdd.
xpatval
Tout comme les autres réponses, si ton id est une clé auto-incrémentée, n'essaie pas de boucher les trous. Sers-toi d'un autre champ réservé à cet effet.

xpatval
Spidetra
1. Je partage l'avis général sur les manipulations de clé primaire.

2. Je poste une solution permettant de trouver les trous dans une séquence. Cette séquence peut-être une clé primaire ou n'importe quel autre type de séquence

3. J'ai trouvé la requête par tatonnement. Donc, il existe certainement une meilleure solution.

4. La requête n'est pas parfaite. Elle marche très bien pour les trous de longueur 1.
Si la longueur est > 1, la requête ne trouve que le premier élément de la séquence manquante.

Dans mon jeu de test il manque : 6, 7, 15, 16.
La requête retourne uniquement 6 et 15.
Il est donc possible :
- de réutiliser les n° 6 et 15
- de repasser une 2° fois la requête qui retournera 7 et 16.


5. Je suis preneur de toutes modifications permettant d'améliorer cette requête.

6. SGBD ne supportant les requêtes imbriquées s'abstenir wink.gif

Mon jeu de test :
CODE

IDVilla Prix
1 10
2 10
3 10
4 10
5 10
8 20
9 20
10 20
11 30
12 30
13 30
14 30
17 30
18 40
19 40


La requête :
SQL
SELECT DISTINCT (v1.IDVilla + 1) As IDLibre
FROM villa v1, villa v2, villa v3
WHERE v1.IDVilla < v2.IDVilla AND ( v2.IDVilla - v1.IDVilla ) >= 2 AND v3.IDVIlla BETWEEN v1.IDVilla AND v2.IDVilla AND NOT EXISTS
( SELECT *
FROM villa v4
WHERE v4.IDVILLA > v1.IDVilla AND v4.IDVilla < v2.IDVilla
)
Spidetra
La même requête en plus simple ( J'ai honte blush.gif )
SQL
SELECT DISTINCT (v1.IDVilla + 1) As IDLibre
FROM villa v1, villa v2
WHERE v1.IDVilla < v2.IDVilla AND v2.IDVilla >= ( 2 + v1.IDVilla ) AND NOT EXISTS
( SELECT *
FROM villa v3
WHERE v3.IDVILLA > v1.IDVilla AND v3.IDVilla < v2.IDVilla
)


Les modifications :
1. La table v3 servait à rien dans le premier SELECT
2. S'il existe un INDEX sur la séquence testée, cette syntaxe sera plus performante :
v2.IDVilla >= ( 2 + v1.IDVilla )
au lieu de
( v2.IDVilla - v1.IDVilla ) >= 2

Cela forcera l'utilisation de l'index sur v2.IDVilla.
Si le champ n'est pas un champ indexé les deux syntaxes sont équivalentes
xorax
merci beaucoup pour vos réponses.

jolie syntaxe anorci!
je vais l'intégrer de ce pas!

CITATION
Je suis de l'avis de Captain Torche : à ta place je ne toucherais pas aux ID des enregistrements gérés par le moteur SQL.

Si tu veux gérer une incrémentation bien à toi il existe des fonctions de séquence, selon les bdd.

je suis pas non plus très au point mysql apparement, qu'est-ce que ça fait si je touche au champ id ? c'est un champ que j'ai créé moi même... mysql éssaye d'optimisé particulièrement les champs qui s'appellent `id` ??

Dans ce cas la il me semble évident de ne pas mettre d'auto_increment.

pour info captain_torche ta syntaxe est pas mal et je vien de la trouvé sur le manuel de référence, et ils indiquent que c'est trés rapide :
CITATION
Si vous avez besoin de calculer souvent des expressions en fonction des informations placées dans de nombreuses lignes (comme compter des lignes), il est probablement plus efficace d'introduire une nouvelle table qui va mettre à jour ce compteur en temps réel. Une modification du type présenté ci-dessous est très rapide!

UPDATE tbl_name SET count_col=count_col+1 WHERE key_col=constant;
C'est très important lorsque vous utilisez les types de tables MyISAM et ISAM , qui ne dispose que d'un verrouillage de table (plusieurs lecteurs, un seul qui écrit). Cela va aussi améliorer les performances avec la plus par des bases, car le gestionnaire de verrouillage de ligne aura moins de tâches à faire.


je faire des test...
Merci!
captain_torche
Bon, tu me diras ce que ça donne sur ta table.
Je suis pas super-calé en optimisation, et je m'en sers actuellement que pour la réorganisation de rubriques (donc, comme je l'ai dit, un nombre très limité d'éléments).
Spidetra
CITATION(xorax @ vendredi 07 avril 2006, 16h30)
je suis pas non plus très au point mysql apparement, qu'est-ce que ça fait si je touche au champ id ? c'est un champ que j'ai créé moi même... mysql éssaye d'optimisé particulièrement  les champs qui s'appellent `id` ??
Merci!
*


Le champ Id, ce n'est pas la clé primaire de ta table ?

Si c'est bien le cas tu doit avoir des relations entre ce champ et les autres tables de ta base. C'est pour cette raison que tout le monde t'as conseillé de ne pas y toucher manuellement.

Maintenant si c'est un champ classique, rien ne t'interdit de modifier ses valeurs.
xorax
à ok!

oui si je met la méthode de captain_torche je le mettrai pa en primaire, c'est d'ailleur ça qui me gène un peu... parce que j'ai une clef primaire à 2 champs et un auto_increment sur le 2ème champ.

d'ailleur en passant quel est la différence entre une clef primaire et unique ?
Spidetra
CITATION(xorax @ vendredi 07 avril 2006, 17h24)
à ok!

oui si je met la méthode de captain_torche je le mettrai pa en primaire, c'est d'ailleur ça qui me gène un peu... parce que j'ai une clef primaire à 2 champs et un auto_increment sur le 2ème champ.


C'est quoi la structure exacte de ta ta ble ?

CITATION(xorax @ vendredi 07 avril 2006, 17h24)
d'ailleur en passant quel est la différence entre une clef primaire et unique ?
*



Une clé primaire est obligatoirement unique. Elle identifie de façon non ambigue un enregistrement de ta table.

UNIQUE est une contrainte que tu peux ajouter à n'importe quelle colonne de tes tables.
Ex : Tu pourrais décider de donner la caractéristique UNIQUE à un champ qui contiendrait des e-mails, un N° de sécurité sociale, la plaque d'immatriculation d'une voiture, etc...
xorax
ok merci pour l'explication.

SQL
CREATE TABLE `test` (
`id` int(10) unsigned NOT NULL,
`id2` smallint(5) unsigned NOT NULL auto_increment,
`name` varchar(32) NOT NULL,
PRIMARY KEY (`id`,`id2`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1;


id2 ne dépassera pa la 20aine en général mais id va surment dépasser les 1000.
id se répetera plusieur fois et id2 aussi mais jamais avec le même doublon.

et ça m'aurait simplifié la vie si id2 avait des valeurs continue. donc dans ce cas la il me semble que je devrais mieux utiliser la méthode de captain_torche.

par contre si j'aurais ça avec id j'aurais utilisé ta méthode anorci!

merci à tous!
Spidetra
Je ne comprend pas le sens de ta clé primaire id, id2 ?
Ta table test est lié avec d'autres tables ?
xorax
nan, une clef primaire sur 2 champs met une contrainte de doublon unique.
ex :
id - id2 - name
1 - 1 - test1
1 - 2 - test2
2 - 1 - test3
2 - 3 - test4

avec la structure précédente si j'ajoute un enregistrement :
insert into test (id, name) values (2, 'test5')

la ligne inséré va être :
2 - 4 - test5
(si l'auto_incrément est à 4...)

c'est assez pratique jdirais biggrin.gif
Ceci est une version "bas débit" de notre forum. Pour voir la version complète avec plus d'information, la mise en page et les images, veuillez cliquer ici.