2009-11-12 14 views
33

Devo definire una relazione uno-a-uno e non riesco a trovare il modo corretto di farlo in SQL Server.Definizione di una relazione uno a uno in SQL Server

Perché una relazione one-to-one chiedi?

Sto usando WCF come DAL (Linq) e ho una tabella contenente una colonna BLOB. Il BLOB non cambia quasi mai e sarebbe uno spreco di larghezza di banda trasferirlo ogni volta che viene effettuata una query.

Ho dato un'occhiata allo this solution e, sebbene sembri un'ottima idea, posso solo vedere Linq avere un piccolo sibilo quando proviamo a implementare questo approccio.

Qualche idea?

risposta

76

Uno a uno è in realtà utilizzato frequentemente nella relazione supertipo/sottotipo. Nella tabella figlio, la chiave primaria funge anche da chiave esterna per la tabella padre. Ecco un esempio:

org_model_00

CREATE TABLE Organization 
( 
    ID  int PRIMARY KEY, 
    Name  varchar(200), 
    Address varchar(200), 
    Phone varchar(12) 
) 
GO 

CREATE TABLE Customer 
( 
    ID    int PRIMARY KEY, 
    AccountManager varchar(100) 
) 
GO 

ALTER TABLE Customer 
    ADD FOREIGN KEY (ID) REFERENCES Organization(ID) 
     ON DELETE CASCADE 
     ON UPDATE CASCADE 
GO 
+5

Grazie a dio qualcuno qui conosce database SQL e relazionali. Hai dimostrato che la relazione è ** esplicita **. Giusto per essere chiari, per coloro che non sono sicuri che la relazione sia 1: 1, nota che Customer.ID, che è anche Organisation.ID, è ** unique ** e quindi può esserci una sola riga Customer per qualsiasi riga Organizzazione. – PerformanceDBA

+30

@PerformanceDBA: la relazione è '1: 0..1' perché manca un vincolo per garantire che per ogni riga della tabella padre sia presente una riga corrispondente in una delle tabelle sottotipo. Per lo schema come pubblicato, per ogni riga in 'Organizzazione 'possono essere zero o una riga in Cliente, quindi' 1: 0..1'. – onedaywhen

+1

@ oneday. Grazie, ma la tua spiegazione del problema di superficie (ovvio) non è rilevante per il problema più profondo. La base del tuo commento, e non il commento stesso, non è corretta. Hai lo stesso malinteso di Adam (che da allora ha cancellato la sua risposta). Il problema non può essere affrontato nei commenti. Se sei sinceramente interessato a comprendere la nomenclatura dei database relazionali, ti preghiamo di fare una nuova domanda, e io risponderò pienamente. Non risponderò a ulteriori commenti. – PerformanceDBA

4

Perché non rendere la chiave esterna di ogni tabella univoca?

+0

Quindi se ho la chiave nella tabellaA = 3 e la chiave nella tabellaB = 4, sono univoci nella loro tabella ma non c'è alcuna relazione. – JeffO

+1

Tuttavia, se tableA.id = 3 e tableB.tableAId = 3 e tableB.tableAId è univoco, e si fa lo stesso per tableB a tableA, allora si garantisce un massimo di uno a uno. – Myles

2

non esiste una relazione uno-a-uno esplicita.

Tuttavia, dal fatto che tbl1.id e tbl2.id sono chiavi primarie e tbl2.id è una chiave esterna che fa riferimento a tbl1.id, è stata creata una relazione implicita 1: 0..1.

1

Put 1: 1 oggetti collegati nella stessa riga della stessa tabella. Ecco da dove viene la "relazione" nel "database relazionale": le cose correlate vanno nella stessa riga.

Se si vuole ridurre la dimensione dei dati che viaggiano sul filo prendere in considerazione sia la proiezione solo le colonne necessarie:

SELECT c1, c2, c3 FROM t1 

o creare una vista che proietta solo le colonne rilevanti e utilizzare questo punto di vista, se necessario:

CREATE VIEW V1 AS SELECT c1, c2, c3 FROM t1 
SELECT * FROM t1 
UPDATE v1 SET c1=5 WHERE c2=7 

Si noti che i BLOB sono archiviati in fila in SQL Server in modo da non risparmiare molto I/O disco mediante il partizionamento verticale dei dati. Se si tratta di colonne non BLOB, è possibile trarre vantaggio dal partizionamento verticale come descritto, poiché si eseguirà meno IO del disco per eseguire la scansione della tabella di base.

0

Che ne dici di questo. Collegare la chiave primaria nella prima tabella alla chiave primaria nella seconda tabella.

Tab1.ID (PK) < -> Tab2.ID (PK)

Il mio problema era che ho un processo a 2 stadi con campi obbligatori in entrambi. L'intero processo potrebbe essere classificato come un episodio (messo nella stessa tabella), ma c'è uno stadio iniziale e uno stadio finale.

+0

Credo sia quello che Damir ha suggerito nella prima risposta. –

+1

Non è possibile avere vincoli a due vie obbligatori. È necessario implementare le transazioni e gestirle all'interno del contesto SQL, in sequenza. Quindi è facile. – PerformanceDBA

0

A mio parere, una soluzione migliore per non leggere il BLOB con la query LINQ sarebbe quella di creare una vista sulla tabella che contiene tutta la colonna eccetto quelle BLOB.

È quindi possibile creare un'entità EF in base alla vista.

+0

Non è necessario firmare i tuoi post, SO lo fa automaticamente per te. Inoltre, le risposte dovrebbero generalmente mostrare esempi di codice che fa ciò che stai suggerendo. : | – vdbuilder

Problemi correlati