Relazione condizionale con chiave esterna


14

Al momento ho una chiave esterna tra due entità e vorrei subordinare tale relazione all'entitàType di una delle tabelle. Ecco la gerarchia di tabelle, questo viene fatto tramite riferimenti FK da figlio a genitore

                  Store
            /                \
  Employees                    \
                             TransactionalStores
                            /       |         \
                     Kiosks         |          BrickMortars
                                 Onlines

Attualmente ho una relazione FK dal dipendente al negozio

ALTER TABLE Employees ADD CONSTRAINT Employee_Store
            FOREIGN KEY (TransStoreId)
            REFERENCES TransactionalStores(StoreId)

Vorrei aggiungere il condizionale:

WHERE TransactionalStores.storeType != 'ONLINE_TYPE'

È possibile o devo sottoclassare TransactionalStores in due nuovi sottotipi (ad esempio PhysicalStores e VirtualStores)


Risposte:


17

Le chiavi esterne possono essere condizionate ... in un certo senso. Non mostri il layout di ogni tabella, quindi ecco un tipico design che mostra le tue relazioni:

create table TransactionalStores(
    ID        int   not null auto_increment,
    StoreType char  not null,
    ..., -- other data
    constraint CK_TransStoreType check( StoreType in( 'B', 'K', 'O' )),
    constraint PK_TransactionalStores primary key( ID ),
    constraint UQ_TransStoreTypes unique( ID, StoreType ) -- for FK references
);
create table Kiosks(
    ID         int   not null,
    StoreType  char  not null,
    ..., -- other Kiosk data
    constraint CK_KioskStoreType check( StoreType = 'K' ), -- kiosks only
    constraint PK_Kiosks primary key( ID, StoreType ),
    constraint FK_Kiosks_TransStores foreign key( ID, StoreType )
        references TransactionalStores( ID, StoreType )
);

Online e BrickMorters avrebbero la stessa struttura di base ma con StoreType vincolato solo a 'O' o 'B' come appropriato.

Ora vuoi un riferimento da un'altra tabella a TransactionalStores (e attraverso di essa alle varie tabelle del negozio) ma limitato a Kiosks e BrickMorter. L'unica differenza sarebbe nel vincolo:

create table Employees(
    ID         int       not null,
    StoreID    int,
    StoreType  char,
    ..., -- other Employee data
    constraint PK_Employees primary key( ID ),
    constraint CK_Employees_StoreType check( coalesce( StoreType, 'X' ) <> 'O' )), -- Online not allowed
    constraint FK_Employees_TransStores foreign key( StoreID, StoreType )
        references TransactionalStores( ID, StoreType )
);

In questa tabella, il riferimento FK impone che StoreType sia 'K', 'O' o 'B' ma il vincolo di campo lo limita ulteriormente a 'K' o 'B'.

Per esempio, ho usato un vincolo di controllo per limitare i tipi di negozi nella tabella TransactionStores. Nella vita reale, una tabella di ricerca StoreTypes con StoreType come FK per quella tabella sarebbe probabilmente una scelta di design migliore.


9

Una chiave esterna non può essere soggetta a condizioni, quindi è fuori discussione. La regola aziendale sembra essere che un dipendente possa lavorare per un solo negozio fisico . Detto questo, il super tipo di negozio ha due sottotipi come hai suggerito: Fisico e Online . Ogni negozio fisico può essere gestito da uno o più dipendenti e ogni dipendente deve essere assegnato a un solo negozio fisico. I negozi fisici hanno quindi due sottotipi, Brick and Mortar e Kiosk . Avere tre sottotipi diretti: Kiosk , Online e Brick and Mortar- nasconde una proprietà posseduta da ogni negozio - indipendentemente dal fatto che possa essere trovata in un luogo fisico. Ora il design si basa su un essere umano per comprendere la semantica inerente ai nomi dei sottotipi per capire che i negozi online non hanno dipendenti. Ciò non è facilmente evidente nello schema dichiarato e il codice sotto forma di trigger deve essere scritto per esprimere tale comprensione in un modo che il DBMS può applicare. Sviluppare, testare e mantenere un trigger che non influisce sulle prestazioni è una soluzione molto più difficile da implementare, come mostrato nel libro Applied Mathematics for Database Professionals .

La sotto-tipizzazione del negozio prima nel suo tipo di posizione e poi nella struttura del negozio fisico è una progettazione più corretta rispetto alle regole aziendali ed elimina la necessità di scrivere codice per far rispettare la regola. Una volta che la proprietà è chiaramente inclusa come tipo di ubicazione del negozio che può essere utilizzata come discriminante per i sottotipi, la relazione può essere stabilita direttamente tra dipendenti e negozi fisici e quindi implementare completamente la regola solo con il vincolo di chiave esterna. Esiste un modello di dati creato con Oracle SQL Developer Data Modeler che mostra il super e il sotto-tipo usando Barker-Ellisnotazione box in box per super e sottotipi, che preferisco per la sua presentazione elegante. Il diagramma ora può mostrare chiaramente anche la regola.

inserisci qui la descrizione dell'immagine

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.