Aller au contenu

valeur minimum non existante


Sujets conseillés

Posté

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 :

+----+---------+
| id | name    |
+----+---------+
|  1 | dog     |
|  2 | cat     |
|  3 | penguin |
|  4 | lax     |
|  5 | whale   |
|  6 | ostrich |
+----+---------+

j'éfface un enregistremnt au hazard, et j'ai ça :

+----+---------+
| 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!

Posté

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

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é

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.

Posté

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.

Posté

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

Posté (modifié)

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 ;)

Mon jeu de test :


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 :

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
)

Modifié par anorci
Posté (modifié)

La même requête en plus simple ( J'ai honte :blush: )

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

Modifié par anorci
Posté

merci beaucoup pour vos réponses.

jolie syntaxe anorci!

je vais l'intégrer de ce pas!

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 :

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!

Posté

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).

Posté
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!

<{POST_SNAPBACK}>

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.

Posté

à 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 ?

Posté
à 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 ?

d'ailleur en passant quel est la différence entre une clef primaire et unique ?

<{POST_SNAPBACK}>

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...

Posté

ok merci pour l'explication.

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!

Posté (modifié)

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 :D

Modifié par xorax

Veuillez vous connecter pour commenter

Vous pourrez laisser un commentaire après vous êtes connecté.



Connectez-vous maintenant
×
×
  • Créer...