web-dev-qa-db-fra.com

Création d'une clé primaire secondaire dans une base de données pour certaines tables

À certaines de mes tables, je veux ajouter "second_primary_key" qui sera uuid ou une clé longue aléatoire. J'en ai besoin car pour certaines tables je ne veux pas exposer des entiers à mon application web. Autrement dit, sur une page "/ factures", j'ai une liste de factures et un lien vers "/ factures /: id" où: id est un entier. Je ne veux pas qu'un utilisateur sache combien de factures dans mon système là-bas, donc au lieu de "/ factures/123", je veux utiliser sa "seconde_principale_ clé" pour que l'url soit "/ factures/N_8Zk241vNa"

Il en va de même pour les autres tables où je veux masquer un vrai identifiant.

Je me demande, est-ce une pratique courante? Quelle est la meilleure façon de mettre cela en œuvre?

Et comment s'appelle cette technique après tout, pour que je fasse une recherche dessus?

22
Dari

Vous pouvez ajouter une colonne UUID mais vous n'en avez vraiment pas besoin (et ne devriez pas). Il s'agit d'un problème de couche de présentation. Vous ne rêveriez pas de dire, en stockant une valeur monétaire de 1999 $ ainsi que 1999.

Vous voulez juste un moyen de masquer la valeur à la volée pour l'application. Vous pouvez le faire dans l'application elle-même ou en tant que vue de base de données.

Comme nous ne parlons que d'une seule valeur, regardez peut-être le cryptage bidirectionnel tel que AES ou similaire - le plus léger est le mieux.

Le hachage pourrait être une autre possibilité - cela dépend si vous souhaitez récupérer le numéro de facture, car le hachage est un moyen.

0
Robbie Dee

Avoir une "clé primaire alternative" est un concept bien connu dans la modélisation de bases de données relationnelles, il est appelé "clé alternative", ou parfois aussi "clé secondaire". L'ensemble des "clés primaires potentielles" est appelé "clés candidates". Voir https://beginnersbook.com/2015/04/alternate-key-in-dbms/

La façon dont vous implémentez cela dépend entièrement de vous, surtout si vous souhaitez masquer le nombre total d'enregistrements. Il n'y a pas de "meilleur moyen", vous devez vérifier vos exigences telles que le jeu de caractères autorisé ou utile, la longueur maximale, si vous voulez que les ID soient sensibles à la casse ou non, si vous voulez qu'ils soient lisibles sur une facture imprimée, si quelqu'un doit pouvoir les répéter au téléphone sans erreur, etc.

48
Doc Brown

La plupart des factures ont un numéro de facture qui, selon la plupart des règles comptables, doit être séquentiel ou un comptable peut ne pas approuver les résultats de l'année ou l'IRS (ou similaire dans votre pays) peut souhaiter effectuer un audit complet sur vos onglets.

Un utilisateur peut déduire du numéro de facture le nombre de clients que vous avez servis ou la durée avant de modifier la stratégie de numérotation des factures.

Le nombre de factures stockées dans la base de données n'est pas une mesure du grand total de vos factures. Il existe d'autres moyens de le savoir, notamment en demandant vos rapports annuels à la Chambre de commerce.

Je voudrais cependant verrouiller la facture derrière un écran de connexion utilisateur, afin que tout le monde ne puisse pas la demander. Ensuite, lors de la connexion de l'utilisateur, ils peuvent utiliser une méthodologie ajax pour demander leurs factures en suspens, etc. Cela sécurise vos données, masque l'URL par ajax (personne ne peut généralement être dérangé pour regarder les détails de la façon dont la demande ajax est construite) et vous contrôlez la façon dont les données sont affichées et proposées.

9
Tschallacka

Vous pourrez peut-être utiliser hashids pour cela, il est conçu pour résoudre exactement ce scénario.

Il encodera votre ID de base de données en un hachage court (similaire à l'URL d'une vidéo YouTube), et il ne vous demandera pas d'ajouter de clés secondaires à votre table.

7
mitchdav

Vous pouvez créer une autre clé unique, mais vous ne devriez pas. Pas pour la raison donnée. Il existe des moyens plus simples de masquer les tailles de table.

Stockage N_8Zk241vNa coûte 12 octets par ligne dans le tableau et encore plus dans l'index. C'est assez inutile pour ce dont vous avez besoin.

Le chiffrement de l'entier id ne vous coûte pas d'espace et ne sert à rien pendant l'exécution. La façon dont vous le faites dépend de votre langage de programmation et/ou de votre base de données.

Notez qu'avec AES, vous obtenez un entier de 128 bits, ce qui signifie 22 caractères en base64, probablement plus que vous ne le souhaitez. Un chiffre avec une taille de bloc de 64 comme DES ou 3DES vous donne 11 caractères, comme vous le souhaitez.

Utilisez différentes clés pour différentes tables.

Si tout ce dont vous avez besoin est de masquer les tailles des tables, vous pouvez utiliser une séquence commune pour toutes les tables. Notez qu'il peut s'agir d'un goulot d'étranglement s'il y a des insertions fréquentes dans plusieurs de vos tables. Avec quelque chose comme Hibernate et un algorithme Hi-Lo, ce problème disparaît.

3
maaartinus

Une autre approche pour votre cas d'utilisation particulier est qu'au lieu de modifier la base de données et l'application, vous pouvez simplement créer un itinéraire personnalisé vers les factures afin que/factures /: f (id) où f(id) soit une fonction de l'id.

L'itinéraire personnalisé est chargé de mapper une demande à l'action correcte côté serveur.

0
user260171

C'est une pratique totalement acceptable, également appelée "clé alternative" (AK). Fondamentalement, l'AK est un autre index unique ou une contrainte unique.

Vous pouvez même créer des contraintes de clé étrangère en fonction de votre AK.

Un cas d'utilisation possible est comme ce que vous avez expliqué: vous avez un PK en cluster sur un numéro d'identité en constante augmentation, mais vous ne voulez pas que ce numéro soit affiché ou utilisé comme critère de recherche, car il peut simplement être deviné. Donc, en plus, vous avez un identifiant unique aléatoire ou un numéro de référence en tant qu'AK, et c'est l'ID que vous présentez à l'utilisateur

0
Alex Schievink

Il existe plusieurs types de clés/index. Une clé primaire est un index unique spécial et, comme le disent les réponses, vous pouvez certainement créer une autre clé unique. Et je conviens qu'il est préférable de ne pas exposer les éléments internes de votre base de données à moins qu'il n'y ait une très bonne raison.

Étant donné que la question se situe dans le contexte des factures et des numéros, il pourrait être utile de rechercher à quoi le secteur comptable s'attend à ce que les numéros de facture ressemblent: http://smallbusiness.chron.com/assign-invoice-numbers-52422. html

Il peut sembler compliqué d'avoir un identifiant interne qui est une clé primaire et un autre champ unique avec le numéro de facture visible de l'application/du client. Mais ce n'est pas si sale quand, disons un an plus tard, le client veut adopter un nouveau schéma de numérotation des factures. Dans ce cas, vous ne dérangeriez pas l'identifiant interne et ses relations dans d'autres tableaux pour renuméroter la boule de cire entière. Vous devez conserver votre ID interne tel quel et renuméroter le numéro de facture non interne.

Idéalement, vous vous efforcez de ne pas lier les tables ensemble sur des clés/clés étrangères susceptibles de changer, et de garder vos tables et relations internes transparentes pour la couche d'application.

0
Thomas Carlisle

Fonce.

Ce n'est pas différent d'un champ "slug" que les articles de blog et similaires ont souvent - une façon unique de se référer à l'enregistrement de base de données distinct de la clé primaire, apte à être utilisé dans une URL. Je n'ai jamais entendu personne argumenter contre cela.

0
RemcoGerlich

À mon humble avis, la création de deux clés primaires différentes n'est pas possible. Bien sûr, vous pouvez mettre cet uuid dans une base de données pour l'avoir comme "alias" pour la clé primaire actuelle. Vous pouvez placer un index au-dessus de cette colonne avec une contrainte unique, mais la clé primaire est (par essence) unique dans une seule table. Il peut y avoir une clé primaire composite, mais ce n'est pas ce que vous recherchez.

Je suggère donc de le mettre là, mais de ne l'avoir qu'avec index. Vous pouvez créer un composant de gestion pour interroger les données par PK ainsi que d'autres colonnes uniques. Lorsque vous gérez une demande pour "/ factures/...", vérifiez simplement le paramètre - s'il est entier, recherchez l'ID, sinon recherchez uuid. Ou vous pouvez avoir la recherche uuid comme solution de rechange lorsque la recherche d'ID n'a rien trouvé.

Et à propos de la génération d'uuids "aléatoires": Pourquoi pas quelque chose comme "prendre l'ID, ajouter CONSTANT, convertir en hexadécimal". L'unicité de l'ID fournira l'unicité de l'uuid, le nombre hexadécimal est plus difficile à lire pour les mortels normaux + l'ajout d'une constante évitera d'avoir l'uuid comme 00000001.

0
Jarda

Si les deux touches pointent vers le même fait, elles ne se heurteront jamais. Pourquoi ne pas dériver l'autre clé de celle d'origine en utilisant une fonction scalaire qui créerait un code de hachage personnalisé de votre clé d'origine.

alternativement, vous pouvez créer une table de mappage annexe, qui stockerait les deux versions de la clé. cette table servira de dictionnaire pour rechercher la clé secondaire.

Selon ma compréhension, les clés sont des indices implicites et plus vous ajoutez d'indices, plus les insertions seront lentes.

0
A.Rashad