2012-04-30 8 views
0

Compte tenu de ces règles métier:cohérence application entre plusieurs 1: relations m

  • Les utilisateurs ont 0 ou plusieurs comptes et tous les comptes sont associés à un seul utilisateur
  • Les utilisateurs ont 0 ou plus actifs et tous les actifs sont associé à un seul utilisateur
  • Un actif peut être associé à un seul compte. S'il est affecté à un compte, ce compte doit appartenir à l'utilisateur associé à l'actif.

Assumer le schéma proposé ci-dessous:

User 
-id 

Account 
-id 
-user_id 

Asset 
-id 
-user_id 
-account_id (Nullable) 

Il semble qu'il y ait une faiblesse dans ce schéma car un actif pourrait être affecté à un compte qui appartient à un autre utilisateur de cet actif . Est-ce que cela est adressé par l'un des formulaires normaux menant à un meilleur schéma ? Si ce n'est pas couvert par la normalisation est la meilleure contrainte alors du côté de la logique métier?

+0

Tous les comptes sont associés à un seul utilisateur. Cela signifie-t-il que deux utilisateurs ne peuvent pas avoir le même numéro d'identification de compte? (Même question pour les actifs.) –

Répondre

1

La seule partie de cette (ci-dessous) que la normalisation pourrait traiter est la colonne nullable. Dans la compréhension de Chris Date, si une colonne autorise NULL, alors la relation n'est pas dans 1NF.

Si vous essayez de suivre strictement le modèle relationnel, je pense que vous seriez capable de gérer cela avec une assertion. Mais la plupart des plateformes SQL ne supportent pas les assertions. En SQL, je crois que vous cherchez quelque chose dans ce sens. J'ai testé cela dans PostgreSQL.

create table users (
    user_id integer primary key 
); 

create table accounts (
    user_id integer not null references users (user_id), 
    account_id integer not null unique, 
    primary key (user_id, account_id) 
); 

create table assets (
    user_id integer not null references users (user_id), 
    asset_id integer not null unique, 
    account_id integer null, 
    primary key (user_id, asset_id), 
    foreign key (user_id, account_id) references accounts (user_id, account_id) 
); 

-- Insert 3 users. 
insert into users values (1), (2), (3); 

-- User 1 has two accounts, user 2 has 3 accounts, user 3 has none. 
insert into accounts values 
(1, 100), 
(1, 101), 
(2, 102), 
(2, 103), 
(2, 104); 

-- User 1 has 1 asset not assocated with an account. 
insert into assets values (1, 200, null); 

-- User 1 has 1 asset associated with account 101 
insert into assets values (1, 201, 101); 

-- User 1 tries to associate an asset with account 102, which doesn't belong to user 1. 
insert into assets values (1, 202, 102); 
[Fails with foreign key violation] 

-- User 2 has two assets not associated with an account. 
insert into assets values 
(2, 500, null), 
(2, 501, null); 
-1

Je suggère de supprimer complètement la clé étrangère account_id de la table Asset. Puisque account_id est lié à votre table utilisateur, vous pouvez joindre l'actif et l'utilisateur, puis effectuer une jointure gauche de l'utilisateur au compte (s'il s'agit de la table où account_id est la clé primaire). Si vous obtenez un résultat de la jointure gauche, l'actif est lié à un compte et l'utilisateur est le même. De cette façon, vous forcez cette contrainte.

Hope this helps, Cordialement

ElChe

+0

Je ne suis pas sûr que cela satisfasse encore aux exigences de la troisième entreprise - que l'actif soit affecté à un ou à aucun compte. Si je me débarrasse de account_id de Asset, il n'y a pas d'assignations explicites de l'actif au compte. La jointure sur l'actif et l'utilisateur produirait l'ensemble de tous les actifs et leur utilisateur correspondant. Je pense qu'une autre jointure sur le compte (via user_id) ne capturerait pas le seul actif à un compte ou aucun, mais plutôt un produit croisé (par exemple, chaque actif d'un utilisateur spécifique «appartiendrait» à chaque compte pour cet utilisateur). – user1338952

+0

Vous avez bien sûr raison, j'ai oublié cela. Que diriez-vous d'avoir une table reliant l'utilisateur au compte et à l'actif. account_asset compte assetid Si cela n'est pas possible, vous devez appliquer cette relation avec businesslogic. –

Questions connexes