2017-10-18 8 views
1

J'ai une application dans laquelle les utilisateurs peuvent créer leurs propres balises privées personnalisées, mais il existe également des balises communes fixes à l'échelle du système. Les balises sont stockées dans une table de base de données, où les balises communes sont celles où USER_ID est NULL.Application d'une valeur unique par utilisateur, y compris les valeurs globales

CREATE TABLE TAG (
    TAG_ID INT IDENTITY(1, 1) NOT NULL, 
    TAG_NAME VARCHAR(40) NOT NULL, 
    USER_ID INT, 

    CONSTRAINT TAG_PK PRIMARY KEY (TAG_ID), 

    CONSTRAINT TAG_FK1 FOREIGN KEY (USER_ID) 
    REFERENCES [USER] (USER_ID) 
); 
CREATE INDEX TAG_IDX1 ON TAG (USER_ID); 

Je veux appliquer au niveau DB que les balises sont propres à chaque utilisateur, ce qui signifie que:

  • Un utilisateur ne peut avoir une étiquette avec un nom donné, mais d'autres clients peuvent également avoir leurs propres étiquettes avec un tel nom.

  • Les balises communes doivent également être prises en compte, de sorte que les utilisateurs ne peuvent pas créer de balise déjà courante.

Un index simple comme cela ne fonctionnera pas, car elle empêche que des dupes dans les groupes (balises communes un chaque utilisateur) -c'est encore possible de recréer des balises communes en tant que balises utilisateur:

CREATE UNIQUE INDEX TAG_UK1 ON TAG (TAG_NAME, USER_ID); 

Je crois que SQL Server ne permet pas d'expressions dans les index, par exemple:

-- Incorrect syntax near the keyword 'COALESCE'. 
CREATE UNIQUE INDEX TAG_UK1 ON TAG (TAG_NAME, COALESCE(USER_ID, 'COMMON')); 

Pouvez-vous penser à une autre approche?

+1

Cela me semble que vous devez repenser l'architecture un peu. C'est un type de relation de plusieurs à plusieurs (avec quelques mises en garde supplémentaires) qui est presque impossible à faire avec seulement deux tables. –

+0

Garantir l'unicité dans ce cas par le biais d'un index peut ne pas être faisable -AFAIK, de toute façon- et il ne semble pas non plus que vous profitiez d'un index pour des raisons de performances. Pourquoi ne mettez-vous pas ces vérifications dans un proc stocké ou un trigger? – Icarus

+0

@SeanLange Je n'y avais pas pensé de cette façon et cela a du sens du point de vue de la conception DB. Mais étant donné que je devrai peut-être aussi éditer l'outil d'administration et de nombreuses autres parties du code, il vaut peut-être mieux autoriser les dupes et ajuster l'interface pour les afficher séparément, ce qui serait probablement acceptable pour mon cas précis. –

Répondre

0

Probablement besoin de gérer cela avec des triggers.

Dans la table de variables si vous insérez ou mettez à jour une nouvelle variable globale. Vous devez vérifier pour chaque utilisateur pour voir s'il a déjà cette étiquette et le transformer en global

Par exemple, vous avez Angular comme un tag mais certains utilisateurs sont un moyen et créer Angular4. Lorsque le Angular4 devient un tag global, vous devez le supprimer de tous les utilisateurs. Idem pour créer un tag pour un utilisateur, vous pouvez vérifier si le global a déjà cette balise et déclencher une erreur.

+0

Les étiquettes communes sont codées en dur dans l'ensemble de données initial et elles ne peuvent pas être modifiées. –

+1

Ne change pas ma réponse. L'ajout de tags pour les utilisateurs ne peut être validé qu'à l'aide des déclencheurs. –

+0

Merci. J'ai probablement pensé à Oracle et à ses index basés sur les fonctions lorsque j'ai conçu ce design brillant xD –