Newsgroup: it.comp.lang.visual-basic
Titolo: importare file di testo in un db

Ciao,
devo importare un file csv di circa 12000 record in un database. 
Il problema e' che devo compiere questa operazione piu' volte al
giorno. Il file e' sempre lo stesso ma cambiano i record. Questi
cambiamenti, in piu', riguardano solo un piccola parte dei dati.
Ho pensato di svuotare ogni volta la tabella e reinserire i dati
ma reputo sia una stupidata. 
Le differenze non sono sempre in coda :(
Avete un'idea?
Saluti
.yo.mo.

 Avete un'idea?
Crea una tabella identica a quella di destinazione.
Importa in quella.
Fai una query che elimina dalla tabella buona i record che ci sono nella
tabella temporanea.
Fai una query di INSERT INTO dalla temporanea alla tabella buona.
(prerequisito e' che tutto il sistema sia progettato bene.)
(cmq funzionerebbe sempre, anche se non e' il massimo)


Dipende in buona parte dal sapere se tu hai o meno una chiava primaria a cui
poter fare riferimento; ovvero se esistono una o piu' colonne del CVS che
identificano il record e sicuramente non cambiano tra un'operazione e
l'altra.
Se hai una chiave puoi valutare una cosa del genere:
Aggiungi una colonna alla tua tabella, oppure crea una seconda tabella di
appoggio con la chiave della prima piu' una colonna; in fase di
importazione, per ogni riga del tuo CSV, calcoli il CRC32 (o un qualche
algoritmo di hash) della stringa e lo memorizzi nella colonna aggiunta, il
"giro" successivo confronti il valore calcolato con una SELECT e se non
corrisponde aggiorni il record sulla base della primary key, viceversa passi
oltre.
Questo sistema potrebbe in parte funzionare anche senza chiave, nel senso
che riesci a distinguere i record esattamente uguali ma non sai come
comportarti con gli altri, che andrebbero per forza eliminati tutti e
reinseriti.
Vedi un po'... ciao
-- 
Luca Dormio - 
luca....@tin.it
________________________________
"Marty, non stai ragionando in maniera quadridimensionale"
Dr. Emmett L. Brown

 Importa in quella.
Ci aveve pensato ma volevo evitare di fare ogni volta 12000 insert
sul db. Mi sembra poco elegante alla luce del fatto che la maggior
parte dei dati esiste gia'.
Ciao
.yo.mo.

 parte dei dati esiste gia'.
Ok, pero' se il sistema e' progettato male non e' che puoi rimediare te
facendo i miracoli.
Cioe', se io ho un file con 12000 righe, lavoro su quello, e poi voglio
buttare i dati modificati su un DB, almeno mi metto nelle condizioni di
segnarmi quali sono quelli modificati.
Altrimenti, se non puoi fare cosi', o butti su una tabella temporanea e poi
metti in join totale le due tabelle (nel caso in cui tu abbia un max di 7-8
campi), oppure ti scorri tutti i record con un po' di codice ed amen.

 
L'idea mi piace. 
calcolo l'hash e controllo se esiste. 
Se esiste vado avanti altrimenti controllo se esiste la chiave. 
Se esiste faccio un update altrimenti un insert.
Dici che magari potrebbe essere il caso di caricare da subito in
due recordset gli hash e le chiavi invece di fare ogni volta una
select? O carico troppi dati inutili in memoria?
Ciao
.yo.mo.

 select? O carico troppi dati inutili in memoria?
Hai detto che l'ordine di grandezza e' 12.000 record, arrotondiamo per
tenerci larghi a 50.000 e supponiamo che la tua chiave sia un intero a 32bit
cosi' come il codice hash: tenere in memoria una connessione ADO aperta a
Access e un recordset static lato client con 2 colonne di interi a 32bit x
50.000 record occupa, sul mio PC, circa 4 MB.
Vedi tu cosa ti conviene...
Ciao


 oltre.
Scusa, Luca, ma non ho mai lavorato con le chiavi HASH e pochissimo con i
CRC32.
Per quel poco che so, sono entrambi valori che non sono necessariamente
univoci, o no?

 In fondo ti porterà via quei 2-3 secondi...
Beh, magari e' il mio PC che e' inchiodato, ma su un P4 2.8Ghz,
connettendomi in locale ad una tabella access semplicissima con un campo
contatore e un altro campo Long, 12.000 insert "hard-coded" ci mettono 10
secondi circa... immagino che, aggiungendo la scansione del file CVS e un
numero di colonne piu' elevato, un minutino ci voglia.
Ma al di la' del tempo, che puo' essere comunque basso, reinserire piu'
volte al giorno tutti quei record genera comunque un sacco di attivita'
inutile: se il DB e' Access una compattazione al giorno ti tocca sicuro, se
il DB e' qualcos'altro su server fai traffico di rete pure non del tutto
trascurabile (e temo che un minuto in quel caso non basterebbe)
In generale, tieni "impegnata" la tabella molto piu' a lungo, e suppongo che
tutti quegli aggiornamenti giornalieri debbano essere fatti perche' ci sono
altri programmi che nel frattempo leggono quei dati.
Certamente la soluzione svuota & carica e' la piu' semplice a livello di
codice e magari, all'atto pratico, risultera' comunque la piu' conveniente;
nei nostri programmi e' una cosa che facciamo spesso, ma li' l'ordine di
grandezza e' blocchi di decine di record a volta; con tutti quei record
anche a me disturberebbe un po' l'idea, sapendo che ogni volta ne cambiano
solo pochi...


 ogni volta ne cambiano solo pochi...
Quindi la soluzione quale potrebbe essere?
bye
-- 
Esistono 10 tipi di persone: chi conosce il binario e chi no.
Gestione Ottica - Gestionale per Ottici e Programmi Gratuiti su:
http://www.nicolaottomano.it


Vedi altra risposta per una possibile idea...


 trascurabile (e temo che un minuto in quel caso non basterebbe)
Il problema e' proprio questo. 
Il server e' MSSQL e il mio db non e' nemmeno l'unico. 
Anzi, diciamo che sono un ospite e vorrei disturbare il meno possibile.
L'hash mi piace perche' posso sapere, con due select, quali sono i dati
presenti e quali quelli che devo modificare. 
Ho a disposizione anche un campo timestamp per capire quali sono i dati
che non mi servono piu'. 
Anche se non e' la soluzione ottimale e' quella mi soddisfa di piu'.
ciao
.yo.mo.

 
L'occupazione di memoria e' accettabile ma la velocita' no. :-(
Al momento carico un recordset con i due campi (chiave e md5) e
poi utilizzo il metodo filter per le ricerche ma ci vogliono 15
minuti per scorrere un file da circa 3 Mb.
Un'alternativa a questo metodo?
ciao.
.yo.mo.

 Un'alternativa a questo metodo?
un collega mi ha illuminato :)
1) carico un recordset formato da due campi (chiave hash)e lo
   trasformo in stringa usando .getstring
2) carico tutto il file e lo divido in array usando clrf come 
   separatore.
3) scorro l'array con un ciclo e se trovo la chiave procedo a
   calcolare l'md5 e lo confronto con quello recuperato dalla
   basedati. Se e' uguale scarto la riga altrimenti faccio un
   update. Se non si trova la chiave faccio un insert.
Che ne dite?
Ancora non ho provato le prestazioni ma sono fiducioso.
Ciao
.yo.mo.