Newsgroup: it.comp.lang.visual-basic
Titolo: [Lungo] Chi sa sbrogliare questa matassa?

E' un problema che devo risolvere per estrapolare dati da un database su un
server AS/400 a cui accedo via ODBC.
Ho una prima tabella, chiamiamola "Anagrafica Articoli", strutturata così:
codice --- descrizione
----------------------
00123       acqua
00555       vino
66000       limonata
C'è poi una seconda tabella, chiamiamola "Codici barre", con questi campi:
codice---barcode
------------------
00123    200123A
00555    200555A
00555    200555B
00123    200123B
00123    200123C
In quest'ultima tabella la chiave è data da "codice+barcode".
In pratica per ogni articolo si possono introdurre tutti i codici a barre
che si vogliono, in qualsiasi ordine.
Mi creo, quindi, una tabella intermedia "Temp" fatta così:
codice---descrizione---barcode
--------------------------------
00123    acqua             200123A
00555    vino                200555A
00555    vino                200555B
00123    acqua             200123B
00123    acqua             200123C
A questo punto ho la necessità di creare una nuova tabella con l'anagrafica
articoli dove,
però, in corrispondenza di ogni codice, oltre ai campi di "Anagrafica
Articoli", ci siano anche gli eventuali barcode. Quindi devo ottenere
qualcosa del tipo (la chiamerò "Tabella Finale"):
codice --- descrizione---barcode1---barcode2---barcode3
------------------------------------------------------------
00123       acqua            200123A    200123B    200123C
00555       vino               200555A    200555B
66000       limonata
Per il momento ho pensato solo a qualcosa in VB di questo tipo
cn.connectionstring = ...
cn.Open
SqlSource = "SELECT * FROM Temp;"
rsSource.Open SqlSource, cn                            'carico nel recordset
rsSource tutta la tabella Temp
Do while not rsSource.EOF
    'seleziona da Tabella Finale il record che ha lo stesso codice del
record attualmente puntato in rsSource
    SqlTarget= "SELECT * FROM TabellaFinale WHERE codice = " &
rsSource!codice & ";"
    rsTarget.Open SqlTarget, cn
    if rsTarget.EOF then
        'Se in Tabella Finale non esiste già il record corrispondente
all'attuale rsSource!codice
        rsTarget.AddNew
    else
        rsTarget!codice = rsSource!codice
        rsTarget!descrizione = rsSource!descrizione
        'riempi il primo campo barcode libero
        if IsNull(rsTarget!barcode1) then
                rsTarget!barcode1 = rsSource!barcode
                Goto ProssimoRecord
        end if
        if IsNull(rsTarget!barcode2) then
                rsTarget!barcode2 = rsSource!barcode
                Goto ProssimoRecord
        end if
        if IsNull(rsTarget!barcode3) then
                rsTarget!barcode3 = rsSource!barcode
                Goto ProssimoRecord
        end if
ProssimoRecord:
        rsTarget.Update
        'Carica il record successivo
        rsSource.MoveNext
Loop
Giunti a questo punto, vi dico che complessivamente ho ottenuto il risultato
voluto. "Cazzo rompi allora?" vi chiederete. Credo che il metodo non sia il
migliore: la tabella Temp contiene 46.000 record e in questo modo funziona
molto speditamente solo per i primi 10.000, poi rallenta esasperatamente
perché per ciascun record fa una query nella tabella finale per vedere se
esiste già e, di conseguenza, l'aggiunge o l'aggiorna. Questo programma lo
userò tre volte in tutta la mia vita, però mi piacerebbe capire se ci sono
alternative. Inoltre mi ha dato un inghippo: dopo circa 29.000 record
processati ha restituito un errore 6 di runtime, un bel overflow. Ho risolto
facendolo ripartire caricando Temp solo dall'ultimo record inserito in
Tabella Finale. Tuttavia, mi chiedo come sia possibile dato che in memoria
carica sì tutta la tabella originale in rsSource, ma di "Tabella Finale"
carica e scarica un solo record alla volta, quindi in fin dei conti occupa
uno spazio grande quanto rsSource + 1 record.
Se siete arrivati a leggere fin qua vi meritate tutta la mia sincera
gratitudine. Se poi mi poteste dare anche una risposta, boh?!, chiederò a
quelli di Striscia la Notizia se per Natale possano mandare il buon
Iacchetti a portarvi un panettone! :)
Mal che vada, spero che a qualcuno possa servire il sorgente che ho postato.
Ciao e grazie!
Alex
--
Private replays to 
not.to....@geocities.com
Remove "
not.to
."!!

ma io barcode sono al massimo 3???
un L2K contrario al quoting se non espressamente necassario :)

Utilizza dei recordset sconnessi... vedrai che le performance aumenteranno 
-- 
Posted via Mailgate.ORG Server - 
http://www.Mailgate.ORG

Francamente non vedo come possa usare dei recordset disconnessi.
Non credo che sia opportuno caricarci in memoria 46.000 record ...
altro che overflow poi ...
Ciao Andrea

supponendo che alla domanda del msg precedente tu risponda "SI" ho buttato
giu una procedurina che dovrebbe farti risparmiare tempo
utilizza "MsDataShape" che è installato di default con ADO quindi no problem
per utilizzarla ho creato un database ACCESS con le tabelle "anagrafica
(codice as string, descrizione as string)", "barcode (codice as string,
barcode as string)", "totale (codice as string, descrizione as string,
barcode1 as string, barcode2 as string, barcode3 as string)"
successivamente per comodita ho aggiunto il DSN di sistema in Pannello di
controllo chiamandolo "dbone"
da VB  : "Nuovo progetto" -> "Project" -> "References" -> "Microsoft ActiveX
Data Object 2.7 Library" (vanno bene tutte le versioni)
aggiunto "command1 al form" e aggiunto codice dopo la firma
Fammi sapere se migliorano le prestazioni e di quanto visto che non ho mai
usato il SHAPING
Ciao
un L2K davanti al libro "Universal Data Access con Visual Basic e ADO di ROB
MACDONALD edizione Mondadori Informatica"
--CODE--
Private Sub Command1_Click()
    Dim Cn As Connection
    Dim Rs As Recordset
    Dim subRs As Recordset
    Dim rsTot As Recordset
    'Inizializzo risorse
    Set Cn = New Connection
    Set Rs = New Recordset
    Set rsTot = New Recordset
    'Apro i RecordSet e la connessione
    Cn.Open "Provider=MSDataShape.1;Persist Security Info=False;Data
Source=dbone;Data Provider=MSDASQL"
    Rs.Open "shape {select * from anagrafica} append ({select * from
barcode} relate codice to codice) as barcodes", Cn
    rsTot.Open "select * from totale", Cn, adOpenKeyset, adLockOptimistic
    With Rs
        While Not .EOF
            rsTot.AddNew
            rsTot.Fields("codice").Value = .Fields("codice").Value
            rsTot.Fields("descrizione").Value = .Fields("descrizione").Value
            'inizializzo recordset dei barcodes e li inserisco nel DB
            Set subRs = Rs.Fields("barcodes").Value
            x = 0
            While Not subRs.EOF
                x = x + 1
                rsTot.Fields("barcode" & CStr(x)).Value =
subRs.Fields("barcode").Value
                subRs.MoveNext
            Wend
            Set subRs = Nothing
            rsTot.Update
            .MoveNext
        Wend
    End With
    MsgBox "Fatto"
    'libero risorse
    rsTot.Close
    Rs.Close
    Cn.Close
    Set rsTot = Nothing
    Set Rs = Nothing
    Set Cn = Nothing
End Sub
--END CODE--

un ultima cosa
La procedura non dovrebbe occupare moltissimo la memoria di sistema in
quanto tutti i recordset ado utilizzano una cache che viene riempita
gradualmente e rilasciata nel momento in cui non hai bisogno
ciao
L2K

 un ultima cosa
Domattina, appena metto piede in ufficio, provo subito! Intanto ti
ringrazio, poi ti farň sapere. (Il panettone dove lo faccio portare? ;) )
Ciao!
Alex


....omissis
Fermati quì.
Tu hai una tabella Anagrafica Articoli con un suo codice (che suppongo sia
chiave primaria).
Hai una tabella di corrispondenza Codice - BarCode con ambedue i campi
definiti chiave.
In Maschera Articoli puoi mettere una listBox per vedere, modificare,
aggiungere ed eliminare BarCode associati a quel codice articolo.
Qualunque programma di lettura BarCode leggerà la tabella di corrispondenza.
Che altro ti serve?
saluti
GB

 GB
Lo scopo di questo lavoro è esportare oltre 46.000 record da un AS/400 a un
sistema Unix. Fatto il lavoro butto la tabella. Grazie comunque.
Ciao.
Alex

 ha scritto nel messaggio
news:a29cfn$vq6p7$1...@ID-126178.news.dfncis.de...

Allora, tutto bene a parte un paio di inghippi. Il problema più grosso,
però, è di nuovo l'overflow (questa volta dopo 32.000 record). Non ho idea
da cosa dipenda. E tu? Troverei interessante, se sei d'accordo e ne hai
voglia, risolverlo.
Parliamo di prestazioni: con SHAPE ci ha impiegato qualche minuto, prima che
si bloccasse per overflow, contro un'oretta e mezza. Che ne dici? Niente
male, eh?
Stavo pensando anche a un'altra cosa: in realtà io so a priori che al
massimo posso avere 10 barcode per articolo (nell'esempio avevamo detto 3)
perché era una limitazione del nostro vecchio gestionale ma, come ho detto,
in teoria con il nuovo potrei averne nessuno o infiniti. Se volessi fare in
modo di aggiungere un campo alla tabella di destinazione ogni volta che
scopro che c'è un barcode in più per il quale non ci sono campi disponibili
come potrei procedere? Prima di tutto dovrei aggiungerlo nel recordset, ma
come?
Sono fuori sede fino giovedì, quindi non so se riuscirò a rispondere subito
alla conversazione.
Ciao.
Alex

 alla conversazione.
PS : Aspetto e intanto faccio delle prove ;)



non puoi prendere in considerazione l'idea di avere una tabella con 
codice articolo - barcode collegata uno a molti?
Saluti.
Emanuele.