Più campi foreign key per un solo campo in un'altra tabella

mercoledì 25 luglio 2007 - 19.48

_J_ Profilo | Senior Member

salve ragazzi,
vorrei un consiglio da voi su come gestire questa situazione:

ho una tabella 'cittadino' contenente due campi 'città nascita' e 'città residenza' che fanno entrambi riferimento ad un altro campo 'cod città' di un'altra tabella 'città', che inoltre contiene anche il campo 'nome città'...
in fase di select mi serve conoscere il cod e il nome della città di nascita, e il cod e il nome della città di residenza...

cioè devo richiamare due volte la tabella 'città' per specificare la città di nascita e quella di residenza...

ho provato con il wizard per le query e ho dovuto per forza duplicare la tabella 'città' (e i due duplicati sono collegati tra essi...)
ma la duplicazione non è che mi convince tantissimo, per via del fatto che in un futuro non molto lontano dovrò intervenire su database con update, insert ecc, ed ho paura di avere problemi in termini di tabella su cui intervenire...

qualcuno d voi saprebbe consigliarmi qualcosa in merito?
grazie a chi risponderà
_J_

"Chi fa domande rischia di sembrare stupido,
chi non ne fa rischia di restare stupido..."

"Conosco me stesso? No, non parlo con gli estranei..."

alx_81 Profilo | Guru

>salve ragazzi,
Ciao!

>ho provato con il wizard per le query e ho dovuto per forza duplicare
>la tabella 'città' (e i due duplicati sono collegati tra essi...)
>ma la duplicazione non è che mi convince tantissimo, per via
>del fatto che in un futuro non molto lontano dovrò intervenire
>su database con update, insert ecc, ed ho paura di avere problemi
>in termini di tabella su cui intervenire...
ma è una duplicazione logica oppure hai creato due tabelle fisicamente?

>qualcuno d voi saprebbe consigliarmi qualcosa in merito?
ti allego uno script di esempio per SQL Server 2005, che, se non ricordo male, è il tuo DBMS (ricordati sempre di indicare le cose che utilizzi per facilitare le risposte ):

USE tempdb; GO -- creo la tabella cittadino IF NOT EXISTS(SELECT * FROM sysobjects WHERE id = object_id(N'Cittadino')) CREATE TABLE Cittadino ( IdCittadino int IDENTITY(1,1) NOT NULL, Nome varchar(30) NOT NULL, Cognome varchar(30) NOT NULL, IdCittaNascita smallint NOT NULL, IdCittaResidenza smallint NOT NULL, CONSTRAINT PK_Cittadino PRIMARY KEY CLUSTERED ( IdCittadino ) ) GO -- creo la tabella citta IF NOT EXISTS(SELECT * FROM sysobjects WHERE id = object_id(N'Citta')) CREATE TABLE Citta ( IdCitta smallint IDENTITY(1,1) NOT NULL, NomeCitta varchar(30) NOT NULL, CONSTRAINT PK_Citta PRIMARY KEY CLUSTERED ( IdCitta ) ) GO -- creo le relazioni ALTER TABLE Cittadino ADD CONSTRAINT FK_Cittadino_CittaNascita FOREIGN KEY (IDCittaNascita) REFERENCES Citta (IDCitta) GO ALTER TABLE Cittadino ADD CONSTRAINT FK_Cittadino_CittaResidenza FOREIGN KEY (IDCittaResidenza) REFERENCES Citta (IDCitta) GO -- popolo i dati di prova INSERT Citta SELECT 'Parma' INSERT Citta SELECT 'Collecchio' INSERT Citta SELECT 'Venezia' INSERT Citta SELECT 'Noceto' INSERT Citta SELECT 'Fidenza' INSERT Citta SELECT 'Londra' INSERT Cittadino SELECT 'Alessandro', 'Alpi', 1, 1 INSERT Cittadino SELECT 'Silvia', 'Pedretti', 2, 2 INSERT Cittadino SELECT 'Daniele', 'Zanella', 3, 4 INSERT Cittadino SELECT 'Michael', 'Denny', 6, 5 INSERT Cittadino SELECT 'Marco', 'Rossi', 5, 5 -- dati SELECT * FROM Cittadino SELECT * FROM Citta -- ecco la join che devi fare per ottenere tutto ciò che ti serve SELECT C.Nome , C.Cognome , CodiceCittaNascita = CN.IdCitta , CittaNascita = CN.NomeCitta , CodiceCittaResidenza = CR.IdCitta , CittaResidenza = CR.NomeCitta FROM Cittadino C JOIN Citta CN ON C.IdCittaNascita = CN.IdCitta JOIN Citta CR ON C.IdCittaResidenza = CR.IdCitta -- pulizia DROP TABLE Cittadino DROP TABLE Citta

è semplice, creo la tabella cittadino e la tabella citta, e poi creo le relazioni con le FOREIGN KEY ed infine scrivo una query che mi ritorna tutto quello che serve..


>grazie a chi risponderà
di nulla!

Alx81 =)

http://blogs.dotnethell.it/suxstellino

_J_ Profilo | Senior Member

ciao alx!

>ma è una duplicazione logica oppure hai creato due tabelle fisicamente?
quando ho provato col query builder (lo uso per vedere se c'è la possibilità di un suggerimento) ho dovuto fare col tasto destro del mouse un 'add table' perchè mi serviva due volte la stessa tabella....


> ecco la join che devi fare per ottenere tutto ciò che ti serve
>SELECT
> C.Nome
> , C.Cognome
> , CodiceCittaNascita = CN.IdCitta
> , CittaNascita = CN.NomeCitta
> , CodiceCittaResidenza = CR.IdCitta
> , CittaResidenza = CR.NomeCitta
>FROM
> Cittadino C
> JOIN Citta CN ON C.IdCittaNascita = CN.IdCitta
> JOIN Citta CR ON C.IdCittaResidenza = CR.IdCitta
>
>-- pulizia
>DROP TABLE Cittadino
>DROP TABLE Citta

quindi fai join 2 volte sulla stessa tabella.... ok! adesso sì che la cosa mi convince (come ti ho detto nel mio post non è che la duplicazione mi piacesse poi tanto...)

una domanda che forse ti semprerà stupida: perchè lla fine fai il drop per la pulizia? è necessario visto che ho una select?

intanto grazie per il consiglio!
_J_

"Chi fa domande rischia di sembrare stupido,
chi non ne fa rischia di restare stupido..."

"Conosco me stesso? No, non parlo con gli estranei..."

alx_81 Profilo | Guru

>quando ho provato col query builder (lo uso per vedere se c'è
>la possibilità di un suggerimento) ho dovuto fare col tasto destro
>del mouse un 'add table' perchè mi serviva due volte la stessa
>tabella....
add table è un'aggiunta logica .. Quindi corrisponde alla join che ho fatto io .
forse se non hai fatto le foreign key ti fa relazioni un po' "così".. Ma se tu aggiungi più volte la tabella e definisci le corrette relazioni, la join che ottieni è del tutto simile a quella che ti propongo..

>una domanda che forse ti semprerà stupida: perchè lla fine fai
>il drop per la pulizia? è necessario visto che ho una select?
perchè è uno script di esempio fatto per girare sul tempdb (vedere la USE in alto), quindi le butto via perchè sennò ti lascio il tempdb sporco

>intanto grazie per il consiglio!
sempre un piacere

Alx81 =)

http://blogs.dotnethell.it/suxstellino

_J_ Profilo | Senior Member

la cosa dei duplicati logici (che ora ho tolto) era per ottenere 2 volte uno stesso campo da una tabella ma con due valori diversi..
cmq le foreign key sono state fatte già da tempo(e se non facevo quelle come andavo avanti???), solo che ora che mi ci fai pensare mi succede una cosa strana:
il database l'ho creato mediante codice sql, sia le chiavi primarie che le foreign, quindi era tutto prestabilito.

nei primi periodi in cui usavo il vs2005 ho visto che nel 'server explorer' c'è lo strumento 'database diagrams' che in un certo senso permette di creare visivamente le relazioni tra tabelle... ecco, la cosa strana è che lì le relazioni le crei e le salvi, ma all'atto della costrzione col query builder (quello delle join di cui in precedenza) le relazioni non te le fa vedere, come se non fossero mai state create, e se si ritorna al database diagram invece ci sono eccome!

ecco, è quello che succede nel caso della tabella che voglio collegare due volte alla tabella principale: devo ricrearmi la relazione con la tabella principale perchè su database diagram risulta, e su query buider no

cmq è sempre sqlserver 2005 (nel post precedente ho dimenticato di dirtelo ^^' )
_J_

"Chi fa domande rischia di sembrare stupido,
chi non ne fa rischia di restare stupido..."

"Conosco me stesso? No, non parlo con gli estranei..."

_J_ Profilo | Senior Member

lo sai? ho usato gli alias di tabella ed ho risolto...

una ciriosità:
se ad esempio tratto città estere, nel caso in cui la città di nascita sia in uno stato e e quella di residenza in un altro... come faccio a tirare fuori lo stato di nascita e quello di residenza oltre alle città?

_J_

"Chi fa domande rischia di sembrare stupido,
chi non ne fa rischia di restare stupido..."

"Conosco me stesso? No, non parlo con gli estranei..."

alx_81 Profilo | Guru

>cmq le foreign key sono state fatte già da tempo(e se non facevo
>quelle come andavo avanti???),
Ci sono persone che non ne hanno mai fatte.. credimi .. anche se non sono decisamente d'accordo..

>solo che ora che mi ci fai pensare
>mi succede una cosa strana:
>il database l'ho creato mediante codice sql, sia le chiavi primarie
>che le foreign, quindi era tutto prestabilito.
>nei primi periodi in cui usavo il vs2005 ho visto che nel 'server
>explorer' c'è lo strumento 'database diagrams' che in un certo
>senso permette di creare visivamente le relazioni tra tabelle...
>ecco, la cosa strana è che lì le relazioni le crei e le salvi,
>ma all'atto della costrzione col query builder (quello delle
>join di cui in precedenza) le relazioni non te le fa vedere,
>come se non fossero mai state create, e se si ritorna al database
>diagram invece ci sono eccome!
sinceramente non ho mai usato query builder.. quindi non ti saprei dire come funziona..

>
>ecco, è quello che succede nel caso della tabella che voglio
>collegare due volte alla tabella principale: devo ricrearmi la
>relazione con la tabella principale perchè su database diagram
>risulta, e su query buider no
ma quella che crei in query builder, a mio avviso, è la join.. non la relazione fisica con foreign key..
quindi ci sta che tu debba legarle..

Alx81 =)

http://blogs.dotnethell.it/suxstellino

alx_81 Profilo | Guru

>lo sai? ho usato gli alias di tabella ed ho risolto...
infatti nello script che ti ho postato c'erano gli alias.. C, CN e CR..

>una ciriosità:
>se ad esempio tratto città estere, nel caso in cui la città di
>nascita sia in uno stato e e quella di residenza in un altro...
>come faccio a tirare fuori lo stato di nascita e quello di residenza
>oltre alle città?
diciamo che la cosa migliore è fare una tabella degli stati separata dalle città, non mischiarle..
non è per nulla normalizzato..
ti consiglio di fare la tabella degli stati, e sulla tabella cittadino metti gli id degli stati.. come hai fatto per le città..
>
>_J_
>
>"Chi fa domande rischia di sembrare stupido,
>chi non ne fa rischia di restare stupido..."
>
>"Conosco me stesso? No, non parlo con gli estranei..."

Alx81 =)

http://blogs.dotnethell.it/suxstellino

_J_ Profilo | Senior Member

ma infatti la tabella degli stati ce l'ho già a parte... era già pianificato fosse a parte, ed ha una sua chiave primaria 'cod_stato'

nella tabella delle città estere c'è un campo 'cod_stato_estero' che fa da foreign verso questa chiave primaria
_J_

"Chi fa domande rischia di sembrare stupido,
chi non ne fa rischia di restare stupido..."

"Conosco me stesso? No, non parlo con gli estranei..."

alx_81 Profilo | Guru

>ma infatti la tabella degli stati ce l'ho già a parte... era
>già pianificato fosse a parte, ed ha una sua chiave primaria
>'cod_stato'
>
>nella tabella delle città estere c'è un campo 'cod_stato_estero'
>che fa da foreign verso questa chiave primaria
in tal caso basta aggiungere le due join..
hai gli alias, devi aggiungere due join una da cittanascita a stato (alias statonascita) ed una da cittaresidenza a stato (alias statoresidenza).. è molto simile al discorso citta --> cittadino..

Alx81 =)

http://blogs.dotnethell.it/suxstellino

_J_ Profilo | Senior Member

sì, già fatto

e funziona benissimo

ancora grazie 1000!
_J_

"Chi fa domande rischia di sembrare stupido,
chi non ne fa rischia di restare stupido..."

"Conosco me stesso? No, non parlo con gli estranei..."
Partecipa anche tu! Registrati!
Hai bisogno di aiuto ?
Perchè non ti registri subito?

Dopo esserti registrato potrai chiedere
aiuto sul nostro Forum oppure aiutare gli altri

Consulta le Stanze disponibili.

Registrati ora !
Copyright © dotNetHell.it 2002-2025
Running on Windows Server 2008 R2 Standard, SQL Server 2012 & ASP.NET 3.5