Vous ne trouvez pas de réponse à votre problème ? Alors posez la question dans le forum. Souvenez-vous qu'il n'y a jamais de question bête, mais rester dans l'ignorance parce que l'on n'ose pas poser une question, ça c'est une erreur !

TROUVER LE PROCHAIN ID DE LIBRE.


Information sur la source

Catégorie :Base de données Classé sous : max, id, autoincrement Niveau : Débutant Date de création : 12/09/2007 Date de mise à jour : 12/09/2007 12:20:21 Vu : 4 439

Note :
Aucune note

Commentaire sur cette source (23)
Ajouter un commentaire et/ou une note

Description

MON PROBLEME ETAIT :

Dans mes tables de ma base de données, j'ai les valeurs suivantes. ces valeurs valent d'ID.
Pour des raisons de facilités, ces id ne sont pas en auto-Incrément.

Par défaut pour insérer un nouvel élément je fais un max(id) +1

Mais reprenons mon histoire ...
J'ai donc les valeurs :
1 - 2 - 3 - 4 - 5 - 6 - 7

Je delete le [4] et le [6] par exemple.

A l'insert suivant, comme a l'habitude je fais un max(id)+1.
Ce qui en toute logique me renvoi 8.

Mais voilà, j'aimerai que ça me renvoi tout d'abord [4], puis le [6] avant le [8].
En gros je souhaite combler les "trous" ...
___________________________________________________________________________________


J'ai trouvée une solution qui fonctionne bien. Le code qui suit est commenté et remplis de ECHO, afin de bien comprendre le cheminement.
Il est bien sûr a améliorer, à nettoyer etc ...
Mais je suis sur qu'il servira à des personnes comme moi, qui ont longuement cherché une instruction Mysql...

Avec un peu d'idée, on peut en faire une fonction, multi table qui renvoi simplement l'ID suivant dispo.

 

Source

  • //Chaine de connexion à la Bdd ici
  • include("connect.php");
  • // On recherche le MAX
  • $result=mysql_query("SELECT max(id) FROM matable WHERE cid='6' AND uid='1' ORDER by id ASC") or die(mysql_error());
  • $MAX= @mysql_result($result, 0);
  • echo "Nb Val. ( val MAX) : $MAX (prochain serait $MAX + 1 )<br>";
  • echo "<hr>";
  • // On regarde les valeurs qui existent dans la table
  • $requetesub=mysql_query("SELECT id FROM matable WHERE cid='6' AND uid='1' ORDER by id ASC") or die(mysql_error());
  • $totalsub = mysql_num_rows($requetesub);
  • // Pour info/test on affiche des résultats
  • echo "$totalsub ID relemnt occupé ( ";
  • while ($row = mysql_fetch_array($requetesub, MYSQL_ASSOC)) {
  • echo " {$row['id']} ";
  • }
  • echo")<hr>";
  • //On remet le pointeur au début. afin de parcourir de nouveau le tableau
  • mysql_data_seek($requetesub, 0);
  • $i=-1; //(-1 pour tester la valeur 0)
  • $p=0; //sera le pointeur.
  • while($i<$MAX)
  • {
  • $i++;
  • echo "<br> <u><b>Test de la valeur</u> : {$i} </b><br>";
  • $row = mysql_fetch_array($requetesub, MYSQL_ASSOC);
  • $val = $row['id'];
  • if($val==$i)
  • {
  • echo"La valeur est = à i -> la preuve :($val=$i)";
  • //on bouge le pointeur d'1 point
  • $p++;
  • @mysql_data_seek($requetesub, $p);
  • // A ce niveau, à la dern. valeur on aura une erreur de dépassement.
  • // Il faut donc prévoir un petit changement ou un test sup.
  • // Le @ évite simplement l'affichage du message d'erreur.
  • } else {
  • echo"ID libre trouvé : <b>$i</b> ($val=$i)";
  • //on ne déplace pas le pointeur
  • mysql_data_seek($requetesub, $p);
  • // ---- ICI on ferai un RETURN de l'ID si on fais une fonction ----
  • }
  • echo"<hr>";
  • }
//Chaine de connexion à la Bdd ici
include("connect.php");

// On recherche le MAX
$result=mysql_query("SELECT max(id) FROM matable WHERE cid='6' AND uid='1' ORDER by id ASC") or die(mysql_error());
$MAX= @mysql_result($result, 0);
echo "Nb Val. ( val MAX) : $MAX (prochain serait $MAX + 1 )<br>";
echo "<hr>";

// On regarde les valeurs qui existent dans la table
$requetesub=mysql_query("SELECT id FROM matable WHERE cid='6' AND uid='1' ORDER by id ASC") or die(mysql_error());
$totalsub = mysql_num_rows($requetesub);

// Pour info/test on affiche des résultats
echo "$totalsub ID relemnt occupé ( ";
while ($row = mysql_fetch_array($requetesub, MYSQL_ASSOC)) {
   echo " {$row['id']} ";
}
echo")<hr>";

//On remet le pointeur au début. afin de parcourir de nouveau le tableau
mysql_data_seek($requetesub, 0);

$i=-1; //(-1 pour tester la valeur 0)
$p=0; //sera le pointeur.

while($i<$MAX)
 {
   $i++;
   echo "<br> <u><b>Test de la valeur</u> : {$i} </b><br>";
   $row = mysql_fetch_array($requetesub, MYSQL_ASSOC);
   $val = $row['id'];
   
   if($val==$i)
    {
      echo"La valeur est = à i -> la preuve :($val=$i)";
      //on bouge le pointeur d'1 point
      $p++;
      @mysql_data_seek($requetesub, $p);
      // A ce niveau, à la dern. valeur on aura une erreur de dépassement.
      // Il faut donc prévoir un petit changement ou un test sup.
      // Le @ évite simplement l'affichage du message d'erreur.
    
    } else {
      echo"ID libre trouvé : <b>$i</b> ($val=$i)";
      //on ne déplace pas le pointeur
      mysql_data_seek($requetesub, $p);
      // ---- ICI on ferai un RETURN de l'ID si on fais une fonction ----

    }

  echo"<hr>";
}

Conclusion

Je précise que ma clé est de ce type :
Pour chaque $GID il exsite 0 à plusieurs $CID
Chaque $CID ayant de 0àn $ID

Plus clairement :
GID CID ID
1 1 1
1 1 1
1 1 2
1 2 1
1 2 1
1 2 4
1 2 5
1 2 6
1 3 1
etc...
 

Historique

12 septembre 2007 12:20:21 :
erreur de nom de table

Commentaires et avis

signaler à un administrateur
Commentaire de depression le 12/09/2007 12:28:41

Berk, c'est crade.

Au lieu d'utiliser une clé primaire dans ta table, utilise une clé unique, ce sera plus rapide et moins affreux pour les performances.

signaler à un administrateur
Commentaire de coockiesch le 12/09/2007 12:56:40

Salut! :-)

Quelques conseils:

  mysql_query est toujours suivi d'un test pour vérifier la bonne exécution de la requête:
$ret = mysql_query( "SELECT ...." );
if( !$ret )
  // traitement de l'erreur, on ne va pas plus loin

Ou, idem:
if( !( $ret = mysql_query( "SELECT ..." ) ) )
  // traitement de l'erreur, on ne va pas plus loin

Ca évite des erreurs sur mysql_num_rows, mysql_fetch_*, ...

Si tu as le choix, privilégie ' ' à  " ".

// ---- ICI on ferai un RETURN de l'ID si on fais une fonction ----
>> Justement, tu pourrais proposer une fonction, non? :-)

@++

R@f

signaler à un administrateur
Commentaire de SuperTonic le 12/09/2007 13:17:05

Bonjour.
Merci de ta réponse constructive.
Au bout de ma chaine (caché en fait par la form se trouve la chaine " or die(mysql_error()); "
qui reviens à ton " if( !$ret ) "

Pour la fonction, je suis en train de la faire.
Je la post dés qu'elle est terminée. (Je laisserai par contre les ECHO mais en commentaires)
Je sais que ça allourdi l'affichage, mais on est bien content de les trouver quand on essai de comprendre.
A bientot donc.

signaler à un administrateur
Commentaire de SuperTonic le 12/09/2007 13:23:25

IDEM mais sous la forme de 2 fonctions.
---------------------------------------------------------
function maxid($table, $id_contact)
   {
     //en fonction de la table les reqêtes différent un peu
     switch($table)
      {
       case 'contacts':
          $requete="SELECT max(id_contact) FROM $table WHERE id_user='{$_SESSION['id_user']}'";
          break;
       default:
          $requete="SELECT max(id) FROM $table WHERE id_contact='$id_contact' AND id_user='{$_SESSION['id_user']}'";
      }

     //on recherche le prochain id pour cette adresse
     @mysql_free_result($result);
     //echo $requete;
     $result=mysql_query($requete,$_SESSION['linkdb']);
     if (!$result) {die('Erreur num: '.mysql_errno($_SESSION['linkdb']).'<br>Échec de la requête : inF_nextid<br>('.$requete.'): '.mysql_error()); }
     $val= @mysql_result($result, 0);
     $max=$val+1;
     return $max ;
   }

---------------------------------------------------------
---------------------------------------------------------

function nextid($table, $id_contact)
   {
     // On recherche le MAX (appel Fonct.1)
     $MAX= maxid($table, $id_contact);
     //echo "Val MAX: $MAX <br>";

     switch($table)
      {
       case 'contacts':
          $requetesub=mysql_query("SELECT id_contact as id FROM $table WHERE id_user='{$_SESSION['id_user']}' ORDER by id_contact ASC") or die('Erreur num: '.mysql_errno($_SESSION['linkdb']).'<br>Échec de la requête : inF_nextid1<br>('.$req.'): '.mysql_error());
          break;
       default:
          $requetesub=mysql_query("SELECT id FROM $table WHERE id_contact='$id_contact' AND id_user='{$_SESSION['id_user']}' ORDER by id ASC") or die('Erreur num: '.mysql_errno($_SESSION['linkdb']).'<br>Échec de la requête : inF_nextid2<br>('.$req.'): '.mysql_error());
      }

     $totalsub = mysql_num_rows($requetesub);
     // Pour info/test on affiche des résultats
     //echo "$totalsub ID relemnt occupé ( ";
     //while ($row = mysql_fetch_array($requetesub, MYSQL_ASSOC)) {
     //   echo " {$row['id']} ";
     //}
     //echo")<hr>";
     //On remet le pointeur au début. afin de parcourir de nouveau le tableau
     // uniquement si on exécute le While précédent mis en comment.
     //mysql_data_seek($requetesub, 0);

     $i=-1; //(-1 pour tester la valeur 0)
     $p=0; //sera le pointeur.

     while($i<$MAX)
      {
        $i++;
        //echo "<br> <u><b>Test de la valeur</u> : {$i} </b><br>";
        $row = mysql_fetch_array($requetesub, MYSQL_ASSOC);
        $val = $row['id'];

        if($val==$i)
         {
           //echo"La valeur est = à i -> la preuve :($val=$i)";
           //on bouge le pointeur d'1 point
           $p++;
           if($p==$MAX)
            {
              return $MAX;
            }else{
              mysql_data_seek($requetesub, $p);
            }
        } else {
            //echo"ID libre trouvé : <b>$i</b> ($val=$i)";
           //on ne déplace pas le pointeur
           mysql_data_seek($requetesub, $p);
           return $i;
        }
      }
  }

Bon courage à tous.

signaler à un administrateur
Commentaire de coockiesch le 12/09/2007 13:23:28

Ok, désolé, j'avais pas vu! :-)
Par contre, si tu fais une fonction, il peut être intéressant de ne pas faire le or die, mais de renvoyer une valeur spéciale...

@++

R@f

signaler à un administrateur
Commentaire de SuperTonic le 12/09/2007 13:30:31

Exact !
Je n'y avais pas pensé. ça peut effectivement être interessant.

signaler à un administrateur
Commentaire de psykocrash le 12/09/2007 20:26:37

Je suis étonné que personne n'ai fait la remarque suivante : il ne faut surtout pas faire ce genre d'opérations quand on utilise des clés étrangères. Ca crée des conflits d'intégrité référentielle. D'ailleurs je vois toujours pas pourquoi les débutants (je parle en général, SuperTonic) cherchent toujours à combler ces "trous" dans les tables ??

signaler à un administrateur
Commentaire de SuperTonic le 12/09/2007 20:34:16

Mes tables sont totalements indépendantes des autres.
Id 4 dans table 1 ne correspond à AUCUN autre enregistrement référencé par cet ID dans les autres tables. Par ailleurs s'il y a un 'trou' c'est que tous les enregistrements des tables connexes ont été supprimés également (quand relation il existe)

Je peux donc combler les trous sans crainte de rencontrer un conflit d'intégrité référentielle.
MAIS
effectivement s'il devait y avoir une relation (n,n) il ne faut pas le faire !
Sinon la clé ne définierai plus les bonnes valeurs....

C'est une précision importante !!
MERCI à toi l'ami.

signaler à un administrateur
Commentaire de coucou747 le 12/09/2007 21:13:07

psykocrash, combler un trou dans une table, c'est avoir le plaisir ensuite de faire une pagination sans voir de lenteurs au chargement...
un select where id between ... and ... sera plus rapide qu'un order by ... limit ...
pour ton probleme de clefs etrangeres, il est simple de mettre un nouveau champ pour chaque parametre possible de pagination...

signaler à un administrateur
Commentaire de psykocrash le 13/09/2007 00:42:41

coucou747, le temps que tu gagnes a utiliser between au lieu de order by ... limit, tu le perds à repasser en revue toute ta table à la recherche d'un id "libéré". L'un dans l'autre, moi je préfère ne pas toucher aux clés primaires pour garder une certaine "logique de progression" dans l'enregistrement des tuples. Et puis je vois pas ce qui t'empêche d'utiliser between dans le cas où certains id ont sauté, il suffit de bien penser ton application et tes requêtes dès le départ (je te fait confiance pour ça) et ça tourne sans problème.

signaler à un administrateur
Commentaire de coucou747 le 13/09/2007 06:48:03

ce temps tu le perds lors des delete... en general dans la partie admin d'un site... a cote de tout les select qui seront acceleres dans la partie utilisateur...

signaler à un administrateur
Commentaire de psykocrash le 13/09/2007 10:58:51

Le temps perdu est pour les INSERT (c'est là qu'on calcule le id, donc aussi coté utilisateurs), pas lors des delete.
Et je ne vois toujours pas pourquoi tu n'utiliserais pas between, que tu peux utiliser même en ayant des id qui ont sauté.

signaler à un administrateur
Commentaire de Evangun le 13/09/2007 18:16:16

Pour la pagination Coucou... quel est le rapport avec les clés primaires ?
un id n'est pas là pour servir à mettre un ordre, il est là pour l'unicité. Mauvaise idée à mon avis de t'en servir pour ordonner les lignes. Ce sera

-> SELECT record LIMIT 10, 20; et peu importe s'il y a des trous dans les index ou pas. Donc si tu fais ORDER BY, ce sera dans un cas comme dans l'autre.

Et au passage, dans le cas où on comble les trous et où ne veut pas utiliser LIMIT, autant faire WHERE id > XX LIMIT 10 et pas utiliser BETWEEN : c'est probablement plus rapide car il ne fait qu'une comparaison par ligne au lieu de deux.

Moi non plus je ne pense que combler les vides soit une bonne idée. Ca n'a objectivement aucun intérêt (ou alors Coucou faudra que tu détailles ton histoire de pagination parce que je ne te suis pas du tout) et n'amène que des problèmes quand les tables ne sont pas indépendantes.

signaler à un administrateur
Commentaire de coucou747 le 13/09/2007 21:03:51

une comparaison mais un select sur beaucoup plus de lignes pour n'en prendre que 10 au final... le between est bien meilleur

signaler à un administrateur
Commentaire de Evangun le 13/09/2007 23:44:46

Mais de toute façon le SELECT parcourt toutes les lignes de la base, peu importe BETWEEN ou > !! Donc mieux vaut >. Et par défaut avec MyIsam, il parcourt toutes les lignes dans l'ordre où elles ont été insérées, donc même si on bouche les index libres, ça ne change rien. Et si on spécifie LIMIT, MySQL s'arrêtera aussitôt après avoir trouvé ce nombre de lignes, c'est pour ça qu'il faut toujours spécifier un LIMIT, même si on sait qu'on ne va récupérér qu'un seul enregistrement.

Bref, à moins que l'index serve aussi pour ordonner les lignes de la table (ce qui n'est pas une bonne idée) et qu'on reclasse la table après chaque insertion (grosse perte de perfs), ça ne sert vraiment à rien de combler les index libres ! il faut abandonner cette idée.

signaler à un administrateur
Commentaire de coucou747 le 14/09/2007 00:56:46

c'est a chaque suppression qu'on doit reindexer en fait...

signaler à un administrateur
Commentaire de Evangun le 14/09/2007 01:37:25

... ou pas. Je me vois mal faire un update sur toute une table, ainsi que sur tous les enregistrements des autres tables liés à ces index, pour un supposé avantage qui n'existe pas...
L'idée d'avoir un index "sans trou" est peut-être sympa esthétiquement parlant, mais mauvaise.

signaler à un administrateur
Commentaire de SuperTonic le 14/09/2007 08:52:37

Bonjour à tous.
Je suit avec pertinance vos discutions... d'une simple petite fonction, je déchaine des discutions intéressantes ... (je suis fier de moi lol )
J'aimerai revenir sur le LIMIT.
Je cite EVANGUN : "il faut toujours spécifier un LIMIT, même si on sait qu'on ne va récupérér qu'un seul enregistrement"

Voilà bien un truc que je ne fais jamais. Pouvez m'expliquer en quoi c'est important.
si je fais un limit à 30 et que mon résultat est à la 35eme ligne ? il va le trouver tout de même ou pas ??

signaler à un administrateur
Commentaire de psykocrash le 14/09/2007 11:58:10

Cette fonction est là pour trouver le prochain id, elle ne réorganise pas les enregistrements. Elle n'est donc pas à exécuter après un delete mais avant un insert.

@SuperTonic : Si tu indiques correctement les conditions, oui. C'est important (mais pas indispensable) car il permet de ne pas mobiliser plus de ressources que nécessaire. C'est de l'optimisation. Pourquoi charger en mémoire tous les enregistrements quand tu n'as besoin que des 10 premiers, ou que du 11ème au 20ème (par exemple...) ?

signaler à un administrateur
Commentaire de coucou747 le 14/09/2007 12:02:24

je viens de vous faire un bench...
http://blogs.codes-sources.com/coucou747/archive/2007/09/14/bench-sur-la-pagination-sous-mysql.aspx
mais meme ton WHERE + limit, ca revient a faire :
WHERE champ_dans_l_ordre >= page*nbr_par_page LIMIT nbr_par_page
donc ton champ doit-etre dans l'ordre...
le explain semble indiquer que... les benchs sont toutefois plus reserves...

signaler à un administrateur
Commentaire de Evangun le 14/09/2007 14:02:29

Merci pour ton article Coucou.
Pour les benchmarks, pourquoi ne pas faire la somme du temps d'exécution de 100 000 instructions ? On y verrait plus clair. Le nombre ROWS de EXPLAIN n'est pas significatif, ça ne veut pas dire que MySQL va parcourir plus de lignes pour un > + LIMIT. C'est uniquement le nombre de résultats possibles, point.

Ta conclusion qui est de dire qu'ordonner une table selon l'ordre où les lignes sont les plus sollicitées me paraît tout à fait logique. Ca revient à faire ORDER une seule fois et pas à chaque SELECT. Sauf que j'en reviens au problème de base :

1) ce n'est pas le métier de la clé primaire de servir pour l'ordre. D'ailleurs une nouvelle ligne vient prendre un id libre au pif, en tout cas dans cette source.
2) sous MyIsam, la clé primaire ne définit PAS l'ordre des lignes dans la table. Une nouvelle ligne ne sera pas accédée plus vite qu'elle porte l'id 3 ou l'id 265972545.

Donc fondamentalement, boucher les trous des ID ne sert à rien et causent des pbs. Ensuite si tu veux réordonner ta table à chaque insertion, libre à toi, ça peut être un choix judicieux dans certains cas précis, mais il n'y a pas de rapport avec le fait de boucher les id libres.

Je signale quand même qu'avec ta technique Coucou, je pense que tu ne peux pas utiliser de clé index, puisqu'au moment de la recherche ça viendrait à l'encontre de la façon dont tu as réordonné ta table par toi-même. Ce qui est coûteux pour toutes les requêtes autres que ta (ton unique) requête optimisée. A moins qu'il soit possible de spécifier quand on fait un SELECT de tenir compte ou pas des colonnes indexées ? Mais je n'en ai jamais entendu parler.

SuperTonic : tout simplement, si tu fais SELECT name where id = 5; MySQL va trouver la ligne, puis continuer pour voir s'il n'y en a pas d'autre ou id = 5. Ce qui est idiot parce que tu sais que chaque id et unique, donc il nen trouvera rien. Avec LIMIT tu lui dit d'arrêter de chercher.
Tu peux aller lire la doc officielle de MySQL, il y a un chapitre entier sur l'optimisation.

signaler à un administrateur
Commentaire de SuperTonic le 14/09/2007 14:08:47

Ok !! j'ai compris... Je vais lire cette doc.
Je vais également ajouté des LIMIT à mes requêtes....

signaler à un administrateur
Commentaire de pbaboon le 19/09/2007 23:07:26

Bonjour à tous,

Je rajouterai, au fait que ça n'a aucun intêret de boucher les trous dans les id, que cela ne peut amener que des problèmes surtout s'il y a plusieurs utilisateurs qui saisissent des données en même temps :
le même id (max id+1) peut etre attribué plusieurs fois à des utilisateurs différents, tant qu'il n'aurra pas été enregistré dans la bd, et donc lors de l'enregistrement pour les utilisateurs suivants, des doublons ou des blocages à l'insert peuvent apparaître suivant la nature de la cle concernée (unique ou pas)...
Quand à moi je préfère laisser mysql gérer ça tous seul...c'est son job...
... peu-etre penser aussi à last_insert()
bonne continuation

Ajouter un commentaire

Discussions en rapport avec ce code source dans le forum

max_user_connection à cause de fopen ? [ par Also know as ] Bonjour,Voilà j'obtiens ce fameux message "max_user_connection" de la base de donnée quand je rajoute ce code :Ou le lien est un lien n'importe sur le Récupérer l'id de session dans la base de donnée [ par tidus2901 ] Bonjour, pour les navigateurs n'acceptant pas les cookies, je voudrais mettre en cache via l'ip dans la base de donnée l'id de session du visiteur. Probléme avec GET_PAGE [ par matrixscript59 ] donc voicie mon probléme quand je regarde les commentaire de mais news  il veut pas me affiché la page 2 ou 3 etc... quand je clic sur 2 il me envoye redirection [ par kelm_by ] salut tous le monde,salut j'ai une page nomée index.php?id=1 comment je peux rediriger automatiquement vers id=2 id=3 et ainsi de suite.merci renomer un champs sql [ par kelm_by ] salut,j'ai une table nomé tab ou il ya un champs id a insertion automatique mais j'ai suprimer quelque ligne alors comment renomer l'id de 1 au dernie GET [ par kelm_by ] salutcomment est ce que je peux envoyer une variable qui contiend &amp;url="index?id=5&amp;ir=10&amp;ip=200"index.php?url=aaaa&amp;id=10merci de la folie [ par kelm_by ] salut tous le monde Warning: fopen( lbum_id=72&amp;artist_id=61) [function.fopen]: failed to open stream: No such file or directory in /....... Question sur un formulaire [ par limaseb ] Bonjour, Je viens de generer un formulaire mais j'aimerais que d envoyer par mails qu'il soit juste valider et qu'il s'ouvre dans une nouvelle fenetre insertion d'image [ par vinz78 ] salut je viens de créer diverse fichier php me permettant d'insérer mes images dans une base de données mysql tout fonctionne sauf pour le script d'ap Php Mysql stocké [ par xa4ke ] hello Voila moi j'ai un petit problème pour charger un code Html à partir d'une base de donnée Mysql j'ai créé une table papa j'ai créé


Nos sponsors

Sondage...

CalendriCode

Novembre 2008
LMMJVSD
     12
3456789
10111213141516
17181920212223
24252627282930

Consulter la suite du CalendriCode

Téléchargements

Logiciels à télécharger sur le même thème :



Développement réalisé par Nicolas SOREL (Nix) avec l'aide de : Cyril DURAND et Emmanuel BAÏSE, Merci à Vincent pour ses précieux conseils
CodeS-SourceS.com© Toute reproduction même partielle est interdite sauf accord écrit du Webmaster
CodeS-SourceS.com© est une marque déposée tous droits réservés
Temps d'éxécution de la page : 0,187 sec

Google Coop CodeS-SourceS Google Coop CodeS-SourceS


Certaines images présentes sur le site (notament certains avatars) sont issues des collections IconShock, donc si vous souhaitez utiliser ces icons vous devez les acheter, ne les copiez pas et ne utilisez pas dans vos sites et applications sans les avoir commandé.