2009-09-07 15 views
8

Immaginate il seguente database:Database Design: Dipendenza circolare

Table 'imprese' ha campi id, nome e flagship_product_id. La tabella 'prodotti' ha i campi id, name e company_id.

Un'azienda deve disporre di un prodotto di punta (rapporto 1: 1) e tutti i prodotti hanno una società (rapporto 1: N).

Quando si utilizza un motore di archiviazione come MyISM, non ci dovrebbero essere problemi con lo scenario sopra, ma quando si utilizza un motore come InnoDB, i problemi si verificano quando INSERIRE nuovi dati.

Qual è una buona soluzione tranne che consentire una relazione NULL per l'INSERT iniziale?

In sintesi, un must società hanno uno prodotto di punta.

+0

ho un problema molto simile, anche se InnoDB non è un fattore. La dipendenza circolare nello schema è il problema. –

risposta

1

Non conosco quel particolare motore di database, ma cerco un modo per sospendere temporaneamente i controlli di coerenza dei dati o l'integrità referenziale durante le operazioni di inserimento e aggiornamento di atomici.

+0

Su MySQL è 'SET FOREIGN_KEY_CHECKS = 0', ma è l'unico modo? – LiraNuna

+0

Sono abbastanza sicuro che sia il percorso, se ti attieni a quel progetto. Se l'hai fatto solo per la durata dell'operazione, perché sarebbe indesiderabile? Penso di sapere cosa ti infastidisce, vuoi che sia più pulito. Sfortunatamente, penso che i database relazionali non siano bravi nell'esprimere questo tipo di relazione. –

+0

Alcune cose devono essere applicate nel livello applicazione. :-) –

2

perché non mettere un campo di prodotto di punta nella tabella prodotti come un valore booleano ... si potrebbe indice che e CompanyID e hanno una piuttosto veloce ricerca

+2

Un indice non ha alcun impatto sulle regole aziendali - chi ha votato per questo ?! –

5

Stai sia andando ad avere per consentire valori null in flagship_product o riconsiderare come si modella questa situazione. Prendi invece in considerazione flagship_product come campo booleano sul prodotto. Quindi non hai una dipendenza circolare. Oppure avere un campo product_type sul prodotto che potrebbe avere valori come FLAGSHIP o NORMAL o OBSOLETE o qualsiasi altra cosa. Ovviamente devi farlo rispettare, ma in passato ho trovato una soluzione più pulita a questo tipo di problema.

+0

Si potrebbe facilmente fare un ulteriore passo avanti e avere una tabella PRODUCT_ATTRIBUTES che elenca gli attributi associati a un prodotto, uno dei quali potrebbe essere "FLAGSHIP". Questo consente più attributi se necessario. – Andrew

+1

Ma allora significa che potrebbero esserci diversi prodotti di punta per un'azienda, cosa che non è desiderata. – LiraNuna

+0

Come ho già detto, deve essere applicato. – cletus

3

mi consiglia di utilizzare il seguente modello di dati:

IMPRESE

  • COMPANY_ID pk

PRODOTTI

  • PRODUCT_ID (PK)
  • COMPANY_ID (fk)

FLAGSHIP_PRODUCTS

  • company_id (pk, fk)
  • product_id (fk)

Creazione di una colonna FLAGSHIP nella tabella PRODUCTS non necessari affinché un unico prodotto è la punta prodotto per l'azienda dato:

  • Una chiave univoca per la colonna FLAGSHIP richiede i valori di essere diverso da ogni altro vincolo
  • Un controllo è solo un elenco di valori accettabili
+0

Questo complicherà le domande e danneggerà le prestazioni? – LiraNuna

+3

È buono che i dati cattivi tornino velocemente? –

+0

Questo modello richiede 'UNIQUE (company_id, product_id)' su 'flagship_products', giusto? Quindi è fondamentalmente una tabella pivot 1: 1 (strano ...). – strager

1

gli unici prodotti che sono intelligente e abbastanza potente per affrontare tali situazioni sono correttamente sistemi che abbracciano/implementano completamente il concetto di Multiple Assignment.

Non c'è un singolo sistema SQL riprodotto in quel campionato.

EDIT

sistemi SQL hanno differito controllo dei vincoli, ma usando che possono ottenere disordinato.

0

Ecco uno schema di un possibile work-around. Non sono sicuro di quanto in alto sulla scala di Kludge si adatti, ma è lassù.

  • Crea database
  • Creare clienti e prodotti tavoli
  • inserire un segnaposto o "fittizio" riga in ogni, configurato per fare riferimento a un l'altro
  • Stabilire vincoli FK tra le tabelle

Successivamente, ogni volta che viene creato un cliente o un prodotto, SE il prodotto/azienda di riferimento appropriato non è stato ancora creato, è stato inizializzato il nuovo elemento in modo che punti al placholder fittizio. Quindi si inserisce quell'elemento e si completa aggiornando la prima voce.

Il vantaggio è, avete l'integrità referenziale assoluta una volta che il database di routine di inizializzazione è completato - e si esegue solo una volta in presumibilmente circostanze molto controllate, in modo da guardare da vicino e assicurarsi che non manca! Il lato negativo è che ora hai un elemento "extra" in ogni tabella che ingombrare il tuo sistema.

+0

È meglio che consentire i null - null essendo il segnaposto riservato invisibile? –

+0

Il riferimento a una riga fittizia o segnaposto è un'alternativa (il?) Standard ad avere un riferimento di chiave esterna NULL. È come "Null" = non sappiamo di cosa si tratta, e "Placholder" = sappiamo che non abbiamo i dati e stiamo gestendo in modo proattivo la situazione con dati inseriti deliberatamente. Il rovescio della medaglia è che devi deliberatamente manipolare/codificare per il segnaposto ... ma poi, dovresti fare lo stesso con i null, quindi perché non rendere un po 'più ovvio cosa sta succedendo? –

0

Avrete bisogno di interrompere il ciclo di rinviare uno dei vostri vincoli di integrità referenziale fino alla fine della transazione.

Si prega di google per "INITIALLY DEFERRED DEFERRABLE".

(non so se InnoDB supporta questo)

Problemi correlati