Dubbio su struttura tabelle

venerdì 11 ottobre 2013 - 09.43
Tag Elenco Tags  SQL Server 2008 R2  |  SQL Server 2008

andrestu Profilo | Expert

salve a tutti,
ho un dubbio su come strutturare il db.
Come potete vedere dall'immagine ho una tabella "utenti" e un altra "ownerUtene" quest'ultima servirebbe a creare una lista di proprietari per gli utenti inseriti.
Quindi un utente inserito nella tabella utente potrà poi diventare proprietario di altri utenti inseriti.
Il punto è che non riesco ad attivare su entrambe le relazioni la funzione che mi elimina il record a cascata, se provo a farlo il manageriale del db mi restituisce un errore di ridondanza ("multiple cycle path"), penso che si possa risolvere con un trigger giusto oppure cosa proponete come alternative?

grazie in anticipo


907x694 79Kb


Andrea Restucci - Web Developer

alx_81 Profilo | Guru

>salve a tutti,
ciao

>ho un dubbio su come strutturare il db.
>Come potete vedere dall'immagine ho una tabella "utenti" e un
>altra "ownerUtene" quest'ultima servirebbe a creare una lista
>di proprietari per gli utenti inseriti.
>Quindi un utente inserito nella tabella utente potrà poi diventare
>proprietario di altri utenti inseriti.
>Il punto è che non riesco ad attivare su entrambe le relazioni
>la funzione che mi elimina il record a cascata, se provo a farlo
>il manageriale del db mi restituisce un errore di ridondanza
>("multiple cycle path"), penso che si possa risolvere con un
>trigger giusto oppure cosa proponete come alternative?
in generale le operazioni di cascade sono sì comode, ma portano anche problemi (pensa al non voler fare una cosa, non hai una fk senza cascade che ti protegge).
Al di là di questo, che è una scelta dello sviluppatore alla fine (ma mi sento sempre di sconsigliarlo) la ridondanza ciclica nel tuo caso è normale.
Con un trigger puoi fare in modo di eseguire le operazioni che vuoi in cascata, ma devi fare attenzione perchè rischi di bloccare i record della tua tabella aumentando anche la possibilità di deadlock..
Io sono sempre a consigliare, se puoi permettertelo, una stored procedure che esegue le logiche che sono necessarie per la gestione della problematica, oppure in generale, fare un TransactionScope lato applicazione chiamante ed eseguire nell'ordine corretto le istruzioni di cancellazione.

>grazie in anticipo
di nulla!
Alessandro Alpi | SQL Server MVP
MCP|MCITP|MCTS|MCT

http://blogs.dotnethell.it/suxstellino
http://suxstellino.wordpress.com
http://mvp.microsoft.com/profiles/Alessandro.Alpi

andrestu Profilo | Expert

Ciao Alessandro,

> in generale le operazioni di cascade sono sì comode, ma portano anche problemi (pensa al non voler fare una cosa, non hai una fk senza cascade che ti protegge).
scusa non ho capito molto.
Parlo sempre da profano quale sono, in riferimento al DELETE non è sempre meglio, là dove possibile, avere un operazione a cascata?
non è un modo anche questo di garantire l'integrità dei dati?
io cerco sempre di impostarla o CASCADE o SET NULL là dove possibile...

tornando invece al problema in effetti come da tuo suggerimento e anche da altri suggerimenti ricevuti in rete a quanto pare sarebbe meglio o un SP o fare una Transaction piuttosto che un trigger.

> ma devi fare attenzione perchè rischi di bloccare i record della tua tabella aumentando anche la possibilità di deadlock..
sinceramente non ne ho mai usati, fino ad ora non ne ho avuto esigenza, in linea di massima li sconsigli ? in che senso rischi di bloccare i dati ? nel senso che se và storto qualcosa la tabella mi rimane bloccata fino al riavvio del servizio Sql ?

e comunque alla fine ho risolto inserendo una nuova colonna nella tabella principale invece di creare un ulteriore tabella, questo perchè per le mie esigenze ho considerato il fatto che tanto un utente non può avere più di un proprietario.
Sempre in riferimento a ciò mi viene in mente un altra domanda, cerco di spiegarti senza allegare nuovamente il diagramma della tabella.
Praticamente, come ti dicevo prima, ho aggiunto una colonna di tipo uniqueidentifier chiamata "UserIdOwner" e questa crea una relazione con una PK di un altra tabella che non si vede nel disegno, praticamente una colonna identica a quella che cè già "UserId" e fin qui tutto ok.
In alternativa a questa soluzione avrei potuto creare una colonna di tipo int "IdOwner" uguale a quella che cè già "Id", ovviamente non autoincrementale, però poi avrei dovuto creare una relazione tra "IdOwner" e "Id", quindi una relazione tra due colonne della stessa tabella il che non mi faceva impazzire come soluzione anzi visto dal diagramma mi faceva proprio ribrezza vedere un collegamento che iniziava e finiva nella stessa tabella, e così ho deciso per la soluzione precedente.
Mi viene però la curiosità di sapere se è consuetudine fare una cosa del genere, è una normale prassi là dove le esigenze lo richiedono oppure no?
se non avessi avuto la colonna "UserId" sarei stato costrtto a farlo...







Andrea Restucci - Web Developer

alx_81 Profilo | Guru

>Parlo sempre da profano quale sono, in riferimento al DELETE
>non è sempre meglio, là dove possibile, avere un operazione a
>cascata? non è un modo anche questo di garantire l'integrità dei dati?
>io cerco sempre di impostarla o CASCADE o SET NULL là dove possibile...
la Foreign key, di per sè, se provi a cancellare un padre, ti fa già i controlli di integrità referenziale, per non farti lasciare orfani. Quindi personalmente preferisco gestire l'errore, grazie al quale capisco che ci sono ancora figli che non posso (e molto spesso non voglio) cancellare. SET NULL secondo me ti potrebbe invece dare più problemi che altro. Non solo per le join che già hai scritto (non è detto che qualcuna di esse debba escludere il record dopo il tentativo di cancellazione) ma anche perchè NULL porta sempre una gestione applicativa che può lanciare errori (ma questo non è legato alla relazione, è un argomento generico).

>tornando invece al problema in effetti come da tuo suggerimento
>e anche da altri suggerimenti ricevuti in rete a quanto pare
>sarebbe meglio o un SP o fare una Transaction piuttosto che un trigger.
>sinceramente non ne ho mai usati, fino ad ora non ne ho avuto
>esigenza, in linea di massima li sconsigli ? in che senso rischi
>di bloccare i dati ? nel senso che se và storto qualcosa la tabella
>mi rimane bloccata fino al riavvio del servizio Sql ?
Sì, perchè il trigger è:
- molto nascosto
- se scritto nella stessa transazione la rende più grande (e questo porta tempi lock maggiori)
- per i miei gusti (ma sono miei eh) troppo nidificato e poco controllabile

per questo preferisco (anche a fini di debug) profilare una sp oppure utilizzare un oggetto TransactionScope di .net per gesire l'atomicità della transazione (anche combinati vanno bene).

>Sempre in riferimento a ciò mi viene in mente un altra domanda,
>cerco di spiegarti senza allegare nuovamente il diagramma della
>tabella.
>Praticamente, come ti dicevo prima, ho aggiunto una colonna di
>tipo uniqueidentifier chiamata "UserIdOwner" e questa crea una
>relazione con una PK di un altra tabella che non si vede nel
>disegno, praticamente una colonna identica a quella che cè già
>"UserId" e fin qui tutto ok.
>In alternativa a questa soluzione avrei potuto creare una colonna
>di tipo int "IdOwner" uguale a quella che cè già "Id", ovviamente
>non autoincrementale, però poi avrei dovuto creare una relazione
>tra "IdOwner" e "Id", quindi una relazione tra due colonne della
>stessa tabella il che non mi faceva impazzire come soluzione
>anzi visto dal diagramma mi faceva proprio ribrezza vedere un
>collegamento che iniziava e finiva nella stessa tabella, e così
>ho deciso per la soluzione precedente.
Beh avresti fatto una parent child sulla stessa tabella e poi avresti potuto sfruttare la ricorsione per farti una gerarchia..

>Mi viene però la curiosità di sapere se è consuetudine fare una
>cosa del genere, è una normale prassi là dove le esigenze lo
>richiedono oppure no?
Dove hai una parent child che puoi fare all'interno della stessa tabella non ci sono grosse controindicazioni.
C'è sempre da fare quello che è comodo e utile in rapporto al tempo che hai e alle performance che dovrai avere (unitamente all'utilizzo che ne fai, le gerarchie sono gestite in realtà in vari modi).

Io ho avuto spesso tabelle in self-join con loro stesse per relazioni parent-child. E sono state veramente molto efficaci laddove ogni nodo doveva essere spostato.
In altri casi ho seguito la via del materialized path perchè mi dava maggiore velocità in lettura (ma mintore in updates e scritture "dentro" all'albero creato).
Alessandro Alpi | SQL Server MVP
MCP|MCITP|MCTS|MCT

http://blogs.dotnethell.it/suxstellino
http://suxstellino.wordpress.com
http://mvp.microsoft.com/profiles/Alessandro.Alpi

andrestu Profilo | Expert

grazie Alessandro,
come semnpre molto preparato, forse però tanti argomenti andrebbero sviscerati da parte mia vista la scarsa preparazione, solo che non ne ho il tempo e forse per il momento neanche l'esigenza.
Uno su tutti però mi preme, il discorso sul CASCADE della FK, io praticametne lho messa ovunque nel mio db e non sono poche le relazioni impostate così, mi hai demolito in un istante una mia convinzione probabilmente errata
Però a questo punto vorrei capirci meglio, cioè amettiamo che nella progettazione ho fatto molta attenzione a capire se il record a cascata deve rimanere o no a seguito di un DELETE, e amettiamo anche che non faccio un uso massiccio di JOIN a parte qualche vista (utilizzando un ORM casalingo gestisco tutto tramite oggetti) a questo punto continuo a vederci un enorme vantaggio l'impostazione del CASCADE sul DELETE, cioè in caso contrario, come da tua indicazione, dovrei rilevare lato codice ad ogni DELETE l'errore, cioè praticametne quasi sempre e lanciare un ulteriore DELETE su tutti i record a cascata, mi sembra un lavoro supplementare eccessivo dal momento che posso rendere automatica l'operazione.
Poi forse mi sbaglio non avendo molta esperienza in progettazione DB ma così "a naso" mi sembra un automatismo molto comodo...



Andrea Restucci - Web Developer

alx_81 Profilo | Guru

>grazie Alessandro,
>come semnpre molto preparato, forse però tanti argomenti andrebbero
>sviscerati da parte mia vista la scarsa preparazione, solo che
>non ne ho il tempo e forse per il momento neanche l'esigenza.
esatto, se non hai esigenza, cerca sempre la soluzione che "fitta" i tuoi requisiti.
Coi tempi che di solito abbiamo è veramente dura formarsi sempre alla perfezione.
Cerca sempre di vedere se qualcuno ha seguito un po' quello che devi fare e la cosa già aiuta.

>Uno su tutti però mi preme, il discorso sul CASCADE della FK,
>io praticametne lho messa ovunque nel mio db e non sono poche
>le relazioni impostate così, mi hai demolito in un istante una
>mia convinzione probabilmente errata
>Però a questo punto vorrei capirci meglio, cioè amettiamo che
>nella progettazione ho fatto molta attenzione a capire se il
>record a cascata deve rimanere o no a seguito di un DELETE, e
>amettiamo anche che non faccio un uso massiccio di JOIN a parte
>qualche vista (utilizzando un ORM casalingo gestisco tutto tramite
>oggetti) a questo punto continuo a vederci un enorme vantaggio
>l'impostazione del CASCADE sul DELETE, cioè in caso contrario,
>come da tua indicazione, dovrei rilevare lato codice ad ogni
>DELETE l'errore, cioè praticametne quasi sempre e lanciare un
>ulteriore DELETE su tutti i record a cascata, mi sembra un lavoro
>supplementare eccessivo dal momento che posso rendere automatica
>l'operazione.
Il lavoro è supplementare, non c'è dubbio. Ma sai tu cosa succede. E sai cosa trappare tu.
E giri tu la logica delle relazioni. Prima uccido tuo figlio, e poi tuo padre perchè un figlio senza padre non può starci..
Ma ripeto, come detto nella prima frase, si tratta un po' anche di filosofia dire che qualcosa non è corretto.
Lungi da me dirti "hai sbagliato", avrebbe lo stesso valore delle frasi con "SEMPRE" e "MAI"

>Poi forse mi sbaglio non avendo molta esperienza in progettazione
>DB ma così "a naso" mi sembra un automatismo molto comodo...
Se la soluzione ti è comoda, è "rock solid", non devi per forza dare il database ad altri gestori (sai a volte io rispondo come se tutto il mondo fosse enterprise SOA ), beh segui la tua strada.
Ti dico solo, fai attenzione perchè dietro a designer e comodità c'è spesso un'anguilla che sfugge.. e quando sfugge poi sono cavoli amari (potrebbe non essere il tuo caso).
Insomma, sono per più controllo logico diretto che demandato.

Alessandro Alpi | SQL Server MVP
MCP|MCITP|MCTS|MCT

http://blogs.dotnethell.it/suxstellino
http://suxstellino.wordpress.com
http://mvp.microsoft.com/profiles/Alessandro.Alpi

andrestu Profilo | Expert

ok perfetto ho compreso a pieno il senso logico, per ora me ne sto così, diciamo che per le mie esigenze e per quel poco di tabelle che gestisco posso continuare a seguire "l'automatismo" concesso dal CASCADE sperando di non dover mai incappare nei cavoli.
Per fortuna ancora i "cavoli" non mi son mai capitati e immagino che non dev'essere bello trovarsi in una situazione del tipo migliaia di record nella tabella e domandarsi: " e questi da dove sono sbucati ?!?! " oppure altre diavolerie simili che solo SQL può concepire...

Se mai dovrà capitarmi una situazione simile le possibili soluzioni saranno due:
1 - pagare un professionista come te per farsi risolvere eventuali casini
2 - mandare tutto a cagare e andare a coltivare pomodori (lavoro molto più rilassante)

probabilmente vista la mia situazione economica e vista la pazienza ormai quasi esaurita che da buon developer devo avere per poter stare dietro a una miriade di aspetti che si moltiplicano di giorno in giorno, sono quasi certo che opterò per la seconda

grazie ancora per il tempo dedicato
Ciao alla prossima

Andrea Restucci - Web Developer

alx_81 Profilo | Guru

>probabilmente vista la mia situazione economica e vista la pazienza
>ormai quasi esaurita che da buon developer devo avere per poter
>stare dietro a una miriade di aspetti che si moltiplicano di
>giorno in giorno, sono quasi certo che opterò per la seconda
sì ma non per le capacità.. ma per il bene che uno ha di sé stesso
pomodori a vita! Si sta da dio

Alessandro Alpi | SQL Server MVP
MCP|MCITP|MCTS|MCT

http://blogs.dotnethell.it/suxstellino
http://suxstellino.wordpress.com
http://mvp.microsoft.com/profiles/Alessandro.Alpi

andrestu Profilo | Expert

he he heeeee condivido a pieno...

Andrea Restucci - Web Developer
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