Identificateurs uniques-encore-simples à l'échelle de la database dans SQL Server

Tout d'abord, je suis au courant de cette question , et la suggestion (en utilisant GUID) ne s'applique pas dans ma situation.

Je veux des UID simples pour que mes users puissent facilement communiquer ces informations par téléphone:

Bonjour, j'ai un problème avec l'ordre 1584

par opposition à

bonjour, j'ai un problème avec l'ordre 4daz33-d4gerz384867-8234878-14

Je veux que ceux-ci soient uniques (database large) parce que j'ai différents types d'objects … il y a des ID de command, des ID de livraison et des ID de facturation et puisqu'il n'y a pas de relation bi-univoque entre ceux-ci, Je n'ai aucun moyen de deviner de quel type d'object un ID fait reference.

Avec des ID uniques à l'échelle de la database, je peux immédiatement dire à quel object mon client fait reference. Mon user peut simplement entrer un identifiant dans un outil de search, et je lui épargne le clic supplémentaire pour affiner ce qu'il cherche.

Mon idée actuelle est d'utiliser des colonnes d'identité avec des graines différentes 1, 2, 3, etc, et une valeur d'incrément de 100.

Cela soulève cependant quelques questions:

  • Et si j'obtenais plus de 100 types d'objects? accordé, je pourrais utiliser 1000 ou 10000, mais quelque chose qui ne va pas bien "sent"

  • Est-il possible que la graine soit "perdue" (lors d'une réplication, d'un problème de database, etc.?)

  • Plus généralement, y a-t-il d'autres problèmes que je devrais connaître?

  • est-il possible d'utiliser un non entier (j'utilise actuellement bigints) comme une colonne d'identité, de sorte que je puisse préfixer l'ID avec quelque chose représentant le type d'object? (par exemple une colonne varchar)

  • Serait-ce une bonne idée d'utiliser une "table maîtresse" contenant seulement une colonne d'identité, et peut-être le type d'object, de sorte que je puisse simplement insert une ligne à chaque fois que j'ai besoin d'une nouvelle idée. Je pense que cela pourrait être un peu exagéré, et j'ai peur que cela complique toutes mes requests d'insertion. Plus le fait que je ne serai pas en mesure de déterminer un type d'object sans regarder la database

  • Y a-t-il d'autres façons intelligentes d'aborder mon problème?

Pourquoi ne pas utiliser les identités sur toutes les tables, mais à chaque fois que vous les présentez à l'user, il suffit de cliquer sur un seul caractère pour le type? par exemple O1234 est une command, D123213 est une livraison, etc.? De cette façon, vous n'avez pas à concevoir un plan fou …

Manipulez-le à l'interface user – ajoutez une lettre préfixée (ou des lettres) sur le numéro d'identification lorsque vous le signalez aux users. Donc, o472 serait un ordre, b531 serait un projet de loi, et ainsi de suite. Les gens sont assez à l'aise de mélanger des lettres et des numbers lorsqu'ils donnent des «numéros» au téléphone, et sont plus précis qu'avec des numbers droits.

Vous pouvez utiliser une colonne autoincrement pour générer l'identifiant unique. Ensuite, ayez une colonne calculée qui prend la valeur de cette colonne et la rajoute avec un identificateur fixe qui reflète le type d'entité, par exemple OR1542 et DL1542, qui représentera l'ordre # 1542 et la livraison # 1542, respectivement. Votre préfixe peut être étendu autant que vous le souhaitez et le format peut être arrangé pour aider à distinguer entre les éléments ayant la même valeur d'auto-incrémentation, par exemple OR011542 et DL021542, les préfixes étant OR01 et DL02.

Je mettrais en œuvre en définissant une table racine générique. En l'absence d'un meilleur nom, appelez-le Entity. La table Entity doit contenir au less une seule colonne Identity. Vous pouvez également inclure d'autres champs communs à tous vos objects ou même des méta-données qui vous indiquent que cette ligne est un ordre par exemple.

Chacune de vos tables Commande, Livraison … aura une reference FK à la table Entité. Cela vous donnera une seule colonne d'identifiant unique

Utiliser les graines à mon avis est une mauvaise idée, et cela pourrait mener à des problèmes.

modifier

Certains des problèmes que vous avez déjà mentionnés. Je vois aussi que c'est une douleur de suivre et de vous assurer de configurer correctement toutes les nouvelles entités. Imaginez un développeur mettant à jour le système dans deux ans.

Après avoir écrit cette réponse, j'avais réfléchi un peu plus à la question de savoir pourquoi vous faisiez cela, et j'en suis arrivé à la même conclusion que Matt.

Le projet de programmation intentionnelle de MS avait un système GUID-to-word qui donnait des noms prononçables à partir des ID randoms

Pourquoi pas une simple représentation Base36 d'un bigint? http://en.wikipedia.org/wiki/Base_36

Nous avons rencontré un problème similaire sur un projet. Nous l'avons résolu en créant d'abord une table simple qui n'a qu'une seule ligne: un set BIGINT comme identité auto-incrémentée. Et nous avons créé un sproc qui insère une nouvelle ligne dans cette table, en utilisant les valeurs par défaut et à l'intérieur d'une transaction. Il stocke ensuite SCOPE_IDENTITY dans une variable, annule la transaction, puis renvoie SCOPE_IDENTITY stockée.

Cela nous donne un identifiant unique dans la database sans remplir une table.

Si vous voulez connaître le type d'object auquel l'ID fait reference, je perds la restauration de la transaction et stocke également le type d'object en regard de l'ID. De cette façon, découvrez quel type d'object auquel l'Id fait reference est seulement un select (ou jointure interne) loin.

J'utilise un algorithm haut / bas pour cela. Je ne peux pas find une description pour cela en ligne. Doit bloguer à ce sujet.

Dans ma database, j'ai une table d'identification avec un champ countur. C'est la partie haute. Dans mon application, j'ai un countur qui va de 0 à 99. C'est la partie basse. La key générée est 100 * haute + basse.

Pour get une key, je fais ce qui suit

 initially high = -1 initially low = 0 method GetNewKey() begin if high = -1 then high = GetNewHighFromDatabase newkey = 100 * high + low. Inc low If low = 100 then low = 0 high = -1 return newKey end 

Le vrai code est plus compliqué avec les verrous etc mais c'est l'essentiel.

Il y a plusieurs façons d'get la valeur élevée de la database, y compris les keys auto inc, les générateurs, etc. La meilleure façon dépend de la database que vous utilisez.

Cet algorithm donne des keys simples tout en évitant le plus souvent le coup de db de searchr une nouvelle key à chaque fois. Lors des tests, j'ai trouvé que les performances étaient similaires à celles des guids et qu'elles offraient des performances nettement meilleures que de récupérer une key auto inc à chaque fois.

Vous pouvez créer une table maître UniqueObject avec votre identité et un champ de sous-type. Les sous-tables (Commandes, Utilisateurs, etc.) auraient un FK à UniqueObject. INSTEAD OF INSERT triggersurs devraient garder la douleur au minimum.

Peut-être une variante itemType-year-week-orderNumberThisWeek?

 o2009-22-93402 

Un tel identifiant peut consister en plusieurs valeurs de colonne de database et être simplement formaté sous la forme d'un identifiant par le logiciel.

J'ai eu une situation similaire avec un projet.

Ma solution: Par défaut, les users ne voient que les 7 premiers caractères du GUID.

Il est suffisamment random que les collisions sont extrêmement improbables (1 sur 268 millions), et il est efficace pour parler et taper.

En interne, bien sûr, j'utilise l'intégralité du GUID.