2017-06-28 6 views
2

Pour une table CARS avec deux colonnes, MAKE et MODEL, je voudrais appliquer que pour certaines valeurs MAKE particulières, leurs valeurs MODEL doivent être uniques (en supposant c'est une base de données Oracle). Par exemple, je veux imposer des doublons pour Ford, mais pas pour Toyota. Je ne veux pas plus d'une rangée avec le modèle 'F150' et le 'Ford' MAKE. Cependant, il est correct d'avoir deux rangées avec le modèle 'Rav4' et le 'Toyota' MAKE. Il est également bon d'avoir une rangée avec le modèle 'F150' et le 'Ford' MAKE et une autre rangée avec le 'F150' MODEL et le 'Toyota' MAKE.Appliquer unicité sur un sous-ensemble de lignes sur une table dans Oracle DB

J'ai étudié différentes stratégies avec des déclencheurs, des contraintes ou des index, mais je n'ai encore rien trouvé qui me donnerait le niveau de contrôle dont j'ai besoin.

Merci!

Répondre

2

Vous pouvez créer un indice de fonction unique pour assurer l'unicité de (marque, modèle) que des paires lorsque make = 'Ford':

create table cars (make varchar2(255) not null, model varchar2(255) not null); 

create unique index ford_index on cars (
    case make 
    when 'Ford' then make 
    else null 
    end, 
    case make 
    when 'Ford' then model 
    else null 
    end ); 


insert into cars (make, model) values ('Ford', 'F150'); 
insert into cars (make, model) values ('Ford', 'Fiesta'); 
insert into cars (make, model) values ('Toyota', 'Camry'); 
insert into cars (make, model) values ('Toyota', 'Camry'); 
insert into cars (make, model) values ('Ford', 'F150'); --- FAILS with unique constraint violation 

index ford_index (marque, modèle) que si make = » Ford '- tout le reste est exclu de l'index et n'est donc pas soumis à la contrainte d'unicité.

+0

Comment écrivez-vous cela, s'il y a vingt-huit marques pour lesquelles l'unicité doit être imposée, et trente-six autres pour lesquelles l'unicité n'est pas nécessaire? Comment serait-il maintenu si la liste des marques qui exigent l'unicité change avec le temps? – mathguy

+0

@mathguy - probablement je créerais un index pour chaque marque qui exige l'unicité du modèle. Puisque nous parlons des constructeurs automobiles, je m'attends à ce que le nombre de marques soit raisonnablement bas. – user1041892

+0

Merci! Je n'avais pas pensé à utiliser des déclarations de cas dans cette situation. C'est certainement le meilleur moyen que j'ai vu.Malheureusement pour moi, je dois ajouter ceci à une table existante qui a déjà des doublons (pour empêcher de futurs dups) mais il ne semble pas y avoir d'équivalent d'index pour les options 'DEFFERED NOVALIDATE' que vous pouvez donner sur une contrainte. – JKuester

0

Créer une vue matérialisée, avec une actualisation rapide lors de la validation. La définition MV peut être simplement select make, model from <your_table> where make in (select make from <small_table>). Le <small_table> listera les marques pour lesquelles vous souhaitez appliquer cette unicité. Puis créez un index unique sur (make, model) dans la vue matérialisée.

Chaque fois qu'une duplication est tentée avec la marque 'Ford', le MV sera actualisé lors de la validation. La modification du MV sera rejetée, ce qui entraînera l'échec de l'original COMMIT.

+0

ce serait bien si vous ajoutez l'instruction create à votre message. – miracle173

+0

@ miracle173 - l'instruction de création de vue matérialisée est triviale. Plus important encore, les journaux MV doivent être créés en premier. – mathguy

+0

Les mviews à rafraîchissement rapide ne peuvent pas avoir de sous-requête de liste de sélection. – eaolson