Suite

Existe-t-il un moyen d'auto_increment pour la colonne ID dans QGIS


Je crée une carte fictive et j'ai donc besoin de créer beaucoup de points, de lignes et bien sûr de polygones. Plus tard, j'exporte mes données au format geojson. Mais avant cela, je dois toujours donner à chaque élément un identifiant unique.

Je n'ai pas besoin d'un tri spécial, comme le plus grand polygone obtient le plus petit ID ou plus. je viens besoin tout polygones avec un identifiant à la fin, sans pour autant Faire il manuellement comme je dois le faire maintenant.

Ce serait génial si quelqu'un sait comment faire.


L'utilisation du calculateur de champ est la voie à suivre :

Aucune pièce d'identité n'a été fournie dans

  1. Numérisez toutes les fonctionnalités sans entrer d'identifiant.
  2. Avant l'exportation, mettez à jour les identifiants uniques avec l'expression « $ Id » à l'aide du calculateur de champ.

Certaines pièces d'identité sont déjà données dans

  1. Si vous avez déjà des identifiants, vous pouvez utiliser '-$Id'. Assurez-vous de sélectionner simplement de nouvelles fonctionnalités, ce qui signifie qu'elles sont « NULL » dans la ligne d'identification. Faites-le simplement en commandant la colonne.
  2. Maintenant, faites les étapes des images:


Alléluia! Ou Eurêka. Ou peu importe. Ceci peut être fait. Avec un fichier de formes.

  1. S'il n'y en a pas déjà un, ajoutez un champ pour contenir l'identifiant de la fonctionnalité, disons "FID", de type Nombre entier (entier).
  2. Ouvert Propriétés de la couche (clic droit sur le calque et choisissez Propriétés… ou double-cliquez sur le calque), cliquez sur le Formulaire d'attributs onglet, puis sous Général décocher Modifiable et sous Valeurs par défaut Sur le terrain Valeur par défaut tapermaximum("FID") + 1.

En décochant Modifiable, vous ne pouvez pas entrer une autre valeur ou supprimer ce qui s'y trouve. Notez que s'il existe des valeurs sans ID, ces valeurs ne seront pas mises à jour. À un moment donné, je vais expérimenter avec la vérification Appliquer la valeur par défaut lors de la mise à jour et réviser ma formule pour vérifier une valeur zéro ou NULL pour mettre à jour uniquement ces enregistrements lorsqu'ils sont modifiés, pas n'importe quel enregistrement avec une valeur supérieure à 1. (Plus tôt dans cet article, il a été expliqué comment mettre à jour le champ FID avec des valeurs uniques, ce que vous devrez faire si vous avez ajouté le champ après qu'il y avait déjà des entités dans le fichier de formes.)

Notez que cela est enregistré avec le fichier de carte actuel, pas le fichier de formes, donc l'ajout de ce fichier de formes plusieurs fois vous obligera à copier cette partie du style de couche dans la couche nouvellement ajoutée. Pour cela, faites un clic droit sur le calque, choisissez Styles > Copier le style > Champs, et faites un clic droit sur un autre calque, choisissez Styles > Coller le style > Toutes les catégories de styles (ou continuer à Des champs). Vous pouvez également copier cette partie du style sur n'importe quel autre calque basé sur un fichier de formes, mais le champ ID doit avoir le même nom que le calque à partir duquel vous copiez.


Je voudrais ajouter au message de vinayan et mentionner brièvement le nombre de lignes fonction, car elle est très similaire et, dans certains cas, peut être un peu plus pratique.

identifiant renvoie le Identifiant de la fonction, ce qui signifie qu'il commence toujours à zéro.
nombre de lignes renvoie le numéro de la ligne, ce qui signifie qu'il commence à une.

Donc, en gros, si vous voulez que l'auto-incrémentation commence à 0, allez pour $id, et si vous voulez qu'il commence à 1 alors allez pour $rownum.


Mise à jour pour QGIS 3

Je sais que je suis assez en retard pour cela mais toujours bon de donner des mises à jour:

Dans QGIS 3, il existe maintenant un outil natif qui peut être utilisé pour faire ce travail exact et il s'appelle "Ajouter un champ auto-incrémental"

Pas besoin d'utiliser une expression dans le calculateur de champ ou de faire de codage mais néanmoins tout cela reste très utile et bon à savoir.


Ce sujet a été abordé ici : Créer un fichier de formes avec une clé primaire d'incrémentation automatique dans QGIS

Mes suggestions seraient :

1) Les bases de données SQLITE / SpatialLite prennent en charge l'auto-incrémentation sur un champ défini sur INTEGER PRIMARY KEY :

Sur un INSERT, si la colonne ROWID ou INTEGER PRIMARY KEY ne reçoit pas explicitement de valeur, elle sera alors automatiquement remplie avec un entier inutilisé, généralement celui de plus que le plus grand ROWID actuellement utilisé. Cela est vrai que le mot clé AUTOINCREMENT soit utilisé ou non.

Chaque fois que vous modifiez/créez des polygones, vous pouvez renseigner leurs attributs et SQLITE lui attribuera une valeur unique incrémentielle dans le champ que vous avez défini sur le type INTEGER PRIMARY KEY.

Lorsque vous êtes prêt à exporter vers GEOJSON, vous êtes tous prêts avec vos ID UNIQUES.

2) Si vous utilisez des fichiers de formes, créez un champ OBJECTID de type INTEGER et utilisez une expression de calculatrice de champ pour remplir ce champ chaque fois que vous modifiez/créez des polygones et que vous devez les exporter. Vous perdrez l'ID d'origine qu'un polygone avait autrefois, mais c'est le seul moyen d'y parvenir en utilisant .SHP. (Je vais devoir trouver l'expression du calculateur de champ).

PostGIS est une autre source de données que vous voudrez peut-être explorer, bien que plus lourde que SQLITE, vous pourriez trouver de la valeur dans un tel système à mesure que vous avancez…


Ancien post, mais pour tous ceux qui recherchent une solution rapide, le mien consistait à créer un champ avec $ID + 1 et il générera automatiquement en commençant par 1 !


Si vous n'avez pas besoin de quelque chose d'humainement digestible, il existe maintenant une solution simple : dans le champ propriétés, sélectionnez "UUID Generator" et laissez tout vide.

Cela créera automatiquement un UUID sur le terrain. Pas aussi convivial qu'un simple nombre (comme $id ou $rownum), mais génère l'UUID dès le début, donc pas d'étapes successives.


vous pouvez simplement supprimer la première colonne (id) et en créer une nouvelle "Comme champ virtuel"


Copiez simplement les fichiers et créez une copie CSV et affichez à nouveau la création d'OID et exportez-les en tant que nouveau fichier de formes ou classe d'entités.


ces solutions ne fonctionnaient plus pour moi dans QGIS 2.01 Dufour. Dactylographie$idsur un champ nouveau ou existant nommé 'id' dans le champ de saisie de l'expression m'a donné une erreur "L'expression n'est pas valide"

Ce qui a fonctionné, c'est de taper la fonction$rownumpuis cliquez sur "OK"


La façon la plus simple de le faire serait probablement d'utiliser un script python ou peut-être est-ce possible avec la calculatrice de champ. Désolé, je n'en ai pas pour vous, peut-être que quelqu'un d'autre le fera. En attendant, je chercherais un script python pour cela. J'en ai vu beaucoup à ce sujet pour ArcGIS, mais je suis sûr qu'il y a quelque chose pour QGIS.


Problème avec l'incrémentation automatique dans MYSQL

Je souhaite conserver JOB_NAME , SANDBOX , PARENT_JOB_NAME en tant que clé primaire et JOB_ID en tant qu'incrément automatique car j'utilise "ON DUPLICATE KEY UPDATE" et en raison de l'auto-incrémentation, il insère de nouvelles lignes et crée un doublon dans la table.

Et tout en supprimant job_id de la clé primaire. J'obtiens une erreur en tant que "Définition de table incorrecte, il ne peut y avoir qu'une seule colonne automatique et elle doit être définie comme une clé"


17 réponses 17

Ce n'est jamais une mauvaise idée d'avoir un identifiant de ligne unique garanti. Je suppose que je ne devrais pas dire jamais &ndash, mais allons-y avec l'écrasante majorité du temps, c'est une bonne idée.

Les inconvénients potentiels théoriques incluent un index supplémentaire à maintenir et un espace de stockage supplémentaire utilisé. Cela n'a jamais été une raison suffisante pour moi de ne pas en utiliser un.

TLDR : Utilisez des UUID au lieu de l'auto-incrémentation, si vous ne disposez pas déjà d'un moyen unique d'identifier chaque ligne.

Je ne suis pas d'accord avec toutes les réponses précédentes. Il existe de nombreuses raisons pour lesquelles c'est une mauvaise idée d'ajouter un champ d'incrémentation automatique dans toutes les tables.

Si vous avez une table où il n'y a pas de clés évidentes, un champ à incrémentation automatique semble être une bonne idée. Après tout, vous ne voulez pas sélectionner * du blog où body = '[10000 character string]' . Vous préférez sélectionner * dans le blog où >. Je dirais que dans la plupart de ces cas, ce que vous voulez vraiment, c'est un identifiant unique et non un identifiant unique séquentiel. Vous voudrez probablement utiliser un identifiant universellement unique à la place.

Il existe des fonctions dans la plupart des bases de données pour générer des identifiants uniques aléatoires ( uuid dans mysql, postgres. newid dans mssql). Ceux-ci vous permettent de générer des données dans plusieurs bases de données, sur différentes machines, à tout moment, sans connexion réseau entre elles, tout en fusionnant les données sans conflit. Cela vous permet de configurer plus facilement plusieurs serveurs et même des centres de données, comme par exemple avec des microservices.

Cela évite également aux attaquants de deviner les URL des pages auxquelles ils ne devraient pas avoir accès. S'il y a un https://example.com/user/1263, il y a probablement aussi un https://example.com/user/1262. Cela pourrait permettre l'automatisation d'un exploit de sécurité dans la page de profil de l'utilisateur.

Il existe également de nombreux cas où une colonne uuid est inutile voire nuisible. Disons que vous avez un réseau social. Il y a une table des utilisateurs et une table des amis. La table friends contient deux colonnes d'ID utilisateur et un champ d'auto-incrémentation. Vous voulez que 3 soient amis avec 5 , vous insérez donc 3,5 dans la base de données. La base de données ajoute un identifiant auto-incrémenté et stocke 1,3,5 . D'une manière ou d'une autre, l'utilisateur 3 clique à nouveau sur le bouton "ajouter un ami". Vous insérez à nouveau 3,5 dans la base de données, la base de données ajoute un identifiant auto-incrémenté et insère 2,3,5 . Mais maintenant, 3 et 5 sont amis deux fois ! C'est une perte d'espace, et si vous y réfléchissez, la colonne d'auto-incrémentation l'est aussi. Tout ce que vous avez besoin de voir si a et b sont amis est de sélectionner pour la ligne avec ces deux valeurs. Ils constituent, ensemble, un identifiant de ligne unique. (Vous voudriez probablement écrire une logique pour vous assurer que 3,5 et 5,3 sont dédupliqués.)

Il existe encore des cas où les identifiants séquentiels peuvent être utiles, comme lors de la création d'un raccourcisseur d'URL, mais la plupart du temps (et même avec le raccourcisseur d'URL), un identifiant unique généré de manière aléatoire est ce que vous voulez vraiment utiliser à la place.

Les clés auto-incitatives ont surtout des avantages.

Mais certains inconvénients possibles pourraient être :

  • Si vous avez une clé métier, vous devez également ajouter un index unique sur cette ou ces colonnes afin d'appliquer les règles métier.
  • Lors du transfert de données entre deux bases de données, en particulier lorsque les données se trouvent dans plus d'une table (c'est-à-dire maître/détail), ce n'est pas simple car les séquences ne sont pas synchronisées entre les bases de données, et vous devrez d'abord créer une table d'équivalence en utilisant le clé métier comme correspondance pour savoir quel ID de la base de données d'origine correspond à quel ID dans la base de données cible. Cependant, cela ne devrait pas poser de problème lors du transfert de données depuis/vers des tables isolées.
  • De nombreuses entreprises disposent d'outils de reporting ad hoc, graphiques, pointer-cliquer, glisser-déposer. Étant donné que les ID auto-incrémentés n'ont pas de sens, ce type d'utilisateurs aura du mal à comprendre les données en dehors de "l'application".
  • Si vous modifiez accidentellement la clé métier, il est probable que vous ne récupérerez jamais cette ligne car vous n'avez plus rien à faire pour que les humains l'identifient. Cela a causé une fois une erreur dans la plate-forme BitCoin.
  • Certains concepteurs ajoutent un ID à une table de jointure entre deux tables, alors que le PK doit simplement être composé des deux ID étrangers. Évidemment, si la table de jointure se situe entre trois tables ou plus, un ID auto-incrémenté est logique, mais vous devez alors ajouter une clé unique lorsqu'elle s'applique à la combinaison de FK pour appliquer les règles métier.

Voici une section d'article de Wikipédia sur les inconvénients des clés de substitution.

Juste pour être contraire, non, vous n'avez PAS besoin d'avoir toujours un PK AutoInc numérique.

Si vous analysez soigneusement vos données, vous identifiez souvent des clés naturelles dans les données. C'est souvent le cas lorsque les données ont une signification intrinsèque pour l'entreprise. Parfois, les PK sont des artefacts de systèmes anciens que les utilisateurs professionnels utilisent comme deuxième langue pour décrire les attributs de leur système. J'ai vu des numéros VIN de véhicule utilisés comme clé primaire d'un tableau "Véhicule" dans un système de gestion de flotte par exemple.

Quelle que soit sa provenance, SI vous possédez déjà un identifiant unique, utilisez-le. Ne créez pas une deuxième clé primaire dénuée de sens, c'est du gaspillage et cela peut provoquer des erreurs.

Parfois, vous pouvez utiliser un AutoInc PK pour générer une valeur client significative, par ex. Numéros de police. Définir la valeur de départ sur quelque chose de sensé et appliquer des règles métier sur les zéros non significatifs, etc. C'est probablement une approche du « meilleur des deux mondes ».

Lorsque vous avez un petit nombre de valeurs relativement statiques, utilisez des valeurs qui ont du sens pour l'utilisateur du système. Pourquoi utiliser 1,2,3 alors que vous pourriez utiliser L,C,H où L,H et C représentent la vie, la voiture et l'habitation dans un contexte d'assurance « Type de police », ou, en revenant à l'exemple du NIV, que diriez-vous d'utiliser « À " pour Toyota ? Toutes les voitures Toyata ont un VIN qui commence par "TO". C'est une chose de moins à retenir pour les utilisateurs, les rend moins susceptibles d'introduire des erreurs de programmation et d'utilisateur et peut même être un substitut utilisable pour une description complète dans les rapports de gestion, ce qui simplifie les rapports. à écrire et peut-être plus rapide à générer.

Un développement ultérieur de ceci est probablement "un pont trop loin" et je ne le recommande généralement pas, mais je l'inclus par souci d'exhaustivité et vous pouvez en trouver une bonne utilisation. C'est-à-dire, utilisez la description comme clé primaire. Pour les données qui changent rapidement, c'est une abomination. Pour très données statiques qui sont rapportées sur Tout le temps, peut être pas. Il suffit de le mentionner pour qu'il reste là comme une possibilité.

J'utilise les PK AutoInc, j'engage simplement mon cerveau et je cherche d'abord de meilleures alternatives. L'art de la conception de bases de données consiste à créer quelque chose de significatif qui peut être interrogé rapidement. Avoir trop de jointures empêche cela.

EDIT Un autre cas crucial où vous n'avez pas besoin d'une PK générée automatiquement est le cas des tables qui représentent l'intersection de deux autres tables. Pour rester dans l'analogie avec la voiture, une voiture a 0..n accessoires, chaque accessoire peut être trouvé sur de nombreuses voitures. Donc, pour représenter cela, vous créez une table Car_Accessory contenant les PK de Car et Accessory et d'autres informations pertinentes sur le lien Dates, etc.

Ce dont vous n'avez pas (généralement) besoin, c'est d'un AutoInc PK sur cette table - il ne sera accessible que via la voiture "dites-moi quels accessoires sont sur cette voiture" ou à partir de l'accessoire "dites-leur quelles voitures ont cet accessoire"

De nombreuses tables ont déjà un identifiant unique naturel. N'ajoutez pas d'autre colonne d'identifiant unique (auto-incrémentation ou autre) sur ces tables. Utilisez plutôt l'identifiant unique naturel. Si vous ajoutez un autre identifiant unique, vous avez essentiellement une redondance (duplication ou dépendance) dans vos données. Cela va à l'encontre des principes de normalisation. Un identifiant unique dépend de l'autre pour la précision. Cela signifie qu'ils doivent être parfaitement synchronisés à chaque fois dans chaque système qui gère ces lignes. C'est juste une autre fragilité dans l'intégrité de vos données que vous ne voulez pas vraiment avoir à gérer et valider à long terme.

De nos jours, la plupart des tables n'ont pas vraiment besoin de l'amélioration des performances très mineure qu'une colonne d'identifiant unique supplémentaire donnerait (et parfois cela nuit même aux performances). En règle générale en informatique, évitez les redondances comme les la peste! Résistez-lui partout où il vous est suggéré. C'est l'anathème. Et tenez compte de la citation. Tout devrait être aussi simple que possible, mais pas plus simple. N'ayez pas deux identifiants uniques où un seul suffira, même si le naturel semble moins bien rangé.

Sur les systèmes plus importants, l'ID est un booster de cohérence, utilisez-le presque partout. Dans ce contexte, les clés primaires individuelles ne sont PAS recommandées, elles sont chères en fin de compte (lisez pourquoi).

Chaque règle a une exception, vous n'aurez donc peut-être pas besoin d'un ID d'auto-incrémentation d'entier sur les tables intermédiaires utilisées pour l'exportation/importation et sur les tables à sens unique ou les tables temporaires similaires. Vous préféreriez également les GUID au lieu des ID sur les systèmes distribués.

De nombreuses réponses ici suggèrent que la clé unique existante devrait être prise. Et bien même s'il a 150 caractères ? Je ne pense pas.

Maintenant mon point principal :

Il semble que les opposants à l'ID entier à incrémentation automatique parlent de petites bases de données contenant jusqu'à 20 tables. Là, ils peuvent se permettre une approche individuelle à chaque table.

MAIS une fois que vous avez un ERP avec plus de 400 tables, ayant un ID d'auto-incrémentation entier n'importe où (sauf cas mentionnés ci-dessus) a tout simplement beaucoup de sens. Vous ne comptez pas sur d'autres champs uniques même s'ils sont présents et sécurisés pour l'unicité.

  • Vous bénéficiez d'une convention universelle qui vous fait gagner du temps, de l'effort et est facile à mémoriser.
  • Dans la plupart des cas, vous JOIGNEZ des tables, sans avoir besoin de vérifier quelles sont les clés.
  • Vous pouvez avoir des routines de code universelles fonctionnant avec votre colonne d'auto-incrémentation d'entiers.
  • Vous pouvez étendre votre système avec de nouvelles tables ou des plugins utilisateur non prévus auparavant en vous référant simplement aux ID des tables existantes. Ils sont déjà là depuis le début, aucun frais pour les ajouter en plus.

Sur les systèmes plus importants, il peut être utile d'ignorer les avantages mineurs de ces clés primaires individuelles et d'utiliser systématiquement l'ID d'auto-incrémentation entière dans la plupart des cas. L'utilisation de champs uniques existants comme clés primaires permet peut-être d'économiser quelques octets par enregistrement, mais un temps de stockage ou d'indexation supplémentaire pose pas de problème dans les moteurs de bases de données d'aujourd'hui. En fait, vous perdez beaucoup plus d'argent et de ressources sur le temps perdu des développeurs/mainteneurs. Le logiciel d'aujourd'hui doit être optimisé pour le temps et les efforts des programmeurs – quelle approche avec des ID cohérents est bien meilleure.

Ce n'est pas une bonne pratique pour les conceptions superflues. C'est à dire. - ce n'est pas une bonne pratique d'avoir toujours une clé primaire d'incrémentation automatique quand on n'en a pas besoin.

Voyons un exemple où l'on n'en a pas besoin.

Vous avez une table pour les articles - elle a une clé primaire int identifiant , et une colonne varchar nommée Titre .

Vous avez également une table pleine de catégories d'articles - clé primaire id int, nom varchar .

Une ligne du tableau Articles a un identifiant de 5, et un Titre "Comment faire cuire l'oie avec du beurre". Vous souhaitez lier cet article aux lignes suivantes de votre tableau Catégories : "Fowl" (identifiant: 20), "Oie" (identifiant: 12), "Cuisine" (identifiant: 2), "Beurre" (id: 9).

Maintenant, vous avez 2 tableaux : articles et catégories. Comment créez-vous la relation entre les deux ?

Vous pourriez avoir une table avec 3 colonnes : id (clé primaire), article_id (clé étrangère), category_id (clé étrangère). Mais maintenant vous avez quelque chose comme :

Une meilleure solution est d'avoir une clé primaire composée de 2 colonnes.

Ceci peut être accompli en faisant :

Une autre raison de ne pas utiliser un entier à incrémentation automatique est si vous utilisez des UUID pour votre clé primaire.

Les UUID sont par définition uniques, ce qui accomplit la même chose que l'utilisation d'entiers uniques. Ils ont également leurs propres avantages (et inconvénients) par rapport aux nombres entiers. Par exemple, avec un UUID, vous savez que la chaîne unique à laquelle vous faites référence pointe vers un enregistrement de données particulier, ce qui est utile dans les cas où vous n'avez pas 1 base de données centrale, ou lorsque les applications ont la possibilité de créer des enregistrements de données hors ligne ( puis les télécharger dans la base de données à une date ultérieure).

En fin de compte, vous ne devez pas considérer les clés primaires comme une chose. Vous devez les considérer comme la fonction qu'ils remplissent. Pourquoi avez-vous besoin de clés primaires ? Être capable d'identifier de manière unique des ensembles de données spécifiques à partir d'une table à l'aide d'un champ qui ne sera pas modifié à l'avenir. Avez-vous besoin d'une colonne particulière appelée id pour ce faire, ou pouvez-vous baser cette identification unique sur d'autres données (immuables) ?

Ou existe-t-il des scénarios dans lesquels vous ne souhaitez pas ajouter un tel champ ?

Tout d'abord, il existe des bases de données qui n'ont pas d'auto-incréments (par exemple, Oracle, qui n'est certainement pas l'un des plus petits concurrents). Cela devrait être une première indication que tout le monde ne les aime pas ou n'en a pas besoin.

Plus important encore, pensez à ce que l'ID fait réellement est - c'est une clé primaire pour vos données. Si vous avez une table avec une clé primaire différente, vous n'avez pas besoin d'ID et ne devriez pas en avoir. Par exemple, une table (EMPLOYEE_ID, TEAM_ID) (où chaque employé peut être dans plusieurs équipes simultanément) a une clé primaire clairement définie constituée de ces deux ID. L'ajout d'une colonne d'ID d'auto-incrémentation, qui est également une clé primaire pour cette table, n'aurait aucun sens. Maintenant, vous trimballez 2 clés primaires, et le premier mot de "clé primaire" devrait vous donner un indice que vous ne devriez vraiment en avoir qu'une.

J'utilise généralement une colonne "identité" (entier auto-incrémenté) lors de la définition de nouvelles tables pour les données "de longue durée" (enregistrements que je prévois d'insérer une fois et de conserver indéfiniment même s'ils finissent par être "logiquement supprimés" en définissant un champ de bits ).

Il y a quelques situations auxquelles je peux penser lorsque vous ne voulez pas les utiliser, dont la plupart se résument à des scénarios où une table sur une instance de la base de données ne peut pas être la source faisant autorité pour les nouvelles valeurs d'ID :

  • Lorsque les identifiants incrémentiels seraient trop d'informations pour un attaquant potentiel. L'utilisation d'une colonne d'identité pour les services de données « publics » vous rend vulnérable au « problème des chars allemands » si l'ID d'enregistrement 10234 existe, il va de soi que l'enregistrement 10233, 10232, etc. existe, jusqu'à au moins l'enregistrement 10001, et il est alors facile de vérifier les enregistrements 1001, 101 et 1 pour déterminer où a commencé votre colonne d'identité. Les GUID V4 composés principalement de données aléatoires cassent ce comportement incrémentiel par conception, de sorte que juste parce qu'un GUID existe, un GUID créé en incrémentant ou décrémentant un octet du GUID n'existe pas nécessairement, ce qui rend plus difficile pour un attaquant d'utiliser un service prévu pour la récupération d'un seul enregistrement en tant qu'outil de vidage. Il existe d'autres mesures de sécurité qui peuvent mieux restreindre l'accès, mais cela aide.
  • Dans les tableaux de concordance M:M. Celui-ci est une sorte de cadeau mais je l'ai déjà vu faire. Si vous avez une relation plusieurs-à-plusieurs entre deux tables de votre base de données, la solution idéale est une table de références croisées contenant des colonnes de clé étrangère référençant le PK de chaque table. Le PK de cette table doit pratiquement toujours être une clé composée des deux clés étrangères, pour obtenir le comportement de l'index intégré et garantir l'unicité des références.
  • Lorsque vous prévoyez d'insérer et de supprimer en masse sur cette table, beaucoup. Le plus gros inconvénient des colonnes d'identité est probablement le battage supplémentaire que vous devez traverser lors de l'insertion de lignes à partir d'une autre table ou requête, où vous souhaitez conserver les valeurs clés de la table d'origine. Vous devez activer "l'insertion d'identité" (cependant cela est fait dans votre SGBD), puis vous assurer manuellement que les clés que vous insérez sont uniques, puis lorsque vous avez terminé l'importation, vous devez définir le compteur d'identité dans le métadonnées de la table à la valeur maximale présente. Si cette opération se produit souvent sur cette table, envisagez un autre schéma PK.
  • Pour les tables distribuées. Les colonnes d'identité fonctionnent parfaitement pour les bases de données à instance unique, les paires de basculement et d'autres scénarios dans lesquels une instance de base de données est la seule autorité sur l'ensemble du schéma de données à un moment donné. Cependant, il n'y a que si grand que vous pouvez aller et toujours avoir un ordinateur assez rapide. La réplication ou l'envoi du journal des transactions peut vous fournir des copies supplémentaires en lecture seule, mais il existe également une limite à l'échelle de cette solution. Tôt ou tard, vous aurez besoin de deux instances de serveur ou plus pour gérer les insertions de données, puis se synchroniser les unes avec les autres. Lorsque cette situation se présente, vous aurez besoin d'un champ GUID au lieu d'un champ incrémentiel, car la plupart des SGBD sont préconfigurés pour utiliser une partie des GUID qu'ils génèrent en tant qu'identifiant spécifique à l'instance, puis générez le reste de l'identifiant de manière aléatoire. ou de manière incrémentale. Dans les deux cas, les chances d'une collision entre deux générateurs de GUID sont nulles, tandis qu'une colonne d'entiers d'identité est un cauchemar à gérer dans cette situation (vous pouvez aller à pair/impair en décalant les graines et en définissant l'incrément à 2, mais si un serveur voit plus d'activité que l'autre, vous gaspillez des identifiants).
  • Lorsque vous devez appliquer l'unicité sur plusieurs tables de la base de données. Il est courant dans les systèmes comptables, par exemple, de gérer le grand livre (avec une ligne pour chaque crédit ou débit de chaque compte qui s'est produit, donc il devient très volumineux très rapidement) comme une séquence de tableaux représentant chacun un mois civil/ an. Des vues peuvent ensuite être créées pour les relier entre elles pour la création de rapports. Logiquement, il s'agit d'une très grande table, mais la découper facilite les tâches de maintenance de la base de données. Cependant, cela pose le problème de la gestion des insertions dans plusieurs tables (vous permettant de commencer à enregistrer les transactions le mois suivant tout en fermant la dernière) sans vous retrouver avec des clés en double. Encore une fois, les GUID au lieu des colonnes d'entiers d'identité sont la solution idéale, car le SGBD est conçu pour les générer de manière vraiment unique, de sorte qu'une seule valeur GUID ne sera vue qu'une seule fois dans l'ensemble du SGBD.

Il existe des solutions de contournement qui permettent l'utilisation de colonnes d'identité dans ces situations, comme je l'ai mentionné, espérons-le, mais dans la plupart d'entre elles, la mise à niveau de la colonne d'entier d'identité vers un GUID est plus simple et résout le problème plus complètement.

Une clé primaire auto-incrémentée (d'identité) est une bonne idée, sauf pour noter qu'elle n'a pas de sens en dehors du contexte de la base de données et des clients immédiats de cette base de données. Par exemple, si vous transférez et stockez certaines des données dans une autre base de données, puis procédez à l'écriture de données différentes dans les deux tables de base de données, les identifiants divergeront - c'est-à-dire que les données avec un identifiant de 42 dans une base de données ne correspondront pas nécessairement aux données avec un identifiant de 42 dans l'autre.

Compte tenu de cela, s'il est nécessaire de toujours pouvoir identifier les lignes de manière unique en dehors de la base de données (et c'est souvent le cas), vous devez alors disposer d'une clé différente à cet effet. Une clé commerciale soigneusement sélectionnée fera l'affaire, mais vous vous retrouverez souvent dans une position d'un grand nombre de colonnes nécessaires pour garantir l'unicité. Une autre technique consiste à avoir une colonne Id en tant que clé primaire groupée à incrémentation automatique et une autre colonne uniqueidentifier (guid) en tant que clé unique non groupée, dans le but d'identifier de manière unique la ligne partout où elle existe dans le monde. La raison pour laquelle vous avez toujours une clé auto-incrémentée dans ce cas est qu'il est plus efficace de regrouper et d'indexer la clé auto-incrémentée que de faire la même chose avec un guid.

Un cas où vous ne voudriez peut-être pas de clé à incrémentation automatique serait une table plusieurs-à-plusieurs où la clé primaire est un composé des colonnes Id de deux autres tables (vous pouvez toujours avoir une clé à incrémentation automatique ici, mais je n'en vois pas l'intérêt).

Une autre question est le type de données de la clé auto-incrémentée. L'utilisation d'un Int32 vous donne une plage de valeurs large, mais relativement limitée. Personnellement, j'utilise fréquemment des colonnes bigint pour l'ID, afin de n'avoir pratiquement jamais à craindre de manquer de valeurs.

Comme d'autres personnes ont plaidé en faveur d'une clé primaire incrémentielle, j'en ferai une pour un GUID :

  • Il est garanti d'être unique
  • Vous pouvez avoir un voyage de moins vers la base de données pour les données de votre application. (Pour une table de types par exemple, vous pouvez stocker le GUID dans l'application et l'utiliser pour récupérer l'enregistrement. Si vous utilisez une identité, vous devez interroger la base de données par nom et j'ai vu de nombreuses applications qui le font pour obtenir le PK et l'interroge à nouveau pour obtenir tous les détails).
  • Il est utile pour masquer des données. www.domain.com/Article/2 Me fait savoir que vous n'avez que deux articles alors que www.domain.com/article/b08a91c5-67fc-449f-8a50-ffdf2403444a ne me dit rien.
  • Vous pouvez facilement fusionner des enregistrements de différentes bases de données.
  • MSFT utilise des GUIDS pour l'identité.

En tant que principe de bonne conception, chaque table doit disposer d'un moyen fiable d'identifier une ligne de manière unique. Bien que ce soit à quoi sert une clé primaire, elle ne nécessite pas toujours l'existence d'une clé primaire. L'ajout d'une clé primaire à chaque table n'est pas une mauvaise pratique car elle permet une identification de ligne unique, mais cela peut être inutile.

Pour maintenir des relations fiables entre les lignes de deux ou plusieurs tables, vous devez le faire via des clés étrangères, d'où la nécessité de clés primaires dans au moins certaines tables. L'ajout d'une clé primaire à chaque table facilite l'extension de la conception de votre base de données lorsque vient le temps d'ajouter de nouvelles tables ou relations aux données existantes. Planifier à l'avance est toujours une bonne chose.

En tant que principe de base (règle dure peut-être), la valeur d'une clé primaire ne doit jamais changer pendant toute la durée de vie de sa ligne. Il est sage de supposer que toutes les données commerciales d'une ligne sont susceptibles de changer au cours de leur durée de vie, de sorte que toutes les données commerciales seront un mauvais candidat pour une clé primaire. C'est pourquoi quelque chose d'abstrait comme un entier auto-incrémenté est souvent une bonne idée. Cependant, les entiers auto-incrémentés ont leurs limites.

Si vos données n'auront une vie que dans votre base de données, les entiers auto-incrémentés conviennent. Mais, comme cela a été mentionné dans d'autres réponses, si jamais vous souhaitez que vos données soient partagées, synchronisées ou aient une vie en dehors de votre base de données, les entiers auto-incrémentés font de mauvaises clés primaires. Un meilleur choix sera un guid (alias uuid "identifiant universellement unique").

La question, et de nombreuses réponses, passent à côté du point important que toutes les clés naturelles de chaque table résident uniquement dans le schéma logique pour la base de données, et toutes les clés de substitution pour chaque table résident uniquement dans le schéma physique pour la base de données. d'autres réponses traitent uniquement des avantages relatifs des clés de substitution entières par rapport aux clés de substitution GUID, sans expliquer les raisons pour lesquelles les clés de substitution sont correctement utilisées et quand.

BTW : Évitons d'utiliser le terme mal défini et imprécis clé primaire. Il s'agit d'un artefact de modèles de données pré-relationnels qui a d'abord été coopté (imprudemment) dans le modèle relationnel, puis réintégré dans le domaine physique par divers fournisseurs de SGBDR. Son utilisation ne sert qu'à brouiller la sémantique.

Remarque de la modèle relationnel que, pour que la base de données schéma logique en être première forme normale, chaque table doit avoir un ensemble de champs visible par l'utilisateur, appelé clé naturelle, qui identifie de manière unique chaque ligne du tableau. Dans la plupart des cas, une telle clé naturelle est facilement identifiée, mais à l'occasion, elle doit être construite, que ce soit en tant que tie break champ ou autre. Cependant, une telle clé construite est toujours visible par l'utilisateur et réside donc toujours dans le schéma logique de la base de données.

En revanche tout Clé de substitution sur une table réside purement dans le schéma physique pour la base de données (et doit donc toujours, à la fois pour des raisons de sécurité et pour le maintien de l'intégrité de la base de données, être entièrement invisible pour les utilisateurs de la base de données). La seule raison de l'introduction d'un Clé de substitution est de résoudre les problèmes de performance dans le entretien physique et utilisation de la base de données, qu'il s'agisse de jointures, de réplication, de plusieurs sources matérielles de données ou autres.

Puisque la seule raison de l'introduction d'une clé de substitution est la performance, supposons que nous souhaitons qu'elle soit performante. Si le problème de performances en question est lié aux jointures, nous souhaitons nécessairement rendre notre clé de substitution aussi étroite que possible (sans gêner le matériel, de sorte que les entiers et les octets courts sont généralement supprimés). Les performances de jointure reposent sur une hauteur d'index minimale, un entier de 4 octets est donc une solution naturelle. Si votre problème de performances est le taux d'insertion, un entier de 4 octets peut également être une solution naturelle (en fonction des composants internes de votre SGBDR). Si votre problème de performances pour une table est la réplication ou plusieurs sources de données que d'autres Clé de substitution la technologie, qu'il s'agisse d'un GUID ou d'une clé en deux parties (ID d'hôte + entier) peut être plus appropriée. Personnellement, je ne suis pas un favori des GUID, mais ils sont pratiques.

En résumé, toutes les tables ne nécessitent pas un Clé de substitution (de quelque type que ce soit) ils ne doivent être utilisés que lorsqu'ils sont jugés nécessaires pour l'exécution de la table considérée. Quelle que soit la commune Clé de substitution technologie que vous préférez, réfléchissez bien aux besoins réels de la table avant de faire un choix en changeant le Clé de substitution Le choix technologique pour une table sera un travail épuisant. Documentez la mesure de performance clé de votre table afin que vos successeurs comprennent les choix effectués.

Cas spéciaux

Si vos exigences commerciales imposent une numérotation séquentielle des transactions à des fins d'audit (ou à d'autres fins), ce champ est ne pas une clé de substitution c'est un clé naturelle (avec des exigences supplémentaires). D'après la documentation, un entier auto-incrémenté ne génère que clés de substitution, alors trouvez un autre mécanisme pour le générer. Évidemment, une sorte de moniteur sera nécessaire, et si vous recherchez vos transactions à partir de plusieurs sites, un site sera spécial, by virtue of being the designated host site for the monitor.

If your table will never be more than about a hundred rows then index height is irrelevant every access will be by a table scan. However string comparisons on long strings will still be much more expensive than comparison of a 4-byte integer, and more expensive than comparison of a GUID.

A table of code values keyed by a char(4) code field should be as performant as one with a 4-byte integer. Although I have no proof of this I use the assumption frequently and have never had reason to rue it.


Creating a table with auto-incrementing IDs in a SQL query

If you’re starting from scratch, you’ll need to create a table in your database that’s set up to auto-increment its primary keys.

➞ PostgreSQL

When creating an auto-incremented primary key in Postgres, you’ll need to use SERIAL to generate sequential unique IDs. Default start and increment are set to 1.

When applied to our example inventory data set, table creation looks like:

This first step is pretty straightforward. Just be sure to mark your item number column as the PRIMARY KEY .

Auto-incrementing in MySQL is pretty similar to SQL Server, except you don’t manually include the starting value and integer value. Instead, you use the AUTO_INCREMENT keyword, which has a default start and increment value of 1.

The basic syntax for creating this table in MySQL is:

In our example, here’s the table we’d want to create:

Like Postgres, you need to make sure that you’re using the PRIMARY KEY keyword for the column you want to generate your unique IDs from.

➞ SQL Server

In SQL Server, you’ll use the IDENTITY keyword to set your primary key (or item_number in our use case). By default, the starting value of IDENTITY is 1, and it will increment by 1 with each new entry unless you tell it otherwise.

To start, create a table. The basic syntax:

When applied to our inventory test case, table creation will look like:

Again—one last time—make sure to include PRIMARY KEY next to the SERIAL keyword, so you’re not just generating a useless list of sequential numbers.

Now, once you’ve created the framework of your table, you’ll need to decide if the default starting and increment values make sense for your use case.

Subscribe to the Retool monthly newsletter
Once a month we send out top stories (like this one) along with Retool tutorials, templates, and product releases.


6 Answers 6

You could use a CAML query and sort by the particular field, grab the highest value and add one. Should probably have a distinct check as well.

The query can be something like this :

I don't think your approach or the idea of performing a CAML query would work (. at least not consistently), primarily due to your inability to natively manage concurrency. It would be challenging enough to handle it in a single WFE environment, but if you have multiple WFEs you would most assuredly have multiple instances of an event receiver or query executing at the same time, returning the same "last ID" value and then all setting their LogIDNumber property to the same last+1 value.

I suppose you could create an ID list with one column (LogIDNumber), make it a Number type, and make sure Enforce unique values = Yes. You can then add an item to that list in your event receiver and if it chokes then you know another EV instance got there first and you need to requery the last ID until the insert into the ID list doesn't choke. If it doesn't choke then your EV instance owns the ID and can safely update the LogIDNumber property for that list item.

Can I ask what requirement(s) are causing you to create your own auto-icrement column versus using ID?


I had a similar issue, I solved it and since this comes up high on Google for what I was looking for it may help others.

I migrated several Wordpress databases from AWS RDS MySQL to MySQL running on an EC2 instance, using the database migration service. What I didn't know is it doesn't copy indexes, keys, auto increment, or really anything other than the basics. Of course the best approach would be to dump the database using mysqldump and import it manually, but one Wordpress install had significant changes and I didn't want to redo them. Instead I manually recreated the auto_increment values and indexes.

I've documented how I fixed Wordpress auto increment here on my website, here's a copy of what worked for me. It's possible I'll make further changes, I'll update the website but I may not remember to update this question.

  • You should check your tables and make sure to set your auto_increment to a value that makes sense for that table.
  • If you get the error “alter table causes auto_increment resequencing resulting in duplicate entry 1” (or 0, or something else). This is usually fixed by deleting the entry with the ID 0 or 1 in the table. Note that you should be careful doing this as it could delete an important row.

Why did this happen? Here's what went wrong for me:

If you exported your database using phpadmin and had an error on reimporting it, the code that adds the primary key doesn't run because it's at the end of the SQL file, not at its creation.

Before I figured this out, I updated to the phpmyadmin 5 beta and it imported the files with the key even though I still had the error.

Lesson one is, don't let your import crash, even if your tables are there. Mine crashed on table that began with wp_w so it came after user and rekt my auto increments.

If you look at the bottom of your SQL export, you will find the alter table for adding the Primary Key and the auto increment.

You don't need to specify the auto increment it automatically knows what the next increment is like so:

If you had admin activity since this happened, you have zeros in your key field, which will not allow you to set a primary key, and without that, you can't auto increment. So you need to run a delete script vs each table like so:

Here's a complete set of updates If your table has these, it will throw and error.


4 réponses 4

Tim, I had faced the same issue where I needed to restart the identity to the next value. I was using db2v9.1.

Unfortunately, there is no way to specify the next value automatically. As per DB2 documentation the value should be a 'numeric constant'. Hence I had to do a select max(id), get the value and replace it in the alter..restart stmt manually.

I don't remember if I tried this - but you can write an sp where max(id) is set in a variable and assign the variable in the alter. restart stmt. (I am unable to try as I dont hav access to any db2 database anymore). I doubt it'll work though. (If it works do let me know :))

DB2 reference:

RESTART or RESTART WITH numeric-constant

Resets the state of the sequence associated with the identity column. If WITH numeric-constant is not specified, the sequence for the identity column is restarted at the value that was specified, either implicitly or explicitly, as the starting value when the identity column was originally created. The column must exist in the specified table (SQLSTATE 42703), and must already be defined with the IDENTITY attribute (SQLSTATE 42837). RESTART does not change the original START WITH value.

The numeric-constant is an exact numeric constant that can be any positive or negative value that could be assigned to this column (SQLSTATE 42815), without non-zero digits existing to the right of the decimal point (SQLSTATE 428FA). The numeric-constant will be used as the next value for the column.


Frequently, we happen to need to fill tables with unique identifiers. Naturally, the first example of such identifiers is PRIMARY KEY data. These are usually integer values hidden from the user since their specific values are unimportant.

When adding a row to a table, you need to take this new key value from somewhere. You can set up your own process of generating a new identifier, but MySQL comes to the aid of the user with the AUTO_INCREMENT column setting. It is set as a column attribute and allows you to generate unique integer identifiers. As an example, consider the users table, the primary key includes an identifiant column of type INT:

Inserting a NULL value into the identifiant field leads to the generation of a unique value inserting 0 value is also possible unless the NO_AUTO_VALUE_ON_ZERO Server SQL Mode is enabled::

It is possible to omit the identifiant column. The same result is obtained with:

The selection will provide the following result:

Select from users table shown in dbForge Studio

You can get the automatically generated value using the LAST_INSERT_ID() session function. This value can be used to insert a new row into a related table.

There are aspects to consider when using AUTO_INCREMENT, here are some:

  • In the case of rollback of a data insertion transaction, no data will be added to a table. However, the AUTO_INCREMENT counter will increase, and the next time you insert a row in the table, holes will appear in the table.
  • In the case of multiple data inserts with a single INSERT command, the LAST_INSERT_ID() function will return an automatically generated value for the first row.
  • The problem with the AUTO_INCREMENT counter value is described in Bug #199 – Innodb autoincrement stats los on restart.

For example, let’s consider several cases of using AUTO_INCREMENT for table1 :

Noter: The next AUTO_INCREMENT value for the table can be parsed from the SHOW CREATE TABLE result or read from the AUTO_INCREMENT field of the INFORMATION_SCHEMA TABLES table.

The rarer case is when the primary key is surrogate — it consists of two columns. le MyISAM engine has an interesting solution that provides the possibility of generating values for such keys. Let’s consider the example:

It is quite a convenient solution:

Special values auto generation

The possibilities of the AUTO_INCREMENT attribute are limited because it can be used only for generating simple integer values. But what about complex identifier values? For example, depending on the date/time or [A0001, A0002, B0150…]). To be sure, such values should not be used in primary keys, but they might be used for some auxiliary identifiers.

The generation of such unique values can be automated, but it will be necessary to write code for such purposes. We can use the BEFORE INSERT trigger to perform the actions we need.

Let’s consider a simple example. Nous avons le sensors table for sensors registration. Each sensor in the table has its own name, location, and type: 1 –analog, 2 –discrete, 3 –valve. Moreover, each sensor should be marked with a unique label like [symbolic representation of the sensor type + a unique 4-digit number] where the symbolic representation corresponds to such values [AN, DS, VL].

In our case, it is necessary to form values like these [DS0001, DS0002…] and insert them into the étiqueter column.

When the trigger is executed, it is necessary to understand if any sensors of this type exist in the table. It is enough to assign number “1” to the first sensor of a certain type when it is added to the table.

In case such sensors already exist, it is necessary to find the maximum value of the identifier in this group and form a new one by incrementing the value by 1. Naturally, it is necessary to take into account that the label should start with the desired symbol and the number should be 4-digit.


3 réponses 3

Why are you creating something that SharePoint already does?

You can use the SharePoint default column ID in Workflows (as mentioned in the comments of the blogpost you refer to)

ID gets assigned après a New Item is created, so you can not use it in Calculated Column Formulas.

But Workflows are executed after the List Item is created so you can use ID in your workflow.

Only drawback might be, ID can not easily be reset, it will always increment

My new workflow is here here is working perfectly for me.

Event Handler approach can be used also for Autonumbering if you are in programming but I haven't tested it!

I'm trying to think of an alternate solution, but it seems you'll need to use a set of If conditions in the solution - that's if you want the preceding 000 prior to the ID value.

The workflow checks if the ID or the Next Number variable is within a certain range, and then append CaseOPT and the correct number of zeroes prior to the ID value.

Edit: The workflow would look something like this:

This is using the format "CaseOPT####" as the unique id.

I've arranged it this way assuming most of your entries will be in the 1000 - 100 range. Rearrange it depending on how much items you expect and how fast your list grows.


1 Answer 1

I read that uuid does not bring any security advantages

This entirely relative to a given context. So it's neither true or false.

Consider that right now the session id is encrypting the auto-increment id (no uuid is used). If someone manages to know how the session is encrypted, then he can impersonate all the users: encrypt "1" and set the value as sessionID, encrypts "2" and set the value as sessionID, etc.

Session identifiers work if they're long random pieces of information. They do not encode or encrypt any information, these tokens are used by the server to locate information pertaining the established session.

In a typical scenario, client A connects to server B for the first time. They have no information or session id at this point. Server generates a new session id and sends it to client. Potentially authentication occurs and some data is stored on the server pertaining that particular session. Every subsequent request from the client carries this identifier so that the server can match the data relevant to that particular client during this particular session. Notice the data is stored on the server, all the client does is issue requests of whatever kind and tack on the session identifier as a way to maintain state in a stateless system.

Simultaneously other clients are doing the same. The server can maintain multiple states since every client uses their own unique session identifier. If the sessions weren't random or easily guessable, then an attacker could calculate or guess them and hijack established sessions.

So a randomly generated UUID is no better or worse than a randomly generated session identifier for the same length of random data.


Is it good practice to keep 2 related tables (using auto_increment PK) to have the same Max of auto_increment ID when table1 got modified?

This question is about good design practice in programming.

Let see this example, we have 2 interrelated tables:

rID is auto_increment primary key & textID is foreign key

The relationship is that 1 rID will have 1 and only 1 textID but 1 textID can have a few rID .

So, when table1 got modification then table2 should be updated accordingly.

Ok, here is a fictitious example. You build a very complicated system. When you modify 1 record in table1, you need to keep track of the related record in table2. To keep track, you can do like this:

Option 1: When you modify a record in table1, you will try to modify a related record in table 2. This could be quite hard in term of programming expecially for a very very complicated system.

Option 2: instead of modifying a related record in table2, you decided to delete old record in table 2 & insert new one. This is easier for you to program.

For example, suppose you are using option2, then when you modify record 1,2,3. 100 in table1, the table2 will look like this:

This means the Max of auto_increment IDs in table1 is still the same (100) but the Max of auto_increment IDs in table2 already reached 200.

what if the user modify many times? if they do then the table2 may run out of records? we can use BigInt but that make the app run slower?

Note: If you spend time to program to modify records in table2 when table1 got modified then it will be very hard & thus it will be error prone. But if you just clear the old record & insert new records into table2 then it is much easy to program & thus your program is simpler & less error prone.

So, is it good practice to keep 2 related tables (using auto_increment PK) to have the same Max of auto_increment ID when table1 got modified?


Voir la vidéo: QGIS - USE IF STATEMENT IN QGIS TO REPLACE ADD VALUES IN FIELD OF ATTRIBUTE TABLE (Octobre 2021).