Newsgroup: it.comp.lang.delphi
Titolo: Gestire integrita' referenziale da programma

Salve a tutti, ho un problema decisamente "pesante". Ho la necessita' di
gestire le relazioni tra tabelle a livello di programma, poiche'
l'applicazione dovra' girare su un database di tipo "qualunque" e quindi non
posso appoggiarmi a questa o a quella particolare funzione dei vari RDBMS.
Diciamo che (in teoria, e' un'ipotesi remota) dovrei poter installare tutto
utilizzando Paradox, usare il programma, trasferire tutto su SQL Server
(cambiando i puntamenti al DB e la configurazione di accesso, ovviamente)
senza che il programma se ne accorga. Mi ritrovo quindi a dover gestire "a
mano" i casi in cui vengono cancellati, ad esempio, articoli utilizzati da
altre parti (e quindi devo impedirne la cancellazione), oltre a dover
aggiornare tutte le tabelle "dettaglio" quando vengono variati i dati chiave
di una tabella testata, in modo da non perdermi per strada la relazione. A
complicare il tutto ci sono altri problemi, tra i quali il fatto che per
ogni tabella "testata" ci sono "N" tabelle di dettaglio (ad esempio gli
articoli vengono utilizzati per fare le bolle, per compilare dei registri e
per altri vari motivi), e, a loro volta, le tabelle di dettaglio possono
fare da testata per altre cose. Visto che diventa molto pesante gestire
tutti questi casi, cercavo un sistema "generico" in modo da poter agganciare
l'evento di modifica/cancellazione a ogni tabella e fare in modo che ognuna
pensi da sola a cercarsi i propri dettagli e a fare le dovute verifiche.
Mi rendo conto che non e' molto facile affrontare questo problema senza
conoscere il database, ma si tratta di oltre 300 tabelle e non potrei in
ogni caso inviarvi tutto, quindi mi accontento di qualche suggerimento. =)
Grazie e scusatemi per il post lungo
Ciao
Daigo

Mi rendo conto che il tuo problema è "pesante".
Visto che non hai alternativa io mi costruirei un sistema basato su due
tabelle: padri e figli dove vai a indicare la relazione che c'è tra padri e
figli e poi, in base alla tabella che stai gestendo fai i dovuti controlli
scrivendo una semplice funzione da chiamare.
Io ho affrontato un caso molto simile e l'ho risolto in questo modo.
Se hai problemi contattami in privato.
Ciao
Solid Snake IT

 scrivendo una semplice funzione da chiamare.
Ci avevo pensato anche io, pero' mi rimane il problema di dover trovare un
modo veloce per fare tutto. Senza contare che il discorso va fatto su un DB
utilizzato anche da decine di utenti, e devo evitare di incasinare tutto...
Pensa al caso in cui, partendo dalla tabella A, comincio a controaggiornare
B, C, D, E, F e cosi' via, e intanto un utente mi cambia qualcosa sulla
tabella Z... Sono fregato.
Un altro problema deriva dal fatto che io ho relazioni "a cascata". Ti
faccio un esempio
Tabella Articoli
CODICE
Tabella Testata (in relazione con Articoli tramite COD_ARTICOLO)
COD_ARTICOLO
CAMPO1
Tabella Dettaglio (in relazione con Testata tramite COD_ARTICOLO + CAMPO1)
COD_ARTICOLO
CAMPO1
CAMPO2
Modificando Testata, verrebbe aggiornata anche Dettaglio (e fin qui tutto
ok), ma se modificassi Articoli? Alla fine dovrei tenere in piedi decine di
relazioni "fittizie", ovvero dovrei mettere in relazione Dettaglio con
Articoli in modo da aggiornare il valore, mentre mi piacerebbe che Articoli
modificasse solo Testata, e poi di conseguenza Testata cercasse le SUE
relazioni e le ribaltasse su Dettaglio, in modo da mantenere solo le
relazioni vere e proprie. Sempre piu' complicato, eh? =)
Ciao
Daigo

Questo è un discorso che non è molto comodo da farsi via e-mail.
Cmq:
1) Tu hai detto che le tabelle sono paradox...giusto ?
2) Se fossero paradox o dbase potresti utilizzare il locktable per bloccare
le tabelle nel momento in cui fai la transazione di modifica delle
relazioni...(questo è il primo scoglio che devi superare. E' chiaro che se
non hai possibilità di modificare, bloccando le tabelle, non potrai mai fare
niente !)
3) Per quanto riguarda le tabelle d'appoggio che devi creare io farei:
    a) TABELLE (contiene TUTTE le tabelle)
        es.
            NOMETABELLA (varchar(32))            CAMPO_PK
            ARTICOLI                                            (metti il
campo primary key separato da ";" se sono più campi)
            TESTATAORDINI
            DETTAGLIOORDINI
            ...
    b) LINKS
        es.
            NOME TABELLA (varchar(32))        FIGLIO (varchar(32))
CAMPOFK
            è il link alla tabella TABELLE              è sempre un link
alla tabella TABELLE        (metti il nome del campo di foreign key sempre
separato da ";" se hai più campi)
4) Quando viene fatta una modifica su ARTICOLI piuttosto che ORDINI blocchi
le tabelle, parti con una bella transazione (puoi farla anche con paradox o
dbase in modo simulato), e fai una query con:
    SELECT
    TABELLE.CAMPO_PK,
    LINKS.FIGLIO,
    LINK.CAMPOFK
    FROM
    TABELLE, LINKS
    WHERE NOMETABELLA = :nometabella
    dove in :nometabella metti Uppercase(tuatabella.TableName)
5) Ad ogni record trovato costruisci un'istruzione SQL tipo questa:
    UPDATE <nome tabella trovata> SET <nome campo foreign key> = <valore del
campo PK trovato>
6) Commit della transazione con sblocco delle tabelle.
Lo scopo è aggiornare i campi FK delle tabelle che dipendono da quella presa
in esame.
ho capito giusto ?
ciao
Solid Snake

 Ho capito giusto ?
Esatto, ma alla fine non potro' farlo perche' si complica troppo il
funzionamento del programma (ogni soluzione genera altri problemi, e tempo
che mi e' stato dato e' pochissimo. Magari affrontero' la questione in
futuro).

Nel messaggio precedente non mi sono firmato e nemmeno ho ringraziato Solid
Snake... Sono proprio cotto... In ogni caso grazie per i suggerimenti.
Ciao
Daigo

gestire le relazioni tra tabelle a livello di programma
non e' possibile: non puoi garantire l'integrita' referenziale,
in ambiente multi utente, affidando al programma i controlli
del caso.

 ha scritto nel messaggio
news:8v5ki9$4lh$2...@lacerta.tiscalinet.it...

Devo farlo per forza, da li' non si scappa... Non so a priori su che
database girera' il programma, e in ogni caso non posso stare a studiarmi
tutti gli RDBMS per capire come generare le relazioni in automatico, visto
che ognuno lo fa in modo diverso...
Come faccio? =(
Daigo

che ognuno lo fa in modo diverso...
un'architettura a driver ?
scusa, non ti capisco: e' un problema di tempo ?
se e' un problema di tempo chiedi al cliente il tempo
necessario (lavori per qualcuno ?)
in ogni caso tutti gli sql server (proprio perche' usano sql)
hanno una gestione standard dell'integrita' refereziale, per
access e paradox la cosa puo' essere molto diversa, nel caso
in cui risulti troppo complesso/impossibile puoi sempre escludere
questi tipi di db.
mi spiace ma piu' di questo non posso dirti, se hai domande
piu' specifiche o se vuoi rimettere in discussione le basi
del tuo progetto saro' lieto di aiutarti (nelle mie minime possibilita')

Ciao, ti ringrazio per i suggerimenti. Ti spiego qual'e' il mio problema:
come gia' sai devo fare un programma che giri su qualunque DB (in teoria),
ma ci sono alcune complicazioni:
1) devo interfacciarmi a un programma gia' esistente, usando una parte dei
SUOI dati (programma che NON USA alcun tipo di indice, chiave primaria,
integrita' referenziale, ecc. ecc. nei suoi dati, e io non posso aggiungere,
ne' togliere, ne' modificare nulla alla struttura del DB. Posso solo
aggiungere o togliere dati, con il rischio di rovinare comunque qualcosa
visto che nemmeno questo programma si accorge di nulla se tronco una testata
documento e lascio le righe).
2) Il tempo e' quello che e': fine dicembre, punto, e DEVE essere finito (se
ti dico anche quanto tempo mi danno per lavorarci in una settimana ti metti
a ridere).
3) Il database del mio programma esiste gia', ed e' gia' quasi completo
(relazioni a parte. O meglio, le relazioni gia' ci sono, ma NON nel
database). Ristrutturarlo a questo punto non e' possibile, significherebbe
rifare il programma (mesi di lavoro buttati all'aria...).
Il fatto e' che l'integrita' referenziale non era poi cosi' indispensabile,
all'inizio, visto che e' stato messo su per la monoutenza. Molti controlli
vengono gia' fatti, ma se sono in multiutenza (cosa che doveva essere
attivata fra almeno un anno, e non un mese) cambia tutto, e adesso sono
fregato...
Hai qualche "suggestione"?
Daigo
PS: ho anche notato un problema mica da poco... Su SQL Server non capisco
come funziona il lock dei record e delle tabelle... Se metto una riga in
Edit con una TTable chiunque puo' modificarla e non succede nulla. Per
quanto riguarda il lock delle tabelle, invece, sono ancora piu' indietro:
uso alcune tabelle che vengono svuotate e ricalcolate ogni volta, quindi mi
servirebbe trovare il sistema di bloccare alcune funzioni del programma
mentre qualcun altro le sta usando. Ad oggi non ho ancora trovato il sistema
di farlo...

di farlo...
allora non sei in mono utenza !   :-O
le tabelle potrebbero essere permanenti e ogni utente potrebbe
lavorare solo sulle righe identificate da quell'utente, oppure il nome
delle tabelle potrebbe contenere un'identificativo di utente...
in ogni caso costruire un programma indipendentemente dal
tipo di database che dovra' utilizzare e' un'impresa davvero
ardua, pensa che io mi preoccupo se devo gestire anche solo
due versioni diverse del medesimo sqlserver...  ;-)


Dillo a me... E per di piu' lavorare su SQL Server per l'80% del tempo e poi
sentirsi dire "Deve funzionare su DB2", e scoprire che tutti i campi
booleani che hai usato dovranno essere cambiati in integer (e la loro
gestione di conseguenza) perche' il DB2 non ha i booleani... Fantastico...
=(
Comunque grazie per l'aiuto. Ciao =)
Daigo

=(
non smettero' mai di dirlo: in sql il tipo boolean non esiste.
auguri !    ;-)

 non smettero' mai di dirlo: in sql il tipo boolean non esiste.
Questo non lo sapevo. Io l'ho visto usare in piu' posti, pensavo fosse
standard (in fondo l'informatica in se' si basa sui booleani), ma alla fine
ho capito che non e' cosi'. L'avessi saputo prima...
Ok, mi rimbocco le maniche e rompo il deretano a qualcuno. ;)
Ciao
Daigo