2009-09-01 4 views
0

J'ai une base de données MySQL où une clé (une chaîne) est lue à partir d'une source tierce. Cependant, ceux-ci ne sont pas toujours garantis uniques (ce sont des titres de films). J'ai donc besoin de vérifier l'unicité de la clé, et si ce n'est pas unique, modifiez-la pour la rendre unique - en ajoutant un compte incrémentiel à la fin de la clé par exemple.Assurer l'unicité d'une clé MySQL

Quel est le meilleur modèle pour cela? J'ai actuellement une table qui stocke toutes les clés reçues de la 3ème partie et stocke un compte, donc je fais:

INSERT INTO MYTABLE(KEY) VALUES(KEY_VAlUE) ON DUPLICATE KEY UPDATE KEY_COUNT = KEY_COUNT + 1 

J'utilise JdbcTemplate et un porte-clefs pour récupérer l'ID du nouveau (ou mis à jour) rangée. Le problème est que j'ai aussi besoin de récupérer le compte. Je peux bien sûr maintenant faire une deuxième requête (SELECT) pour aller chercher l'enregistrement avec cet ID. Cependant, le problème ici est avec la concurrence. C'est possible (bien qu'improbable), un autre INSERT avec la même clé tierce se produit juste avant de faire mon SELECT. Dans ce cas, le compte serait incrémenté une seconde fois et je reculerais le compte.

Des idées?

Merci Richard.

Répondre

0

Si vous autorisez le système à créer des valeurs de clé uniques arbitraires pour N'IMPORTE QUELLE ligne (celles qui ne sont pas uniques au départ), alors, au lieu de le modifier pour être unique, créez votre propre substitut interne clé, en utilisant la fonction d'auto-incrémentation (MySQL a ce droit?), et stocker la clé soumise telle qu'elle a été soumise dans un attribut de colonne non unique.

utiliser la clé de remplacement interne pour toutes les contraintes d'intégrité relationnelles, et utiliser uniquement la clé soumis à d'autres exigences non uniques ...

1

Le meilleur modèle pour ce faire est de ne pas. Clouer votre table par une corde comme celle-ci, surtout là où vous savez à l'avance qu'il y aura des collisions, ne vous causera que du chagrin à long terme. Utilisez simplement une clé auto-incrémentée sans signification. Vous pouvez toujours indexer par titre si vous le souhaitez, et vous n'avez pas à utiliser vos données. Incidemment, je pense que lorsqu'il s'agit de collisions de titres de films, la convention est d'ajouter l'année du film entre parenthèses, par ex. "The Producers (1968)" contre "The Producers (2005)"

+0

Hi Thom. Oui, je sais que ce n'est pas idéal. La raison pour laquelle je veux le faire est que j'ai une belle URL lisible par l'homme - le titre est converti en une URL comme ça: http://mysite.com/The_Producers. "The_Producers" est donc ma clé DB unique, qui est utilisée pour extraire les informations de film correctes de la base de données. J'aime la suggestion de l'année, merci. –

+0

Qu'est-ce que votre URL doit faire avec votre clé primaire? Il n'y a aucune raison qu'ils doivent être connectés. –

0

Transactions. Vous sont en utilisant InnoDB, non? Tu devrais être. Cependant, un titre de film ressemble à une mauvaise clé primaire pour moi. Avez-vous envisagé d'ajouter un synthetic primary key, tel qu'un entier auto-incrémenté?

+0

Salut bobince. Oui, j'utilise InnoDB. La transactionnalité est probablement ce que je vais faire. J'utiliserais autre chose que le titre comme clé, mais je veux des URL comme: http://mysite.com/my_movie_title, donc "my_movie_title" est forcément la clé. Bravo pour la suggestion. –

+0

Un titre peut être une clé unique sans que ce soit * la * clé primaire.Dans tous les cas, ce style d'URL est joli, mais si vous devez changer/corriger un titre de film, toutes vos anciennes références et vos URL vont se casser. Si les titres de films dupe sont communs (et dans une base de données assez importante, ils le seront probablement), vous finirez quand même par 'my_movie_title-12', à ce moment là, avec le style ID-and-slug mysite.com/1234/ my_movie_title ne semble pas vraiment désavantageux. – bobince

+0

ouais je pense que vous pourriez avoir raison. Il est plus facile d'encoder une clé/identifiant unique garanti avec le titre. –

0

Je ne sais pas s'il existe un "modèle" pour cela, mais pourquoi ne pas simplement utiliser une transaction?

START TRANSACTION; 

INSERT INTO MYTABLE(KEY) VALUES(KEY_VAlUE) ON DUPLICATE KEY UPDATE KEY_COUNT = KEY_COUNT + 1; 
SELECT KEY_COUNT FROM MYTABLE WHERE KEY=KEY_VALUE; 

COMMIT; 
+0

Salut Zombat. Merci pour votre suggestion, je pense que c'est la meilleure façon de le faire. À votre santé. –