SlideShare a Scribd company logo
1 of 72
Download to read offline
UNIVERSITÀ DEGLI STUDI DI TRIESTE




             FACOLTÀ DI INGEGNERIA

                  Corso di laurea triennale in
                   Ingegneria Informatica

                       Tesi di laurea in
                 Sistemi Informativi Aziendali




 “Migrazione della base di
    dati operativa di un’
 assicurazione vita diretta”

Laureando:                                          Relatore:
Piero De Tomi                chiar.mo prof. Leonardo Felician




                Anno Accademico 2008-2009
                                2008-
Migrazione della base di dati
operativa di un’ assicurazione vita
              diretta
Indice

                                                                             Pg.

1. Perché migrare da Access a SQL Server?                                     1

2. Gli obiettivi della migrazione del sistema informativo di OnLife           3

3. I tool di migrazione “già pronti” e la scelta di una soluzione “ibrida”    6

       3.1 Considerazioni e conclusione                                       7

4. Elaborazione e pianificazione di una strategia di migrazione ben           9
   pensata e ordinata
5. Le cose che bisogna sapere prima di iniziare la migrazione                11

       5.1 Le “debolezze” dell’ Upsizing Tool di MS Access                   11

               5.1.1 Gestione dei valori NULL sulle tabelle esportate        11

               5.1.2 Datatype corrispondenti su SQL Server                   12

               5.1.3 Migrazione delle relazioni                              14

                      - Relazioni tra campi di precisione diversa            14

                      - Relazioni in cui la Foreign Key ammette valori       15
                        NULL
                      - Conclusione                                          15

       5.2 Le principali differenze nelle query tra Access ed SQL Server     16

               5.2.1 L’ istruzione IIF                                       16

               5.2.2 L’ istruzione SWITCH                                    16

               5.2.3 La funzione ISNULL                                      17

               5.2.4 Confronti sulle date                                    17

               5.2.5 Filtri su query con valori booleani                     18

               5.2.6 Subqueries nella clausola FROM della query madre        18

               5.2.7 Uso della funzione InStr                                19

               5.2.8 Uso della funzione Format nelle date                    19
5.2.9 Uso della funzione DateAdd                                20

              5.2.10 Uso delle funzioni come CInt e CLng                      21

              5.2.11 Query con l’ operatore LIKE                              21

              5.2.12 Concatenazione di stringhe: "&" e "+"                    21

              5.2.13 Casting di un valore numerico a stringa                  22

              5.2.14 Utilizzare nelle subquery gli alias definiti nella       23
                     query madre
              5.2.15 Le funzioni First e Last                                 23

6. La migrazione “in locale”                                                  26

       6.1 Creazione di un nuovo database su SQL Server                       26

       6.2 Creazione di un nuovo Progetto di Microsoft Access (*.adp) e       27
           collegamento al server in locale
              6.2.1 Importazione dei moduli e delle classi nel progetto       29
                    Access
       6.3 Migrazione della struttura della base di dati                      29

              6.3.1 Migrazione delle tabelle                                  30

              6.3.2 Ricostruzione delle relazioni                             31

              6.3.3 Migrazione delle query                                    32

                     - Query parametriche e di data manipulation              32

                     - Query non parametriche                                 33

              6.3.4 Controlli e modifiche eventuali sulla nuova struttura     34
                    creata
                     - Valori NULL                                            34

                     - Modifiche sui datatype                                 34

       6.4 Aggiunta di nuove funzionalità al database migrato                 35

              6.4.1 Nuovi vincoli e proprietà per le tabelle e i lori campi   35

              6.4.2 Creazione di Triggers per la gestione di eventi           35

       6.5 Migrazione del back end del sistema informativo                    39
6.5.1 Importazione dei moduli/classi e maschere “vecchi”    40
                      nel nuovo progetto Access *.adp
               6.5.2 Modifica del codice contenuto nei moduli per la       41
                      compatibilità con il nuovo database su SQL Server
                       - La funzione ApreTabella                           42

                       - Modifica delle query annidate nel codice          44

                       - La proprietà RowSourceType                        46

                       - Caso particolare: l’ oggetto DAO.Database         47

               6.5.3 Il meccanismo di pseudo-paginazione dei risultati     49
                      nel back end di OnLife
               6.5.4 Test e Debug                                          50

7. La migrazione vera e propria                                            52

       7.1 Creazione della struttura del database sul server in rete       52

               7.1.1 La funzione “Script Table as...” di SQL Server        53

               7.1.2 Esecuzione degli script sul server in rete            53

                       - L’ ordine di esecuzione degli statements CREATE   54

       7.2 Scrittura di un piccolo software “ad-hoc” per la migrazione     54
           dei dati
               7.2.1 La necessità di introdurre un meccanismo di           55
                      automazione per la migrazione dei dati
               7.2.2 Il problema dell’ IDENTITY_INSERT e la sua            56
                      soluzione
               7.2.3 Stima del tempo di migrazione del database di         59
                      OnLife
       7.3 Installazione del sistema informativo in ambiente aziendale     62

               7.3.1 Collaudo e manutenzione                               63

Conclusioni                                                                64

Bibliografia                                                               65
Indice delle figure
Figura 1 – Un estratto della struttura del database di OnLife……….8
              Fonte : database del sistema informativo di OnLife.
Figura 2 – Creazione di un nuovo database tramite Microsoft SQL Server
           Management Studio……….27
              Fonte : elaborazione propria.
Figura 3 – La situazione dopo la migrazione del database di OnLife……….28
              Fonte : http://office.microsoft.com.
Figura 4 – Creazione di un nuovo progetto *.adp: schermata in cui vengono
           richiesti i parametri di connessione ad SQL Server……….28
              Fonte : elaborazione propria.
Figura 5 – Esportazione dei moduli e delle maschere dal file *.mdb……….29
              Fonte : elaborazione propria.
Figura 6 – Alcuni passi seguiti durante l’ upsizing del database……….30
              Fonte : elaborazione propria.
Figura 7 – Tabella di appoggio in cui sono state memorizzate le informazioni
           relative alle relazioni del database di OnLife……….31
              Fonte : elaborazione propria.
Figura 8 – Il primo passo per l’ importazione di moduli, maschere e
           classi……….40
              Fonte : elaborazione propria.
Figura 9 – Il secondo passo per l’ importazione dei moduli/classi e delle
           maschere……….41
              Fonte : elaborazione propria.
Figura 10 – La schermata dei Partner con i primi 50 risultati visualizzati……….49
              Fonte : Sistema Informativo di OnLife.
Figura 11 – Il software di migrazione sviluppato per la migrazione della base di
            dati di OnLife……….55
              Fonte : elaborazione propria.
Figura 12 – Il log del software di migrazione per OnLife……….59
              Fonte : elaborazione propria.
Figura 13 – Variazione del tempo di migrazione delle singole tabelle in funzione
            del numero di record……….61
              Fonte : elaborazione propria.




Indice delle tabelle
Tabella 1 – Tavola delle corrispondenze tra i datatype di Access ed SQL
            Server……….13
              Fonte : http://sqlserver2000.databases.aspfaq.com.
Tabella 2 – Esempio di tabella con ordinamento crescente secondo il campo
            “ID”……….24
              Fonte : elaborazione propria.
Tabella 3 – Tabella di esempio, con identità sul campo ID……….56
              Fonte : elaborazione propria.
Tabella 4 – Schema dei tempi medi di migrazione di alcune tabelle del
            database……….60
              Fonte : elaborazione propria.
CAPITOLO 1
   Perché migrare da Access a SQL
              Server?



La migrazione di un sistema informativo da un ambiente ad un altro è un
problema che spesso si presenta nelle aziende, quando si vede crescere con
sempre maggior velocità la mole di dati che il sistema stesso deve trattare e quindi
il carico delle applicazioni - in termini di dati - inizia ad incidere in maniera
significativa sulle prestazioni del sistema.
È questo il caso di OnLife, il cui sistema informativo inizialmente era composto
principalmente da un database e da un back end, usato per accedere ai suoi dati.
Sia il database che l’ applicativo sono stati sviluppati in Microsoft Access 2003,
uno strumento tanto semplice quanto potente per lo sviluppo veloce di buoni
prototipi di applicazioni.
Tuttavia, quando è stato sviluppato questo prototipo, il carico previsto
inizialmente non era lo stesso che il sistema deve sopportare oggi: nel tempo si è
passati da tabelle con qualche migliaia di record a tabelle (la situazione attuale)
con centinaia di migliaia di record. Si intuisce facilmente che un sistema
informativo realizzato con uno strumento come Access, più adatto a soluzioni
prototipali che a soluzioni “definitive”, non è più adatto ad una situazione del
genere.
È questo il motivo che ha dato la spinta decisiva verso la migrazione dei dati del
sistema da ambiente Access a SQL Server: un RDBMS (Relational Data Base
Management System) professionale, più adatto a gestire grandi quantità di dati in
maniera efficiente, robusta ed affidabile.

                                                                                  1
Bisogna però operare una distinzione importante tra Access ed SQL Server:
mentre Access offre la possibilità di definire strutture di database e al tempo stesso
sviluppare velocemente interfacce visuali (le cosiddette Maschere) tramite cui
accedere ai dati definiti, SQL Server è un RDBMS, ovvero un sistema per la
gestione di database. Ciò significa che con SQL Server non si possono sviluppare
interfacce per accedere ai dati.
Proprio per questo motivo, nel voler affrontare una migrazione del sistema di
OnLife da Access ad SQL Server, si sono presentate essenzialmente due
possibilità:


    •   Migrazione della base di dati e sviluppo completo di un nuovo back end in
        un     altro   ambiente,   eventualmente     usando     un   linguaggio    di
        programmazione diverso da quello usato precedentemente (si ricorda che
        il linguaggio nativo usato all’ interno di MS Access è il VBA, ovvero Visual
        Basic for Applications).
    •   Migrazione della base di dati e modifica del codice del back end
        preesistente, al fine di renderne corretto l’ interfacciamento con il nuovo
        database su SQL Server.


La scelta effettuata e la sua motivazione saranno oggetto del prossimo capitolo.




                                                                                    2
CAPITOLO 2
      obiettivi
  Gli obiettivi della migrazione del
   sistema informativo di OnLife



Di fronte a due possibili modalità di migrazione, la cosa più corretta da fare era
valutare tutti i pro e i contro per ognuna delle due soluzioni, per arrivare ad una
conclusione ragionevole.
Fermo restando il fatto che entrambe le alternative avevano in comune la
migrazione dei dati da Access a SQL Server, rimaneva da effettuare la scelta
riguardo il back end.
Il vantaggio dello sviluppo di un nuovo applicativo per l’ accesso ai dati risiedeva
nella possibilità di riprogettare completamente il sistema, rendendolo adatto – in
tutte le sue funzionalità – all’ interazione con il nuovo database su SQL Server.
Inoltre, dovendo partire da zero, sarebbe stato possibile scegliere un linguaggio di
programmazione più performante e adatto a questo tipo di lavoro.
D’ altra parte, scegliendo questa soluzione i tempi di sviluppo si sarebbero
dilungati notevolmente, il che costituiva un fattore di cui certamente si doveva
tenere conto, dal momento che la necessità di una migrazione era sempre più
incombente.
Il mantenimento dell’ applicativo originale comportava essenzialmente uno
svantaggio: il lavoro non sarebbe stato di sviluppo – come invece lo sarebbe stato
nel primo caso –, bensì di manutenzione adattativa/evolutiva: ed è chiaro che
solitamente, quando si effettua un qualsiasi tipo di manutenzione su un software,
c’ è una grossa percentuale di rischio di incorrere in regressioni e comportamenti
anomali del sistema in seguito ai cambiamenti operati.

                                                                                    3
Tuttavia bisognava considerare il fatto che un sistema già pronto e con una logica
applicativa già funzionante – su cui eventualmente fare manutenzione per
ottenere la compatibilità con SQL Server - era un buonissimo punto di partenza e,
probabilmente, anche un grosso risparmio di tempo.
Con queste considerazioni alla mano, la scelta non era per niente facile, anzi:
entrambe le alternative presentavano delle valide motivazioni per essere scelte ed
allo stesso tempo dei piccoli svantaggi da prendere in considerazione.
Un fattore che ha inciso molto nella predilezione di una soluzione piuttosto che l’
altra è stata la necessità di migrare il sistema in tempi contenuti, al massimo
qualche mese: la quantità di dati che il sistema doveva gestire e il carico che
doveva sopportare stavano crescendo ad una velocità considerevole.
Per questo motivo la scelta finale è caduta sulla seconda alternativa: mantenere il
sistema originale ed effettuare su di esso la manutenzione necessaria. In questo
modo il requisito della velocità dei tempi di migrazione sarebbe stato soddisfatto,
non dovendo progettare ex novo lo sviluppo di un nuovo applicativo.
Pertanto, l’ obiettivo stabilito per la migrazione della base di dati di OnLife era
arrivare ad un sistema con le seguenti caratteristiche:


    •   Database (migrato) su SQL Server.
    •   Back End su Access (opportunamente modificato), per accedere al
        database su SQL Server.
    •   I tempi di risposta dell’ applicazione dovevano migliorare o, al più,
        rimanere invariati.


Un sistema con queste caratteristiche sarebbe stato in grado di gestire la grande
mole di dati presente nel database con maggiore affidabilità, robustezza e velocità;
inoltre, esso avrebbe seguito a pieno il principio del buon senso nello sviluppo di
ogni software: mantenere sempre separati i dati e l’ interfaccia utente.
Le scelte tecniche riguardo le versioni dei software da utilizzare sono state
valutate in funzione delle necessità e per mantenere la compatibilità con la
situazione preesistente in azienda: si è scelto di utilizzare la versione 2003 di

                                                                                  4
Microsoft Access (in quando già precedentemente in uso) e la versione 2005 di
Microsoft SQL Server.




                                                                           5
CAPITOLO 3
 I tool di migrazione “già pronti” e
 la scelta di una soluzione “ibrida”



Nel voler migrare un database da Access a SQL Server, ci si trova di fronte a
diverse possibilità, che vanno prese in considerazione e valutate di volta in volta,
a seconda delle caratteristiche che presenta la base di dati.
Le principali alternative si possono distinguere essenzialmente in tre categorie:


   •   Migrazione completamente manuale: si tratta di ricostruire manualmente
       tutta la struttura del database su SQL Server (tabelle e relazioni), per poi
       importare i dati nella nuova struttura con delle query ad-hoc.
       Naturalmente questa è una soluzione che ben si adatta a database di
       piccole dimensioni (al più una ventina di tabelle), per cui il lavoro di
       migrazione può essere svolto in un tempo relativamente piccolo e
       prestando una cura massimale ad ogni minimo dettaglio.
       Al crescere delle dimensioni della base di dati, però, questa non è più una
       soluzione praticabile e, in ogni caso, non la migliore.
   •   Migrazione totalmente automatizzata: si tratta di una migrazione
       effettuata completamente da uno strumento software, preposto a questo
       tipo di operazioni. Il software in questione si occupa della migrazione sia
       della struttura del database, sia dei dati contenuti al suo interno.
       Una migrazione di questo tipo non si può in ogni caso definire
       “completamente automatizzata”: essa necessita comunque di un controllo
       finale, per accertarsi che ogni tabella sia stata esportata senza commettere


                                                                                    6
errori e che, nel processo di migrazione, non siano in quache modo stati
       persi dei dati delle tabelle (perdita di informazioni).
       Per questo motivo nemmeno questa alternativa si adatta a database di
       grosse dimensioni, in quanto si rischia – in fase finale – di aver ottenuto
       una struttura compromessa, a causa dei troppi errori (non gestiti)
       commessi in fase di esportazione.
   •   Migrazione “ibrida”: in questo caso la migrazione viene effettuata
       manualmente, ma con l’ ausilio di uno strumento software.
       Ci si serve di un tool di migrazione per l’ esportazione della struttura della
       base di dati; successivamente si controlla che la struttura sia stata ricreata
       correttamente (correggendo eventuali errori o anomalie). Infine, si effettua
       manualmente la migrazione dei dati, con delle query ad-hoc.
       Questa soluzione si adatta meglio a database di grandi dimensioni, per i
       quali è necessario procedere passo-passo, valutando di volta in volta il
       risultato ottenuto e correggendo (ove necessario) gli errori, per arrivare ad
       una struttura finale solida e stabile.



3.1 Considerazioni e conclusione
Il database di OnLife si componeva di 70 tabelle e 74 relazioni (figura 1): una
struttura piuttosto complicata e di grandi dimensioni, che sicuramente escludeva
una migrazione completamente manuale.
Anche la soluzione automatizzata era da escludere, in quanto si incorreva nel
rischio già descritto in precedenza.
Infine, la scelta è ricaduta su una migrazione ibrida, effettuata manualmente e con
l’ affiancamento di uno strumento software.
Nel caso di Access 2003 ed SQL Server 2005, era possibile utilizzare l’ Upsizing
Tool di Microsoft Access 2003 oppure l’ SQL Server Import and Export Wizard: si
è scelto di affiancare alla migrazione manuale l’ Upsizing Tool di Access.




                                                                                   7
Figura 1 - Un estratto della struttura del database di OnLife




                                                                8
CAPITOLO 4
    Elaborazione e pianificazione di
    una strategia di migrazione ben
           pensata e ordinata



Tanti sono i fattori da prendere in considerazione quando si deve effettuare una
migrazione: le caratteristiche e la configurazione del sistema di partenza, gli
obiettivi che si vogliono raggiungere, gli strumenti a disposizione, e così via…
Tuttavia, il fattore che incide in maniera significativa su una migrazione di
successo è l’ elaborazione di una buona strategia d’ azione: non bisogna mai
lasciare tutto al caso.
In quest’ ottica è necessario iniziare il lavoro solo dopo aver pianificato ogni
dettaglio, essersi posti degli obiettivi, delle scadenze, aver organizzato tutto il
lavoro in modo ordinato, preciso e schematico, essersi preparati ad ogni
imprevisto.
Solo così facendo si possono ottenere ottimi risultati, accompagnati dalla sicurezza
di aver sfruttato tutto il tempo e le risorse a disposizione in modo efficiente.
Nel caso specifico di OnLife è stato fatto proprio questo. In particolare, la strategia
elaborata prevedeva i seguenti punti:


   •   Migrazione delle tabelle da Access a SQL Server in locale, utilizzando l’
       Upsizing Tool di Microsoft Access 2003;
   •   Controllo manuale della correttezza della struttura creata, ovvero
       controllo sulla qualità della struttura: eventuali correzioni di errori;



                                                                                     9
•   Controllo che nel processo di migrazione non sia stata persa informazione,
       ovvero controllo sulla quantità dei dati: eventuali correzioni di errori;
   •   Creazione manuale delle relazioni sul nuovo database su SQL Server,
       modificando eventualmente i vincoli preesistenti sulle tabelle, dove
       necessario.
       Infatti Microsoft Access permette di mettere il relazione due campi dello
       stesso datatype, ma di precisione diversa. Ad esempio si possono
       relazionare una Foreign Key testo(5) ed una Primary Key testo(3): per
       ricreare tale relazione su SQL Server, invece, sarà necessario che entrambi
       i campi abbiano non solo lo stesso tipo di dati, ma anche la stessa
       precisione. Pertanto dovranno essere entrambi testo(5) oppure testo(3).
       Il motivo per cui si è deciso di migrare le relazioni manualmente sarà
       spiegato nel prossimo capitolo;
   •   Migrazione di tutte le query dal database Access a quello su SQL Server,
       modificandone il codice SQL per renderle funzionanti su SQL Server;
   •   Eventuale creazione di nuovi vincoli e funzionalità aggiuntive (ad esempio
       i Triggers) sul database su SQL Server;
   •   Modifica del codice del Back End applicativo per renderlo compatibile e
       adatto all’ interfacciamento con SQL Server;
   •   Test e debug del sistema. Questa è la fase centrale, che richiede una
       quantità maggiore di tempo.
   •   Migrazione vera e propria dei dati al database creato sul server in rete;
   •   Installazione del sistema informativo in ambiente aziendale, test e
       collaudo.


Questi sono i punti salienti del lavoro svolto sul sistema informativo di OnLife,
ma costituiscono anche delle linee guida che possono ritenersi valide per ogni
migrazione di un grosso sistema, dove è necessaria una pianificazione molto
precisa e rigorosa.




                                                                                   10
CAPITOLO 5
  Le cose che bisogna sapere prima
      di iniziare la migrazione



5.1 Le “debolezze” dell’ Upsizing Tool di MS Access
Come già spiegato in precedenza, prima di intraprendere il processo di migrazione
di un qualsiasi sistema informativo bisogna prepararsi, documentarsi, effettuare
qualche test sugli strumenti a disposizione al fine di comprenderne le potenzialità
ed i limiti.
Questo è ciò che è stato fatto prima di iniziare la migrazione del sistema
informativo OnLife: più precisamente, si è testato l’ Upsizing Tool di Microsoft
Access 2003, in modo da scoprirne le effettive potenzialità e gli accorgimenti da
adottare nell’ uso di questo strumento.
Le scoperte che ne sono derivate sono state di sorprendente importanza.
Effettuando un piccolo upsizing di prova, interessando esclusivamente la struttura
delle tabelle del database con le relative relazioni, si sono scoperte alcune
“mancanze” che il tool di Access presenta: queste mancanze verranno esposte nei
capitoli seguenti.



5.1.1 Gestione dei valori NULL sulle tabelle esportate

Dopo aver effettuato l’ upsizing, se si va ad analizzare la nuova struttura delle
tabelle ricreata (all’ apparenza perfettamente) su SQL Server, si nota che questa ha
“perso” le informazioni riguardanti la gestione dei valori NULL: ovvero, ad



                                                                                 11
eccezione della Primary Key, tutti i campi ammettono valori nulli, anche quelli
che in Access erano stati definiti come “richiesti”.
Questa è una situazione anomala e certamente un risultato indesiderato; tuttavia
non vi è alcun modo di ovviare a questo problema a priori: l’ unica possibile
soluzione è correggere manualmente gli errori a posteriori, cioè dopo aver
effettuato l’ esportazione delle tabelle.



5.1.2 Datatype corrispondenti su SQL Server

Ogni datatype di Access trova un suo corrispondente tra i datatype di SQL Server
(Tabella 1).
Bisogna però prestare attenzione ad un particolare: la stessa Microsoft afferma che
“i tipi di dati TEXT, NTEXT ed IMAGE verranno rimossi a partire da una delle
prossime versioni di Microsoft SQL Server”; è questo il motivo per cui conviene
“evitare di utilizzare questi tipi di dati in un nuovo progetto di sviluppo e
prevedere interventi di modifica nelle applicazioni che attualmente li utilizzano”.
Quando si effettua l’ upsizing di una tabella con il tool di Access, ogni campo di
tipo MEMO viene trasformato in un campo di tipo NTEXT; ma stando a quanto
detto in precedenza, questa associazione non è del tutto corretta: sarà pertanto
necessario, una volta esportate le tabelle, cambiare manualmente il datatype da
NTEXT a NVARCHAR(max).
Una cosa analoga succede con i campi OLE Object di Access: essi, nel processo
di esportazione, vengono convertiti nell’ equivalente (secondo la Tabella 1)
IMAGE, anch’ esso un tipo di dati candidato alla rimozione a partire dalle
prossime versioni di SQL Server.
In questo caso, è conveniente assegnare il tipo di dati VARBINARY ai campi che
precedentemente erano stati definiti come IMAGE.
Infine, è utile sapere cosa succede ai campi che contengono delle date dopo aver
effettuato l’ upsizing di una tabella.




                                                                                 12
Microsoft Access permette di definire dei campi contenenti date nel formato
"gg/mm/aaaa" (o anche "mm/gg/aaaa", "aaaa/mm/gg", ecc…), ovvero
delle date dove non viene specificato l’ orario. In SQL Server non si possono
specificare date senza l’ orario: infatti, il tipo di dati DATETIME ha sempre il
formato "gg/mm/aaaa hh.mm.ss".
Pertanto un campo data che in Access aveva valore "12/03/2009", in SQL
Server verrà trasformato automaticamente in un campo DATETIME con valore
"12/03/2009 0.00.00": l’ orario con tutte le cifre poste a zero indica che
non è stata specificata l’ ora.



           Access                               SQL Server
           Yes/No                               BIT
           Number (Byte)                        TINYINT
           Number (Integer)                     SMALLINT
           Number (Long Integer)                INT
           (no equivalent)                      BIGINT
           Number (Single)                      REAL
           Number (Double)                      FLOAT
           Currency                             MONEY
           Currency                             SMALLMONEY
           Decimal                              DECIMAL
           Numeric                              NUMERIC
           Date/Time                            DATETIME
           Date/Time                            SMALLDATETIME
           Text(n)                              CHAR(n)
           Text(n)                              NCHAR(n)
           Text(n)                              VARCHAR(n)
           Text(n)                              NVARCHAR(n)
           Text(n)                              NVARCHAR(max)
           Memo                                 TEXT
           Memo                                 NTEXT
           OLE Object                           BINARY
           OLE Object                           VARBINARY(max)
           OLE Object                           IMAGE

       Tabella 1 - Tavola delle corrispondenze tra i datatype di Access ed SQL Server




                                                                                        13
5.1.3 Migrazione delle relazioni

Come già affermato in precedenza, decidendo di utilizzare l’ Upsizing Tool ci si
trova di fronte a due possibilità:


   •   Migrare le tabelle e le relazioni;
   •   Migrare solamente le tabelle, creando manualmente a posteriori tutte le
       relazioni.


Mentre nel secondo caso l’ operazione di migrazione, se ben organizzata, non
presenta particolari rischi di imprevisti, nel primo caso c’ è la possibilità di
incorrere in errori durante l’ esportazione.



Relazioni tra campi di precisione diversa

Si è già visto che Access si rivela più “flessibile” per quanto riguarda la creazione
di relazioni tra campi che hanno diversa precisione (seppur aventi lo stesso tipo di
dati); SQL Server invece permette di creare relazioni solamente tra campi che
hanno lo stesso datatype e la stessa precisione.
È un comportamento rigido da parte di SQL Server, che ne decreta l’ affidabilità e
le prestazioni di un motore di database professionale.
Effettuando alcuni test di utilizzo dell’ Upsizing Tool, si è scoperto che quando si
verificano errori di questo tipo Access si può comportare in due modi diversi:


   1. Visualizzare un messaggio di errore (che verrà poi anche incluso nel report
       finale di migrazione), avvisando che la relazione non è stata creata a causa
       di un errore.
       In tal caso se ne può prendere atto e correggere l’ errore sulla nuova
       struttura.
   2. Non visualizzare alcun messaggio di errore (sebbene si sia verificato) e non
       creare la relazione.



                                                                                  14
Questo caso costituisce un comportamento anomalo del tool e si rivela
       alquanto problematico: non ci si accorge che una relazione del database
       non è stata creata, ma si è convinti del contrario, in quanto non è stato
       dato alcun messaggio di errore durante la migrazione o nel report finale.


Il problema maggiore è che non c’ è una precisa regola secondo cui lo strumento
di upsizing si comporta in un modo o nell’ altro, ne una statistica che possa aiutare
a prevederne il comportamento.



Relazioni in cui la Foreign Key ammette valori NULL

La flessibilità di Access si manifesta anche in un’ altra occasione, cioè in relazioni
in cui la Foreign Key ammette valori NULL.
Quando si crea una relazione su SQL Server, di default essa viene creata usando l’
integrità referenziale senza permettere la presenza di valori nulli sulla chiave
esterna.
Per questo motivo, quando ci si appresta a migrare relazioni di questo tipo con lo
strumento di upsizing di Access si incorre in un errore.
Anche in questa occasione, l’ errore può essere segnalato da Access oppure no.



Conclusione

Alla luce di quanto detto sopra, si conclude che è più conveniente creare le
relazioni tra le tabelle del database manualmente, dopo aver effettuato la
migrazione delle tabelle stesse.
In questo modo si ha la certezza che non si avrà alcun errore non rivelato e che,
qualora se ne verificasse qualcuno, si avrà la possibilità di correggerlo.




                                                                                   15
5.2 Le principali differenze nelle query tra Access ed
     SQL Server
Sebbene l’ SQL sia un linguaggio standard per l’ interrogazione delle basi di dati,
ne esistono diverse implementazioni che, se pure solo per qualche piccolo
dettaglio, differiscono tra di loro.
In questo senso, la sintassi SQL che viene utilizzata all’ interno di Access spesso
presenta delle differenze col Transact-SQL (o anche, più brevemente, T-SQL), la
sintassi SQL utilizzata dal motore di database SQL Server.
Nel seguito verranno descritti alcuni casi particolari di fronte a cui ci si può
trovare quando si devono modificare delle query SQL progettate in Access per
renderle compatibili e funzionanti su SQL Server.



5.2.1 L’ istruzione IIF

L’ istruzione IIF è usata in Access per restituire un valore in funzione del
verificarsi o meno di una condizione. La sua sintassi è la seguente:


IIF (condizione, risultato se TRUE, risultato se FALSE)


È uno statement molto utile e molto usato nelle query Access. Il suo equivalente
in SQL Server è lo statement CASE, che ha la seguente sintassi:


CASE
       WHEN condizione
       THEN risultato se condizione = ‘True’
       ELSE risultato se condizione = ‘False’
END



5.2.2 L’ istruzione SWITCH

Questa è un’ istruzione utilizzata quando si vuole testare il verificarsi di diverse
condizioni (dove l’ una esclude l’ altra) e restituire un risultato in funzione della
condizione che si è verificata.

                                                                                  16
La sua sintassi è la seguente:

SWITCH(condizione1,ris1,condizione2,ris2,condizione3,ris3,...)


Come l’ istruzione IIF, SWITCH non esiste nel T-SQL, dove invece il suo
equivalente è ancora lo statement CASE, in cui ci si serve di clausole WHEN/THEN
multiple, in questo modo:


CASE
       WHEN condizione 1 THEN ris           1
       WHEN condizione 2 THEN ris           2
       WHEN condizione 3 THEN ris           3
       ...
       [opzionale: ELSE risultato          alternativo]
END



5.2.3 La funzione ISNULL

La sintassi Access-SQL è la seguente:

ISNULL(valore)


Le keywords IS NULL vengono poste nel codice T-SQL dopo il valore da testare:

valore IS NULL



5.2.4 Confronti sulle date

In Access i valori delle date vengono solitamente indicati delimitandoli col
carattere "#", mentre SQL Server utilizza l’ apice singolo.
Esempio di sintassi Access-SQL:

SELECT ...
FROM ...
WHERE data = [oppure <, >, <>] #02/12/2009#




                                                                             17
Esempio di sintassi T-SQL:

SELECT ...
FROM ...
WHERE data = [oppure <, >, <>] '02/12/2009'




5.2.5 Filtri su query con valori booleani

Sintassi Access-SQL:

SELECT ...
FROM ...
WHERE field = True [oppure False]


Sintassi T-SQL:

SELECT ...
FROM ...
WHERE field = 'True' [oppure 'False']


Si noti l’ utilizzo degli apici singoli a delimitare i valori True e False: un
piccolo dettaglio che, se omesso, compromette il funzionamento della query.



5.2.6 Subquery nella clausola FROM della query madre

In Access è possibile utilizzare una subquery all’ interno della clausola FROM della
query madre senza associarle alcun alias:


SELECT ...
FROM ..., (SELECT ... FROM ... WHERE ...), ...
WHERE ...




                                                                                 18
In SQL Server è invece obbligatorio associare alla subquery in questione un alias:


SELECT ...
FROM ..., (SELECT ... FROM ... WHERE ...) AS tblAlias, ...
WHERE ...



5.2.7 Uso della funzione InStr

In Access è possibile utilizzare le buil-in functions di Access stesso: una di queste
è la funzione InStr(), che verifica se all’ interno di una stringa sia presente la
sottostringa che si sta cercando.
La sintassi Access-SQL per l’ uso di questa funzione è la seguente:

SELECT ...
FROM ...
WHERE ... AND/OR InStr(stringa, stringa_da_cercare)


Naturalmente, essendo InStr una funzione nativa di Access, essa non esiste in SQL
Server; perciò bisogna trovare una forma equivalente, che sarà data da:


SELECT ...
FROM ...
WHERE ... AND/OR CHARINDEX(stringa, stringa_da_cercare)



5.2.8 Uso della funzione Format nelle date

In Access può capitare di vedere utilizzata, all’ interno di una query, la funzione
Format per manipolare il formato di una data.
Mentre Access accetta il formato di data "dd/mm/yyyy hh.mm.ss", SQL
Server accetta invece un formato del tipo "dd/mm/yyyy hh:mm:ss".
Si noti la sottile differenza tra i due formati: il primo richiede che ci sia un punto
a separare le cifre delle ore/minuti/secondi, mentre il formato di SQL Server
utilizza il carattere doppio-punto.


                                                                                   19
Pertanto, per ottenere un formato corretto da utilizzare nelle query eseguite da
codice su SQL Server, è opportuno ricorrere alla funzione Replace() di VBA: si
sostituisce il carattere "." restituito dalla Format() con il carattere ":" prima
di inviare la query al server.
Ad esempio, il codice Access-VBA

Format(Now(),"dd/mm/yyyy hh.mm.ss")


verrà modificato nel codice Access-VBA, compatibile con SQL Server

Replace((Format(Now(),"dd/mm/yyyy hh.mm.ss")), ".", ":")



5.2.9 Uso della funzione DateAdd

La funzione DateAdd esiste sia in Access SQL che nel T-SQL. Tuttavia vi è una
leggera differenza nella sintassi con cui viene usata questa funzione.
La sintassi Access è

DateAdd('d ', 5, Date())
oppure anche
DateAdd('d', 5, Now())


Mentre il suo corrispondente Transact-SQL si differenzia così:

DateAdd(day, 5, GetDate())
oppure anche
DateAdd(day, 5, { fn Now() })


Come si può notare, la parte di data (day, month oppure year) viene specificata
per esteso e senza gli apici singoli (day invece di 'd') e differisce anche il modo
in cui si ricava la data o il timestamp corrente.




                                                                                20
funzioni
5.2.10 Uso delle funzioni come CInt e CLng

Con queste funzioni si può convertire un valore numerico ad una certa precisione,
a seconda della funzione usata (conversione al tipo Int con la funzione CInt, al
tipo Long con la funzione CLng)
In SQL Server la CLng e la CInt possono essere sostituite, ottenendo lo stesso
risultato, dalla funzione CAST, la cui sintassi è:


CAST(valore_da_convertire AS DataType)


Dove DataType può essere uno dei tipi supportati da SQL Server.



5.2.11 Query con l’ operatore LIKE

Sintassi Access-SQL:

SELECT ...
FROM ...
WHERE ... AND value LIKE '*stringa'


Sintassi T-SQL:

SELECT ...
FROM ...
WHERE ... AND value LIKE '%stringa'


Si noti la differenza del carattere jolly utilizzato nei due casi: "*" per Access, "%"
per SQL Server.



       Concatenazione
5.2.12 Concatenazione di stringhe: "&" e "+"

In Access, il concatenamento tra stringhe nelle query si effettua mediante il
carattere "&", mentre su SQL Server è richiesto l’ uso del carattere "+".



                                                                                   21
Ad esempio la query Access

SELECT ..., (string1 & " " & string2) AS string3, ...
FROM ...
WHERE ...


Troverà il suo equivalente nel codice T-SQL

SELECT ..., (string1 + ' ' + string2) AS string3, ...
FROM ...
WHERE ...



                            numeric
                                 ico
5.2.13 Casting di un valore numerico a stringa

In Access è permesso effettuare il casting di un valore numerico a stringa
semplicemente concatenandolo ad un’ altra stringa, come se fosse anch’ esso tale.
SQL Server, invece, non permette questo e pertanto è necessario forzare il casting
del numero a stringa prima di concatenarlo con un’ altra stringa.
Si consideri il seguente codice SQL:

SELECT (val_numerico & " " & val_stringa) AS stringa, ...
FROM ...
WHERE ...


Il suo equivalente in SQL Server sarà:

SELECT (CAST(val_numerico AS VARCHAR)
          + ' ' +
          val_stringa) AS stringa, ...
FROM ...
WHERE ...




                                                                               22
Utilizzare
5.2.14 Utilizzare nelle subquery gli alias definiti nella query
       madre

In SQL Server non è possibile utilizzare direttamente in una subquery gli alias
definiti nella query madre.
Si prenda come esempio la query:

SELECT (SELECT First(...)
           FROM ...
           WHERE ...) AS alias, alias & " " & value, ...
FROM ...
WHERE ...


Essa, se eseguita su SQL Server, darà l’ errore:

Il nome di colonna 'alias' non è valido.

Per funzionare correttamente, la query dovrà essere opportunamente modificata:

SELECT (SELECT TOP (1) ...
           FROM ...
           WHERE ...) AS alias, (SELECT TOP (1) ...
                                         FROM ...
                                         WHERE ...) + ' ' + value, ...
FROM ...
WHERE ...


Pertanto, la subquery dovrà essere riscritta al posto del suo alias.


5.2.15 Le funzioni First e Last

La funzione First di Access restituisce il primo record di un resultset. Essa si usa
con la sintassi:


SELECT First(field_name)
FROM table_name
WHERE conditions




                                                                                  23
Si consideri, ad esempio, la seguente tabella:

                                          Table
                             ID              Field
                             1               value1
                             3               value2
                             7               value3
       Tabella 2 – Esempio di tabella con ordinamento crescente secondo il campo “ID”


La tabella è ordinata secondo il campo ID in modo crescente: una query di
selezione che usa la funzione First restituirà il primo record, con la coppia di
valori <1, value1>.
Per ottenere un risultato equivalente in SQL Server si può utilizzare lo statement
TOP, che permette di estrarre un numero di record dal resultset della query,
partendo dall’ inizio del resultset: per questo motivo è importante prima di tutto
fare attenzione all’ ordinamento della tabella; se esso, una volta migrata ad SQL
Server, risultasse differente, si dovrà eseguire anche un ordinamento nella query.
Nell’ esempio appena visto, la query T-SQL sarebbe la seguente:

SELECT TOP (1) ID, Field
FROM Table


Volendo essere sicuri che tutto funzioni correttamente, si può aggiungere una
clausola ORDER BY per forzare l’ ordinamento crescente secondo il campo ID:


SELECT TOP (1) ID, Field
FROM Table
ORDER BY ID ASC


La funzione Last dà il risultato opposto a quello della funzione First: essa
restituisce l’ ultimo record di un insieme di risultati di una query.
Non esiste un suo diretto equivalente in SQL Server, tuttavia si può arrivare al
risultato desiderato in un altro modo.
Si prenda nuovamente in considerazione la tabella dell’ esempio precedente: la
query con la Last restituirebbe il record con la coppia di valori <7, value3>.

                                                                                        24
Riflettendo qualche istante, si può concludere che lo stesso risultato si può
ottenere ordinando il risultato della query secondo il campo ID decrescente e
applicando successivamente il filtro TOP (1):


SELECT TOP (1) ID, Field
FROM Table
ORDER BY ID DESC




                                                                          25
CAPITOLO 6
            La migrazione “in locale”



I dati di cui si vuole effettuare la migrazione sono vitali per il funzionamento dell’
azienda, pertanto non è pensabile effettuare subito una migrazione dei dati
“reali”, in quanto ciò comporterebbe il blocco della produzione per tutta la durata
della migrazione: ciò non è chiaramente tollerabile.
Per questo motivo si è pensato ad una soluzione molto più efficiente: lavorare in
un calcolatore con una copia del database di produzione. In questo modo si era
liberi di lavorare e mettere a punto la migrazione in tutti i suoi dettagli, senza
bloccare la produzione o “sporcare” i dati.
Terminato il lavoro in locale, si sarebbe effettuata la vera migrazione, passando
così al nuovo sistema in non più di una giornata.



6.1 Creazione di un nuovo Database su SQL Server
La prima cosa da fare era creare un nuovo database su SQL Server. Nella macchina
sulla quale si sarebbero effettuati tutti i test e le prove prima della vera
migrazione, è stato installato Microsoft SQL Server 2005, utilizzando come
strumento gestionale il software SQL Server Management Studio: un’ interfaccia
visuale che permette di creare e gestire i database sul motore SQL Server.
Per creare un nuovo database utilizzando l’ SQL Server Management Studio, è
sufficiente cliccare col tasto destro sulla voce “Databases” nella schermata
principale del programma e selezionare dal menu che compare la voce “New
Database…”, come si può notare osservando la figura 2.



                                                                                   26
Figura 2 – Creazione di un nuovo database tramite Microsoft SQL Server Management Studio



6.2 Creazione di un nuovo Progetto di Microsoft
    Creazione
    Access (*.adp) e collegamento al server in locale
Come già spiegato, l’ obiettivo della migrazione era avere un database su SQL
Server a cui si voleva accedere tramite un’ applicazione Access/VBA, pertanto si
presentavano due possibilità: mantenere il vecchio applicativo *.mdb, apportando
le dovute modifiche al codice VBA, oppure trasformarlo in un nuovo progetto di
Microsoft Access (ADP, ovvero Access Data Program).
Ora, mentre i progetti *.mdb vengono solitamente utilizzati in applicazioni
sviluppate totalmente all’ interno di Access, i progetti *.adp consentono di
accedere in modo efficiente e nativo a un database di Microsoft SQL Server
mediante l'architettura dei componenti OLE DB (msdn.microsoft.com). Pertanto
si è concluso che i progetti *.adp si adattavano meglio agli obiettivi che si
volevano raggiungere: è per questo motivo che si è scelto di trasformare il vecchio
back end in un nuovo progetto Access *.adp.
Prima della migrazione, il sistema di OnLife era composto da tre file Access
*.mdb: due di essi contenevano esclusivamente il database coi dati, mentre il terzo




                                                                                         27
conteneva tutte le query di accesso/modifica/definizione di dati e il software
applicativo.
Dopo la migrazione la situazione sarebbe cambiata:




               Figura
               Figura 3 – La situazione dopo la migrazione del database di OnLife


il database (e tutti i dati in esso contenuti) e le query sarebbero stati gestiti dal
motore SQL Server, mentre nel nuovo progetto *.adp sarebbero rimaste solamente
le maschere di accesso ai dati che costituivano di fatto l’ intero back end di
OnLife.
Per creare un nuovo progetto Access si accede al menu File > Nuovo… e si
seleziona la voce “Progetto che utilizza dati esistenti…”:




Figura 4 – Creazione di un nuovo progetto *.adp: schermata in cui vengono richiesti i parametri di
                                  connessione ad SQL Server

                                                                                               28
6.2.1 Importazione dei moduli e delle classi nel progetto
      Access

Una volta creato il progetto Access, bisogna importare in esso i moduli associati
alle maschere e le classi presenti nel file *.mdb. Per fare ciò è sufficiente cliccare
col tasto destro sul modulo (o classe) del file *.mdb che si vuole esportare e
successivamente selezionare la voce “Esporta…” (figura 5): infine viene chiesta la
destinazione verso cui esportare il modulo, che può essere un altro file di tipo
*.mdb oppure *.adp (o altri formati).




              Figura 5 – Esportazione dei moduli e delle maschere dal file *.mdb



6.3 Migrazione della struttura della base di dati
Fino a questo punto sono stati creati un nuovo database sul server in locale ed un
progetto Access *.adp (che si connette ad esso), in cui sono stati importati tutti i
moduli delle maschere per l’ accesso ai dati e tutte le classi: l’ ambiente per la
migrazione è pronto e correttamente settato.




                                                                                   29
delle
6.3.1 Migrazione delle tabelle

La migrazione delle tabelle del database, utilizzando l’ Upsizing Tool, è un’
operazione piuttosto semplice e che presenta una bassa probabilità di errore.
Per utilizzare l’ Upsizing Tool si seleziona la voce “Strumenti > Utilità database >
Upsize guidato” dal menu principale di Access: si avvierà una procedura che,
attraverso piccoli steps, guiderà l’ utente nell’ esportazione del database ad SQL
Server.
In figura 6 si possono vedere alcuni dei passi seguiti nel processo di esportazione:




               Figura
               Figura 6 – Alcuni passi seguiti durante l’ upsizing del database
                          Alcuni                          upsizing


La prima informazione che viene richiesta è se si vuole utilizzare un database
esistente o crearne uno nuovo: avendone creato già uno in precedenza, non
rimane che collegarsi ad esso, tramite il driver ODBC presente nel calcolatore.
Successivamente viene richiesto di indicare quali tabelle si vuole esportare nel
database su SQL Server ed infine qualche opzione aggiuntiva: tra queste è
presente l’ opzione “Relazioni delle tabelle”, sotto la voce “Indicare gli attributi


                                                                                   30
delle tabelle di cui eseguire l’ upsize”; questa voce deve essere deselezionata
qualora si voglia esportare solo le tabelle, senza le relazioni.
Al termine dell’ upsize viene presentato un report, in cui sono elencate tutte le
tabelle che sono state esportate, i loro vincoli, i campi ed eventualmente la
segnalazione di errori che si sono verificati durante il processo di migrazione. È
sempre buona norma leggere attentamente questo report prima di proseguire con
il lavoro: in tal modo si evita di trascurare errori di cui probabilmente ci si
accorgerebbe ad uno stadio più avanzato, producendo così effetti ancor peggiori
sull’ intero lavoro svolto fino a quel momento.



6.3.2 Ricostruzione delle relazioni

Questa operazione viene effettuata sulla nuova base di dati gestita dal motore SQL
Server. Una tecnica efficiente è quella di annotarsi (anche su un foglio excel,
oppure memorizzando le informazioni in una tabella di appoggio) tutte le
relazioni e le loro proprietà (come, ad esempio, se è presente l’ integrità
referenziale e, se si, di che tipo, ecc…).




Figura 7 – Tabella di appoggio in cui sono state memorizzate le informazioni relative alle relazioni
                                       del database di OnLife

                                                                                                 31
Infine, servendosi delle informazioni appena annotate, si ricorstruiscono una ad
una le relazioni nel database su SQL Server.
Durante questo processo, se la relazione che (di volta in volta) si cerca di creare
presenta incoerenze o errori, SQL Server lo segnala e si può immediatamente
provvedere a correggere l’ errore.
Seguendo un procedimento di questo tipo si ha la massima sicurezza che la
struttura finale che si otterrà sarà solida e affidabile e non presenterà incoerenze.



6.3.3 Migrazione delle query

Il precedente file *.mdb aveva definite al suo interno tutte le query che venivano
utilizzate per la lettura e la manipolazione dei dati.
In Access non si fa una particolare distinzione tra gli oggetti di tipo query: si
distingue solamente in query di selezione, aggiornamento, modifica e
cancellazione dei dati. In SQL Server, invece, intercorre una sostanziale
differenza tra una Vista (o View) ed una Stored Procedure: in prima
approssimazione, una query Access di selezione trova quasi sempre il suo
corrispondente in una vista di SQL Server, mentre una query di aggiornamento,
modifica o cancellazione dei dati diventerà in SQL Server per lo più una Stored
Procedure, un oggetto programmabile mantenuto all’ interno del database stesso.



Query parametriche e di data manipulation

Quanto detto sopra non è sempre vero. Vi è un caso in cui una query Access di
selezione non diventa una vista in SQL Server: è questo il caso particolare delle
query parametriche, ovvero delle query che accettano dei parametri in input.
Queste, per essere migrate al database gestito da SQL Server, dovranno essere
trasformate in Stored Procedure.
Per quanto riguarda le query cosiddette di “data manipulation”, ovvero quelle
query che contengono degli statement di insert, delete o update e che, pertanto,



                                                                                    32
permettono la manipolazione dei dati, queste dovranno essere sempre trasformate
in Stored Procedure nel passaggio al nuovo database.
Un esempio su tutti, la query dm2_controllo_email_di_partner, una
query di aggiornamento che in Access aveva la sintassi:


UPDATE Partner
SET [Evidenza?] = True,
     Note = "CONTROLLARE INDIRIZZO EMAIL" &
     chr$(13) & chr$(10) & Note
WHERE (Note NOT LIKE "*CONTROLLARE INDIRIZZO EMAIL*")
      AND
      (IDStatoPartner = 2 OR IDStatoPartner = 3)
      AND
      (UsoPartner <> 3)



Essa è stata trasformata in SQL Server nella stored procedure:


SET ANSI_NULLS ON
SET QUOTED_IDENTIFIER ON
GO

CREATE PROCEDURE [dbo].[dm2_controllo_email_di_partner]
AS
BEGIN
      SET NOCOUNT ON;

       UPDATE Partner
       SET [Evidenza?] = 'True',
           Note = 'CONTROLLARE INDIRIZZO EMAIL' +
           char(13) + char(10) + [Note]
       WHERE (Note NOT LIKE '%CONTROLLARE INDIRIZZO EMAIL%')
       AND
       (IDStatoPartner = 2 OR IDStatoPartner = 3)
       AND
       (UsoPartner <> 3)
END



Query non parametriche

Le rimanenti query, ovvero tutte quelle di selezione non parametriche, possono
invece essere migrate al nuovo database creando per ognuna una vista e
correggendo opportunamente il codice SQL contenuto in esse, al fine di ottenere
la compatibilità col T-SQL.


                                                                            33
6.3.4 Controlli e modifiche eventuali sulla nuova struttura
       creata

La nuova struttura creata su SQL Server non si presenta ancora robusta ed
affidabile, necessita di qualche perfezionamento: in seguito sono riportati alcuni
accorgimenti che vanno seguiti al fine di ottenere il miglior risultato possibile
dalla migrazione effettuata.



Valori NULL

Nel capitolo 5 sono state citate le “debolezze” dell’ Upsizing Tool di Microsoft
Access 2003. Una di queste debolezze è la totale mancanza nel migrare le
informazioni riguardanti la gestione dei valori nulli sui campi delle tabelle.
Pertanto alla luce di quanto detto sarà necessario, una volta terminata la
migrazione, controllare manualmente ogni tabella del database e modificare
queste informazioni (riferendosi ovviamente alla struttura originale del database
stesso).
Questo è un passo molto importante: trascurarlo porterebbe certamente a seri
problemi e incoerenze nella struttura della base di dati.



Modifiche sui datatype

Sebbene sia vero che lo strumento per l’ upsize esporti molto bene le informazioni
riguardanti i datatype dei campi delle tabelle, tuttavia per ottimizzare la base di
dati al meglio (anche in vista di passaggi futuri a versioni successive di SQL
Server) è bene prestare attenzione a due dettagli.
In primo luogo, l’ Upsizing Tool trasforma i campi Access MEMO in campi NTEXT
di SQL Server: sarebbe preferibile, invece, impostare il tipo di dati di questi campi
a NVARCHAR(max); in secondo luogo, i campi OLE Object vengono esportati
come campi IMAGE, mentre un’ ulteriore ottimizzazione vedrebbe questi campi
trasformati a VARBINARY(max) (a tal proposito si veda anche il Capitolo 5).



                                                                                  34
6.4 Aggiunta di nuove funzionalità al database migrato
Spesso la migrazione di una base di dati non rappresenta solo il passaggio di un
sistema da un ambiente ad un altro, ma costituisce anche una buona occasione per
apportare migliorie e aggiungere nuove funzionalità al database stesso: questo è
ciò che è stato fatto anche nella migrazione del database di OnLife, introducendo
nuovi vincoli, proprietà e controlli azionati dagli eventi sulle tabelle (Triggers).



            vincoli
6.4.1 Nuovi vincoli e proprietà per le tabelle e i loro campi

In primo luogo, si desiderava effettuare un controllo sui campi di alcune tabelle,
affinchè si fosse certi che i valori contenuti in essi non fossero errati o incoerenti
con la reale situazione.
Ad esempio, nella tabella dei Carichi Contabili si desiderava che, qualora il valore
del campo MezzoPagamento fosse 'B' (ovvero Bonifico), il campo IBAN fosse
assolutamente NULL e, viceversa, qualora MezzoPagamento fosse 'R' (ovvero
RID) si voleva che il campo IBAN fosse assolutamente valorizzato: in effetti non
avrebbe avuto alcun senso, qualora il pagamento fosse stato bonifico, che il campo
IBAN fosse stato valorizzato.
Questo vincolo (ed altri simili) sono stati implementati a livello di tabella; ed in
particolare, il vincolo sopra citato è stato espresso dalla seguente relazione:


(MezzoPagamento = 'R' AND IBAN IS NOT NULL)
OR
(MezzoPagamento = 'B' AND IBAN IS NULL)




6.4.2 Creazione di Triggers per la gestione di eventi

Una funzionalità implementata dall’ RDBMS SQL Server, che in Access invece
non si ritrova, è quella dei Triggers: apposite procedure programmabili che
vengono eseguite in funzione del verificarsi di certi eventi (come, ad esempio, l’
inserimento/cancellazione o la modifica di un record di una tabella).
                                                                                       35
I Triggers sono una funzionalità molto potente che rende il database capace di
“reagire” a certe situazioni, risultando in tal modo più dinamico; inoltre, essi
costituiscono uno strumento in più per specificare e mantenere vincoli di
integrità anche complessi.
Si è deciso così di avvalersi di queste procedure per rafforzare, ad esempio, il
vincolo di integrità sul campo Email della tabella delle email; questo trigger
effettua un controllo in fase di inserimento e di aggiornamento del record della
tabella, verificando ogni volta che l’ indirizzo email specificato sia (almeno)
formalmente valido.
Il codice del trigger è il seguente:



CREATE TRIGGER [dbo].[chk_Email]
ON   [dbo].[Email]
FOR INSERT,UPDATE
AS
        declare @email nvarchar(80)
        declare @start int
        declare @end int
        declare @tld nvarchar(40)
        declare @tld_tmp nvarchar(40)
        declare @id int
        set @email = (SELECT email FROM inserted)
        set @end = (SELECT LEN(email) FROM inserted)
        set @start = (SELECT (CHARINDEX('@',email)+1) FROM inserted)
        set @tld = SUBSTRING(@email,@start,@end)
BEGIN
        SET NOCOUNT ON;




-- Controllo della presenza della chiocciola e che ci sia almeno
-- una lettera prima di essa


SET @id = (SELECT ID FROM inserted)


IF(((SELECT CHARINDEX('@',email) FROM inserted) = 0) OR ((SELECT
CHARINDEX('@',email) FROM inserted) = 1))


                                                                             36
BEGIN
        UPDATE Email
        SET UsoEmail = 1
        WHERE ID = @id
END


-- Se si arriva al prossimo IF allora la chiocciola è presente
-- nell'indirizzo email e prima di essa c'è almeno una lettera.


-- Controlliamo ora che ci sia una stringa anche dopo la chiocciola
-- e che vi sia almeno un punto al suo interno.


-- **************************************************************
-- La stringa dovrà essere lunga come minino 3 caratteri, se
-- consideriamo il seguente esempio:
        -- Un indirizzo email dove il nome del dominio (es: yahoo,
        -- hotmail, gmail, ecc..) è lungo solamente un carattere
        -- (anche se è una situazione abbastanza improbabile!) e il
        -- tld (es: .it, .com, .org, ecc..) ha almeno 2 caratteri
        -- (non esistono certamente nomi di tld che consistono di
        -- un solo carattere!!)
-- Effettuando un controllo di questo tipo, esempi di validi
-- indirizzi email potrebbero essere:
        -- +----------------------+
        -- | 1. a@b.it              |
        -- | 2. io@z.ru             |
        -- | 3. qualcuno@a.it       |
        -- +----------------------+
-- I quali sono indirizzi improbabili, ma per lo meno
-- formalmente validi
-- **************************************************************

ELSE IF(((SELECT (LEN(email)+1)
            FROM inserted) - (SELECT (CHARINDEX('@',email)+1)
                                FROM inserted)) < 3)
BEGIN
        UPDATE Email
        SET UsoEmail = 1
        WHERE ID = @id
END




                                                                      37
-- Controlliamo che nella stringa successiva alla chiocciola
-- non vi sia un'ulteriore chiocciola, altrimenti l'indirizzo
-- non sarebbe formalmente valido:


ELSE IF((SELECT CHARINDEX('@',@tld)
           FROM inserted) <> 0)
BEGIN
        UPDATE Email
        SET UsoEmail = 1
        WHERE ID = @id
END


-- Controlliamo che ci sia almeno un punto nella stringa che segue
-- la chiocciola:


ELSE IF((SELECT CHARINDEX('.',@tld)
           FROM inserted) = 0)
BEGIN
        UPDATE Email
        SET UsoEmail = 1
        WHERE ID = @id
END


-- Se siamo arrivati fino a qui significa che l'indirizzo immesso
-- ha le seguenti caratteristiche:
--         +---------------------------------------------------------+
--         | > Ha SOLO una chiocciola                                |
--         | > Prima della chiocciola c'è ALMENO 1 lettera           |
--         | > Dopo la chiocciola ci sono ALMENO 3 lettere           |
--         | > Nella stringa dopo la chiocciola c'è ALMENO 1 punto   |
--         +---------------------------------------------------------+



-- Ora però dobbiamo pensare al caso in cui il dominio non sia
-- di primo livello, quindi l' email potrebbe essere della forma:
--      > someone@livello2.livello1.it
-- oppure addirittura:
--      > someone@livello3.livello2.livello1.it
-- e così via...
-- Memorizzeremo nella variabile @tld la sottostringa che parte
-- dal punto e va fino alla fine dell'indirizzo, e poi agiremo così:



                                                                     38
--      +---------------------------------------------------------+
--      |     > Se nella sottostringa è presente un punto, otteniamo |
--      |       una nuova sottostringa come fatto precedentemente             |
--      |     > Se nella sottostringa non è presente nessun punto e           |
--      |       non è nulla (es: “someone@yahoo.” non è valido,               |
--      |       perchè dopo il punto non c'è niente!) allora abbiamo |
--      |       finito.                                                       |
--      +---------------------------------------------------------+


ELSE
BEGIN
        WHILE (CHARINDEX('.',@tld) <> 0)
                      begin
                              set @start = CHARINDEX('.',@tld) + 1
                              set @end = LEN(@tld)
                              set @tld_tmp = SUBSTRING(@tld,@start,@end)
                              set @tld = @tld_tmp
                      end
        IF(LEN(@tld) < 2)
                      begin
                              UPDATE Email
                              SET UsoEmail = 1
                              WHERE ID = @id
                      end
        END
END


In caso di inserimento di un indirizzo email formalmente non valido, viene
visualizzato un errore e l’ azione non viene eseguita: il vincolo di integrità sul
campo Email risulta quindi rafforzato ulteriormente con questo trigger.



6.5 Migrazione del back end del Sistema Informativo
Una volta migrata la base di dati, bisogna esaminare il back end: naturalmente ci
saranno delle modifiche da fare nel codice VBA dei moduli/classi del software,
soprattutto per quanto riguarda le query annidate al loro interno (si veda il
capitolo 5.2, “Le principali differenze nelle query tra Access ed SQL Server”).



                                                                                  39
6.5.1 Importazione dei moduli/classi e maschere “vecchi” nel
       nuovo Progetto Access *.adp

La prima cosa da fare è importare nel nuovo progetto i moduli, le classi e le
maschere presenti nel file *.mdb. Fare questo è molto semplice: è sufficiente
aprire il file *.adp, cliccare col tasto destro nella finestra interna di progettazione
del database e selezionare la voce “Importa…” (figura 8) dal menu visualizzato.




             Figura 8 – Il primo passo per l’ importazione di moduli, maschere e classi


Verrà richiesto da quale file si desidera effettuare l’ importazione e
successivamente si aprirà una finestra, dalla quale si possono selezionare gli
oggetti che si desidera importare (tabelle, moduli e classi, maschere…): basterà
selezionare tutte le maschere ed i moduli ed infine premere il tasto “OK” per
procedere.




                                                                                          40
Figura 9 – Il secondo passo per l’ importazione dei moduli/classi e delle maschere



                   codice            nei
6.5.2 Modifica del codice contenuto nei moduli per la
                                 database
      compatibilità con il nuovo database su SQL Server

A questo punto il nuovo progetto è completo di tabelle (sono solo tabelle collegate
al progetto, si ricorda che le tabelle sono fisicamente gestite dal motore SQL
Server), maschere, moduli e classi.
La modifica del codice VBA è un lavoro che, come tutto il resto della migrazione,
va affrontato con una certa metodologia sistematica ed una buona preparazione:




                                                                                            41
bisogna avere ben chiaro, ancor prima di cominciare, quali saranno le parti di
codice interessate maggiormente dalle modifiche.
Come si può intuire dalle cose dette nei precedenti capitoli, è chiaro che le parti
di codice che verranno cambiate principalmente saranno quelle in cui appaiono
delle query, dal momento che queste erano state originariamente pensate per
essere eseguite in Access e, pertanto, non sempre saranno compatibili con il
linguaggio T-SQL che SQL Server si aspetta di ritrovare in una query.
Una volta fatta la manutenzione sulle query, si analizzerà il resto del codice nell’
insieme, entrando man mano nel dettaglio, per capire se esso necessita di ulteriori
modifiche di altro tipo: tuttavia questo resta un passo secondario, dal momento
che la logica applicativa che non coinvolge direttamente i dati difficilmente avrà
bisogno di essere cambiata.



La funzione ApreTabella

Riguardo le query, un ruolo centrale nel software applicativo di OnLife veniva
svolto dalla funzione ApreTabella, che aveva principalmente il compito di aprire
un recordet ADODB e di farlo puntare ad una tabella o query specificata: quasi
tutte le query venivano eseguite dal codice VBA tramite questa funzione, che
però necessitava di una modifica per funzionare nel nuovo progetto.
Il codice originale della funzione era il seguente:



Public Function ApreTabella(rst As ADODB.Recordset, _
                           strCriterio As String, _
                           Optional NumeroRecord As Long = 0, _
                           Optional nomedB As String = "", _
                           Optional ByRef errDecode As String = "") _
                           As Boolean
     Set rst = New ADODB.Recordset
     Set rst.ActiveConnection = CurrentProject.Connection


     ' se la tabella è in un DB diverso
     If nomedB <> "" Then



                                                                                 42
strCriterio = ApreDBDiverso(strCriterio, nomedB)
    End If


    rst.CursorType = adOpenKeyset
    rst.LockType = adLockOptimistic
    ApreTabella = False


    On Error GoTo esci_apretabella
    rst.Open strCriterio, Options:=adCmdTableDirect


    If rst.RecordCount >= 0 Then
         NumeroRecord = rst.RecordCount
         ApreTabella = True
    End If
    Exit Function


esci_apretabella:
    errDecode = err.Description
End Function


Come si può notare, c’ è una riga marcata in rosso: l’ istruzione
adCmdTableDirect non funzionava nel nuovo *.adp, in quanto questa opzione
di apertura delle tabelle viene tipicamente usata per connessioni al motore Jet (il
motore usato all’ interno di Microsoft Access).
Pertanto il codice della funzione ApreTabella è stato modificato nel modo che
segue:



Public Function ApreTabella(rst As ADODB.Recordset, _
                          strCriterio As String, _
                          Optional NumeroRecord As Long = 0, _
                          Optional nomedB As String = "", _
                          Optional ByRef errDecode As String = "") _
                          As Boolean
    Set rst = New ADODB.Recordset
    Set rst.ActiveConnection = CurrentProject.Connection


    ' se la tabella è in un DB diverso
    If nomedB <> "" Then



                                                                                43
strCriterio = ApreDBDiverso(strCriterio, nomedB)


    End If


    rst.CursorType = adOpenKeyset
    rst.LockType = adLockOptimistic
    ApreTabella = False


    On Error GoTo esci_apretabella
    rst.Open strCriterio, CurrentProject.Connection


    If rst.RecordCount >= 0 Then
          NumeroRecord = rst.RecordCount
          ApreTabella = True
    End If
    Exit Function


esci_apretabella:
    errDecode = err.Description
End Function


In tal modo, viene specificato che la connessione su cui agisce il metodo Open del
recordset rst è la connessione corrente del progetto Access, ovvero la
connessione al server SQL.
Era fondamentale effettuare questa modifica sulla funzione ApreTabella, in
quanto altrimenti non si sarebbe stati in grado di eseguire quasi nessuna query dal
codice VBA, rendendo in questo modo praticamente impossibile il funzionamento
del nuovo sistema.



Modifica delle query annidate nel codice

Un altro passo fondamentale nel lavoro di manutenzione del software di OnLife
era, come affermato in precedenza, la modifica delle query eseguite a livello di
codice.
Questo passo si rivela non molto difficoltoso, se eseguito con ordine e con
sistematicità: è necessario, per ogni query presa in esame, verificare se il suo
codice sia compatibile con il T-SQL (eventualmente effettuando anche un test
                                                                                44
pratico della query su SQL Server): in caso negativo, bisognerà provvedere a
modificare la query secondo le considerazioni già eseposte al capitolo 5.2.
Un esempio di query eseguita a livello di codice che necessitava di modifiche per
l’ adattamento al T-SQL è il seguente∗:


...
sqlstr =             "SELECT ID " & _
                     "FROM PartnerTeam " & _
                     "WHERE        Username = '" & _
                                    credenziali.Username & "' AND " & _
                     "              Password = '" & _
                                    credenziali.Password & "' AND " & _
                     "              DataInizioValidita <= #" & _
                                    Format(Date,"mm/dd/yyyy") & "# AND " & _
                     "              DataFineValidita >= #" & _
                                    Format(Date, "mm/dd/yyyy") & "#"
...


Questa query, per poter essere eseguita su SQL Server con esito positivo, è stata
trasformata in questo modo*:


...
sqlstr =             "SELECT ID " & _
                     "FROM PartnerTeam " & _
                     "WHERE        Username = '" & _
                                    credenziali.Username & "' AND " & _
                     "              Password = '" & _
                                    credenziali.Password & "' AND " & _
                     "              DataInizioValidita <= '" & _
                                    Format(Date, "dd/mm/yyyy") & "' AND " & _
                     "              DataFineValidita >= '" & _
                                    Format(Date, "dd/mm/yyyy") & "'"
...




∗
    La sintassi SQL è stata evidenziata al fine di facilitarne la lettura

                                                                                45
Come si può notare, dove nella query Access si utilizzava il simbolo "#" per i
confronti sulle date, nel Transact-SQL i confronti sulle date si effettuano
utilizzando gli apici singoli. Inoltre, si noti il cambio di formato utilizzato per le
date: in Access veniva precedentemente utilizzato il formato mese/giorno/anno
(mm/dd/yyyy), mentre per fare funzionare la stessa query su SQL Server è stato
necessario cambiare il formato della data a giorno/mese/anno (dd/mm/yyyy).



La proprietà RowSourceType

Spesso si ha la necessità di impostare come fonte di un oggetto di una maschera
(una textbox, combobox, ecc…) una tabella o una query. Normalmente nei
progetti Access *.mdb ciò viene fatto impostando la proprietà RowSourceType
dell’ oggetto in questione:


elemento.RowSourceType = "Table/Query"


D’ altra parte i progetti *.adp si collegano ad SQL Server e, pertanto, il concetto di
“Query” com’ era inteso in Access non ha più senso, essendo sostituito da quello
di “Vista”. È per questo motivo che, per rendere correttamente funzionante un
oggetto in cui viene utilizzata la proprietà RowSourceType, sarà opportuno
modificare la precedente riga di codice in questo modo:


elemento.RowSourceType = "Table/View/StoredProc"


Si può facilmente intuire che la sigla "Table/View/StoredProc" indica
come sorgente per un controllo una tabella, una vista oppure una stored
procedure, il che è corretto per un progetto che si interfaccia con SQL Server.




                                                                                   46
Caso particolare: l’ oggetto DAO.Database

Esistono due differenti librerie per l’ accesso programmato ai dati in Access: i Data
Access Objects, più comunemente DAO, e gli ActiveX Data Objects, meglio
chiamati ADO.
Le versioni precedenti di Access facevano largo uso della libreria DAO, usata
come interfaccia al motore di database Jet. Se è vero che i DAO sono ancora
presenti in Access, tuttavia non sono la miglior libreria da utilizzare per le nuove
applicazioni: infatti per esse è preferibile usare la metodologia ADO, più recente.
Nella manutenzione del codice del back end di OnLife è stata osservata qualche
occasione in cui veniva utilizzata ancora la vecchia metodologia DAO.
Di seguito viene riportato il codice della funzione QueryComando che, come
suggerisce il nome stesso, aveva il compito di eseguire sul database quelle che in
Access vengono definite “Query di comando”:


Public Function QueryComando(strsql As String) As Boolean
       Dim dbs As DAO.Database


       QueryComando = False



       On Error GoTo segnala
       Set dbs = CurrentDb
       dbs.Execute strsql
       Set dbs = Nothing


       QueryComando = True


       Exit Function


segnala:
       Messaggio msgDialog, "Non eseguita causa errore la " & _
                                    "query di comando " & strsql
End Function



                                                                                  47
Il codice appena visto, se già non era più considerato adatto per i nuovi progetti
Access, nell’ *.adp che si collegava ad SQL Server non funzionava: in particolare l’
errore si incontrava all’ istruzione contrassegnata in rosso, ove (evidentemente)
Access si aspettava che l’ oggetto CurrentDb fosse un database Access, pertanto
l’ istruzione non funzionava correttamente.
È per questo motivo che la precedente funzione (e così tutte le funzioni analoghe,
facenti uso della libreria DAO) è stata modificata nel modo seguente:


Public Function QueryComando(strsql As String) As Boolean


       Dim rst As ADODB.Recordset
       Set rst = New ADODB.Recordset


       QueryComando = False


       On Error GoTo segnala
       rst.Open strsql, CurrentProject.Connection
       Set rst = Nothing


       QueryComando = True


       Exit Function
       segnala:
       Messaggio msgDialog,"Non eseguita causa errore la " & _
                                  "query di comando " & strsql
       End Function


Si nota che la metodologia di accesso ai dati è stata cambiata da DAO ad ADO: in
particolare si è fatto uso dell’ ADODB Recordset, un oggetto usato molto
frequentemente per l’ accesso ai dati in Access.
Nel metodo Open del recordset è stata specificata come connessione attiva la
CurrentConnection, ovvero la connessione corrente ad SQL Server, pertanto
il codice così strutturato può funzionare correttamente.




                                                                                 48
pseudo-
6.5.3 Il meccanismo di pseudo-paginazione dei risultati nel
       back end di OnLife

Nel vecchio sistema, il modo in cui venivano visualizzati i dati nelle maschere era
il seguente: veniva eseguita una query e si visualizzavano tutti i risultati restituiti
da essa. Se per query strutturalmente semplici e che restituivano al più una
centinaia di risultati questo meccanismo si rivelava tutto sommato efficace, per
query che restituivano qualche migliaia di risultati o che, pur restituendo pochi
risultati, avevano una complessità strutturale (a livello di codice SQL) piuttosto
elevata questo modo di visualizzare le informazioni si rivelava tutt’ altro che
efficiente, sollevando seri problemi performance (soprattutto in termini di tempo
di attesa per la visualizzazione delle informazioni).
Si è pensato pertanto ad una soluzione che permettesse di migliorare le
performance del sistema in questo senso, giungendo alla seguente idea: su ogni
maschera inizialmente si sarebbero visualizzati soltanto i primi 50 risultati della
query, rendendo così l’ esecuzione della stessa (e di conseguenza anche l’ apertura
della relativa maschera) molto più veloce.




Figura 10 – La schermata dei Partner con i primi 50 risultati visualizzati. In basso a sinistra di può
                                                                               basso
                      notare la nuova combobox inserita nell’ interfaccia.

                                                                                                   49
Successivamente l’ utente avrebbe potuto scegliere, mediante un’ apposita
combobox se visualizzare più risultati o addirittura l’ intero set di risultati.
Si potrebbe obiettare che questo meccanismo non è l’ ideale, in quanto parte già
dal presupposto che l’ utente voglia visualizzare solo i primi 50 risultati di una
query: e l’ obiezione sarebbe corretta, se non fosse che da un’ analisi è risultato
che gli utenti del sistema informativo raramente hanno bisogno di visionare una
quantità maggiore dei primi 50 record proposti con questo meccanismo.
A livello di implementazione, questa pseudo-paginazione è relizzata con una
variabile globale numerica, inizializzata a 50, il cui valore può essere cambiato
mediante la già citata combobox: questa variabile sarà poi utilizzata, a livello di
codice, per limitare i risultati della query eseguita con uno statement (T-SQL)
TOP.
Per fare un esempio che possa rendere più chiare le idee, supponendo che la
variabile numero_risultati abbia correntemente il valore di 50 e che venga
eseguita una query sulla tabella Partner per la maschera dei Partners, il codice
VBA∗ che eseguirà la query sarà di questo tipo:


rst.Open             "SELECT TOP (" & numero_risultati & ") " & _
                     "FROM Partner "


La pseudo-paginazione introdotta ha migliorato notevolmente le performance in
termini di velocità del sistema: basti pensare che, prima della modifica, l’ accesso
alla maschera Contratti richiedeva un tempo medio di attesa di 10 secondi
mentre, dopo la modifica, questo tempo si è ridotto a circa 5 secondi.



6.5.4 Test e Debug

Sebbene questo argomento sia discusso alla fine del capitolo, ciò non significa che
il lavoro di test e debug vada fatto solamente alla fine di tutte le modifiche.



∗
    La sintassi SQL è stata evidenziata al fine di facilitarne la lettura

                                                                                   50
Al contrario, è di assoluta importanza effettuare numerosi test anche durante
tutto lo sviluppo e la manutenzione del software, analizzando gli errori e ciò che
non funziona correttamente e intervenendo ove opportuno.
In particolare è bene riflettere sull’ importanza di uno strumento molto semplice
– ma di grande aiuto per lo sviluppatore – messo a disposizione da Access: lo
strumento di debug.
Utilizzando il debugger è possibile seguire passo-passo (con l’uso di breakpoints) l’
esecuzione delle istruzioni del software scritto, in modo tale da permettere allo
sviluppatore di:


   •   Scoprire errori di cui non si era accorto;
   •   Capire in che punto del codice si verifica un errore di cui non si riusciva a
       capire la causa.


È pertanto di grande importanza comprendere l’ utilità di uno strumento di
questo tipo, al fine di sviluppare software in modo efficiente, ordinato e serio.




                                                                                    51
CAPITOLO 7
           La migrazione vera e propria



Esportato il database in locale e testato il back end e verificato che tutto funzioni
correttamente, si è finalmente pronti per la migrazione vera e propria.
Una buona strategia per questa fase del lavoro è composta dai passi di seguito
esposti:


   •   Ricreazione della struttura della base di dati sul server in rete;
   •   Migrazione dei dati dal vecchio database Access al nuovo database su SQL
       Server;
   •   Installazione del sistema informativo sulle macchine aziendali;
   •   Collaudo ed eventuale manutenzione del sistema messo in funzione.



7.1 Creazione della struttura del database sul server in
    rete
    rete
È certamente impensabile ricreare manualmente per la seconda volta tutta la
struttura della base di dati, agendo sul server in rete: ciò comporterebbe uno
spreco di tempo che si può facilmente evitare. In questo senso, fortunatamente
SQL Server mette a disposizione una funzione che eviterà molto lavoro che
altrimenti si sarebbe dovuto svolgere manualmente.




                                                                                  52
7.1.1 La funzione “Script table as…” di SQL Server

La funzione usata è la “Script table as…”: essa crea un file *.sql con uno script in
linguaggio Transact-SQL, contenente degli statements che, una volta eseguito lo
script, creeranno la struttura della tabella e dei suoi vincoli.
In realtà è un po’ approssimativo dire solamente che esiste la funzione “Script
Table as…”; in realtà esistono le:


   •   “Script Table as…”, per le tabelle e le relazioni;
   •   “Script View as…”, per le viste;
   •   “Script Stored Procedure as…”, per le stored procedures;
   •   “Script Function as…”, per le user defined functions.


Per creare lo script *.sql sopra citato, è necessario selezionare tutte le tabelle del
database e cliccare col tasto destro sulle tabelle selezionate: dal menu che appare
si seleziona a questo punto la voce “Script Table as…”, si sceglie tra le diverse
opzioni quella “CREATE To” e infine si sceglie l’ opzione “File…”.
Eseguendo lo script così ottenuto sul server in rete, verrà ricreata la stessa
struttura della base di dati che risiede correntemente sulla macchina locale usata
fino a questo punto.
Per quanto riguarda la creazione delle viste, stored procedures e user defined
functions sul nuovo database, il procedimento da seguire è esattamente lo stesso
di quello già seguito per le tabelle: naturalmente ogni oggetto avrà la sua opzione
“Script…”, a seconda che sia una vista, stored procedure oppure user defined
function.



7.1.2 Esecuzione degli script sul server in rete

A questo punto non rimane che un semplice passo: eseguire gli scripts creati sul
server in rete.
Tuttavia, anche in tale occasione bisogna prestare attenzione a ciò che si sta
facendo, in quanto c’ è ancora una probabilità che si verifichi un errore.
                                                                                   53
L’ ordine di esecuzione degli statements CREATE

Come tutti gli strumenti automatizzati ad uso generico (e pertanto non pensati,
progettati e realizzati specificamente di volta in volta per il caso considerato),
anche la funzione “Script…” a volte può presentare qualche sorpresa.
Nel caso specifico di OnLife, nell’ esecuzione dello script per ricreare le viste sul
server di produzione si è verificato un errore, dovuto ad un errato ordine di alcuni
statements CREATE nello script T-SQL.
Ad esempio, l’ istruzione CREATE per la vista MailOfPartnerQry, che
utilizzava    al    suo    interno     le    viste    MailOfPartnerQryArch,
MailOfPartnerQryIN e MailOfPartnerQryOUT, si trovava prima delle
istruzioni che avrebbero duvuto creare le altre tre viste coinvolte: l’ istruzione
CREATE in questione restituiva quindi un errore, in quanto utilizzava delle viste
che non erano ancora state create.
La soluzione a questo problema è abbastanza ovvia: infatti è stato sufficiente
spostare le istruzioni per la creazione delle tre viste (MailOfPartnerQryArch,
MailOfPartnerQryIN e MailOfPartnerQryOUT) prima delle istruzioni
per la creazione della vista MailOfPartnerQry stessa.



7.2 Scrittura di un piccolo software “ad - hoc” per la
                   dati
    migrazione dei dati
Le stesse considerazioni fatte in precedenza per la modalità di migrazione,
valgono anche in questo caso: si potrebbe decidere di esportare i dati al nuovo
database utilizzando il tool di Access o quello messo a disposizione da SQL Server,
tuttavia per grosse moli di dati è preferibile scegliere una strada che permetta un
maggior controllo e una maggior sicurezza sul risultato ottenuto.
Per questo motivo, in occasione della migrazione dei dati del database di OnLife si
è deciso di sviluppare un piccolo software ad-hoc, progettato e realizzato
specificamente per il caso corrente (figura 11).



                                                                                  54
Figura 11 – Il software di migrazione sviluppato per la migrazione della base di dati di OnLife



7.2.1 La necessità di introdurre un meccanismo di
                        la
      automazione per la migrazione dei dati

In presenza di più di una ventina di tabelle (70 nel caso specifico di OnLife), non
sarebbe una buona soluzione realizzare un software che esegua la migrazione dei
dati una tabella alla volta, richiedendo ad ogni passo la conferma per procedere; il
motivo è essenzialmente uno: ciò richiederebbe troppo tempo.
Quando si decide di entrare in produzione con un nuovo sistema bisogna farlo
velocemente, in modo che l’ attività dell’ azienda non risenta di spiacevoli disagi
(o, ad ogni modo, ne risenta in minima parte) e di problematici rallentamenti
della produttività. Inoltre, migrare una tabella con centinaia di migliaia di record
ad una base di dati su un server installato in locale può richiedere in media anche
solo un tempo di attesa di 15 minuti: la situazione è ben diversa quando si vuole
eseguire la stessa operazione collegandosi ad un server che si trova in rete, dove il
tempo di migrazione della stessa quantità di record potrebbe trasformarsi
addirittura in un’ ora o più.
                                                                                                55
Delle considerazioni più dettagliate in merito alla stima dei tempi di migrazione
verranno esposte al capitolo 7.2.3.
In base ai ragionamenti appena fatti, si conclude che non è possibile eseguire la
migrazione manualmente, tabella per tabella, bensì si rende necessaria l’
introduzione (nel software di migrazione) di un meccanismo di automazione.
Nel caso di OnLife, si è pensato alla seguente strategia: si è scelto un giorno
prestabilito in cui, a fine giornata lavorativa, si sarebbe eseguito il software
automatizzato per la migrazione, lasciandolo in esecuzione durante tutta la notte.
In tal modo, nella mattinata della giornata seguente, con ogni probabilità la
migrazione sarebbe già stata completata e si sarebbe potuto procedere senza
intoppi all’ installazione del nuovo back end del sistema informativo sui
calcolatori aziendali.
Un’ ottima soluzione quella appena descritta, che avrebbe permesso (a meno di
imprevisti) di eseguire la migrazione della base di dati al server di produzione
senza “sacrificare” preziose ore lavorative.



7.2.2 Il problema dell’ IDENTITY_INSERT e la sua soluzione

Volendo realizzare un software che gestisca la migrazione dei dati dalle tabelle
vecchie a quelle nuove, non bisogna lasciare niente al caso. In particolare bisogna
considerare che, generalmente, non è possibile in una tabella modificare il valore
di un campo di tipo contatore con una query di inserimento.
Si consideri, ad esempio, la seguente tabella:


                                       ExampleTable
                         Field       DataType
                         ID          INT, AUTO_INCREMENT
                         Field 1     VARCHAR
                         Field 2     BIT
                         ...         ...
           Tabella 3 – Tabella di esempio, su cui è definita un’ identità sul campo ID




                                                                                         56
La query di inserimento

INSERT INTO ExampleTable (ID, Field1, Field2, ...)
VALUES (45, 'stringa', 'False', ...)


restituirà l’ errore

Quando          IDENTITY_INSERT              è    OFF      non     è    possibile   inserire   un
valore          esplicito           per      la      colonna         Identity   nella   tabella
'ExampleTable'.


Sarà pertanto necessario introdurre una modifica nelle query, che permetta di
inserire i valori desiderati anche in campi di tipo contatore (Identity).
Tale obiettivo viene raggiunto impostando la proprietà IDENTITY_INSERT a ON
per la tabella su cui si vuole eseguire la query di inserimento.
L’ estratto di codice VBA∗ che segue è stato ripreso dal software scritto per la
migrazione delle tabelle del database di OnLife:



rstRem.Open "DECLARE @err INT " & _
       "BEGIN TRY " & _
           "SET IDENTITY_INSERT " & tableName & " ON " & _
       "END TRY " & _


       "BEGIN CATCH " & _
           "SET @err = ERROR_NUMBER() " & _
       "END CATCH " & _


       "IF @err <> 0 " & _
           "BEGIN " & _
              "INSERT INTO " & tableName & " (" & fields_ & ") " & _
              "VALUES (" & values_ & ") " & _
           "END " & _
       "ELSE " & _
           "BEGIN " & _



∗
    La sintassi SQL è stata evidenziata al fine di facilitarne la lettura

                                                                                               57
"SET IDENTITY_INSERT " & tableName & " ON " & _
         "INSERT INTO " & tableName & " (" & fields_ & ") " & _
         "VALUES (" & values_ & ") " & _
         "SET IDENTITY_INSERT " & tableName & " OFF " & _
       "END"


Di fronte a questa query sembra quasi naturale chiedersi perché non ci si sia
limitati ad eseguire il solo statement per impostare l’ IDENTITY_INSERT ad ON,
seguito dalla query di inserimento. Il motivo è che non tutte le tabelle del
database avevano un’ identità con auto-incremento definita su di esse: questo
fatto ha reso necessaria l’ introduzione di un’ ulteriore modifica della query. In tal
senso, viene prima eseguita un’ istruzione T-SQL per testare se esiste sulla tabella
corrente un’ identità, generando così due possibili casi:


   •   Si verifica un errore nel test dell’ istruzione "SET IDENTITY_INSERT
       nome_tabella ON": ciò significa che non era definita alcuna identità; l’
       errore viene catturato con l’ apposita istruzione CATCH.
       A questo punto viene eseguita la sola query di inserimento ed infine
       termina lo statement.
   •   Il test non genera alcun errore: è definita un’ identità sulla tabella.
       Viene eseguita nuovamente l’ istruzione per impostare IDENTITY_
       INSERT a ON e successivamente si esegue la query di inserimento.


Una volta terminata l’ esecuzione della query, la proprietà IDENTITY_ INSERT
viene reimpostata al valore OFF (se era stata precedentemente impostata a ON): se
non si facesse questo, cambiando successivamente la tabella sulla quale eseguire le
query ed eseguendo nuovamente l’ istruzione "SET                IDENTITY_INSERT
nome_tabella ON" si riceverebbe l’ errore


IDENTITY_INSERT        è    già    impostata       su    ON     per    la    tabella
'Tabella1'.       Impossibile       eseguire      l'operazione        SET    per   la
tabella 'Tabella2'



                                                                                   58
in quanto la proprietà IDENTITY_INSERT può essere impostata a ON solo su una
tabella alla volta.



                tempo
7.2.3 Stima del tempo di migrazione del database di OnLife

In genere potrebbe essere utile farsi un’ idea dei tempi medi di migrazione delle
singole tabelle, in modo da poter fare una stima del tempo totale richiesto per l’
operazione relativa all’ intera base di dati.
In particolare, sarebbe opportuno osservare in funzione di quali parametri varia il
tempo di migrazione di una singola tabella e se queste variazioni siano lineari
oppure no.
Il software sviluppato per la migrazione del database di OnLife era stato
progettato in modo da visualizzare a schermo, durante la sua esecuzione, una
traccia delle operazioni effettuate di volta in volta (Figura 12).




                      Figura 12 – Il log del software di migrazione per OnLife




                                                                                 59
Tre informazioni molto importanti venivano visualizzate dal log:


   •   Il numero di record della tabella da migrare;
   •   L’ ora di inizio della migrazione della tabella;
   •   L’ ora in cui è stata completata la migrazione della tabella.


Schematizzando queste informazioni, facendo dei test per un numero significativo
di tabelle, si è ottenuto il seguente schema (vengono trascurati i nomi delle
tabelle, in quanto non sono rilevanti in questo contesto):


 Quantità record    Ora inizio   Ora fine Tempo totale (s)       Tempo singolo record (s)
               34     23.05.25   23.05.26                    1                           0,029
               59     18.07.52   18.07.54                    2                           0,033
               74     18.07.35   18.07.37                    2                           0,027
               85     18.07.46   18.07.49                    3                           0,035
              111     18.07.28   18.07.32                    4                           0,036
              115     18.07.40   18.07.44                    4                           0,034
              180     17.16.27   17.16.33                    6                           0,033
              343     23.05.11   23.05.22                   11                           0,032
              515     23.04.53   23.05.11                   18                           0,034
            2.239      1.29.54    1.31.50                  120                           0,053
            2.315      1.31.50    1.33.17                  120                           0,051
            4.896     18.07.57   18.10.56                  180                           0,036
            6.292     23.05.26   23.10.43                  300                           0,047
            6.374     18.40.08   18.43.44                  180                           0,028
           33.862     17.48.29   18.07.28                1.140                           0,033
           50.103     18.10.56   18.40.08                1.800                           0,035
           50.122     18.43.44   19.11.50                1.680                           0,033
           52.331     22.35.18   23.04.53                1.140                           0,021
           56.111     17.16.33   17.48.28                1.920                           0,034
           80.634     21.50.15   22.35.17                2.700                           0,033
          132.959     20.34.32   21.50.15                3.960                           0,029
          132.959     19.11.50   20.34.32                4.380                           0,032
          236.580     23.10.43    1.29.54                4.740                           0,020
                                                           alcune
        Tabella 4 – Schema dei tempi medi di migrazione di alcune tabelle del database




                                                                                             60
Migrazione della base di dati operativa di un'assicurazione vita diretta
Migrazione della base di dati operativa di un'assicurazione vita diretta
Migrazione della base di dati operativa di un'assicurazione vita diretta
Migrazione della base di dati operativa di un'assicurazione vita diretta
Migrazione della base di dati operativa di un'assicurazione vita diretta

More Related Content

Viewers also liked

Un esempio di Collaborazione tra PA e Imprese
Un esempio di Collaborazione tra PA e ImpreseUn esempio di Collaborazione tra PA e Imprese
Un esempio di Collaborazione tra PA e ImpreseOsmosit Srl
 
Osmosit case study_asl2
Osmosit case study_asl2Osmosit case study_asl2
Osmosit case study_asl2Osmosit Srl
 
Migrazione di basi di dati dall’ambiente MS-Access all’ambiente MS SQL
Migrazione di basi di dati dall’ambiente MS-Access all’ambiente MS SQLMigrazione di basi di dati dall’ambiente MS-Access all’ambiente MS SQL
Migrazione di basi di dati dall’ambiente MS-Access all’ambiente MS SQLFabio Ferroni
 
Alpine Drupal Camp 2011 - Data migration
Alpine Drupal Camp 2011 - Data migrationAlpine Drupal Camp 2011 - Data migration
Alpine Drupal Camp 2011 - Data migrationMarco Vito Moscaritolo
 
Presentazione Etl
Presentazione EtlPresentazione Etl
Presentazione Etlycram83
 
Note di Data Warehouse e Business Intelligence - Pensare "Agile"
Note di Data Warehouse e Business Intelligence - Pensare "Agile"Note di Data Warehouse e Business Intelligence - Pensare "Agile"
Note di Data Warehouse e Business Intelligence - Pensare "Agile"Massimo Cenci
 
Presentazione Nuvola Software
Presentazione Nuvola SoftwarePresentazione Nuvola Software
Presentazione Nuvola Softwarenuvolasoftware
 
Hand Coding ETL Scenarios and Challenges
Hand Coding ETL Scenarios and ChallengesHand Coding ETL Scenarios and Challenges
Hand Coding ETL Scenarios and Challengesmark madsen
 
Tecniche di progettazione della staging area in un processo etl
Tecniche di progettazione della staging area in un processo etlTecniche di progettazione della staging area in un processo etl
Tecniche di progettazione della staging area in un processo etlMassimo Cenci
 
Octobus enterprise management system
Octobus enterprise management systemOctobus enterprise management system
Octobus enterprise management systemFoedus
 
Dw & etl concepts
Dw & etl conceptsDw & etl concepts
Dw & etl conceptsjeshocarme
 
Etl process in data warehouse
Etl process in data warehouseEtl process in data warehouse
Etl process in data warehouseKomal Choudhary
 
Manuale presentazioni efficaci
Manuale presentazioni efficaciManuale presentazioni efficaci
Manuale presentazioni efficaciCristina Rigutto
 

Viewers also liked (19)

#materaodd15
#materaodd15#materaodd15
#materaodd15
 
Un esempio di Collaborazione tra PA e Imprese
Un esempio di Collaborazione tra PA e ImpreseUn esempio di Collaborazione tra PA e Imprese
Un esempio di Collaborazione tra PA e Imprese
 
Osmosit case study_asl2
Osmosit case study_asl2Osmosit case study_asl2
Osmosit case study_asl2
 
Migrazione di basi di dati dall’ambiente MS-Access all’ambiente MS SQL
Migrazione di basi di dati dall’ambiente MS-Access all’ambiente MS SQLMigrazione di basi di dati dall’ambiente MS-Access all’ambiente MS SQL
Migrazione di basi di dati dall’ambiente MS-Access all’ambiente MS SQL
 
Alpine Drupal Camp 2011 - Data migration
Alpine Drupal Camp 2011 - Data migrationAlpine Drupal Camp 2011 - Data migration
Alpine Drupal Camp 2011 - Data migration
 
Presentazione Etl
Presentazione EtlPresentazione Etl
Presentazione Etl
 
Note di Data Warehouse e Business Intelligence - Pensare "Agile"
Note di Data Warehouse e Business Intelligence - Pensare "Agile"Note di Data Warehouse e Business Intelligence - Pensare "Agile"
Note di Data Warehouse e Business Intelligence - Pensare "Agile"
 
Presentazione Nuvola Software
Presentazione Nuvola SoftwarePresentazione Nuvola Software
Presentazione Nuvola Software
 
Presentazione di SpagoWord
Presentazione di SpagoWordPresentazione di SpagoWord
Presentazione di SpagoWord
 
Hand Coding ETL Scenarios and Challenges
Hand Coding ETL Scenarios and ChallengesHand Coding ETL Scenarios and Challenges
Hand Coding ETL Scenarios and Challenges
 
Tecniche di progettazione della staging area in un processo etl
Tecniche di progettazione della staging area in un processo etlTecniche di progettazione della staging area in un processo etl
Tecniche di progettazione della staging area in un processo etl
 
Octobus enterprise management system
Octobus enterprise management systemOctobus enterprise management system
Octobus enterprise management system
 
Dw & etl concepts
Dw & etl conceptsDw & etl concepts
Dw & etl concepts
 
Etl process in data warehouse
Etl process in data warehouseEtl process in data warehouse
Etl process in data warehouse
 
What is ETL?
What is ETL?What is ETL?
What is ETL?
 
Manuale presentazioni efficaci
Manuale presentazioni efficaciManuale presentazioni efficaci
Manuale presentazioni efficaci
 
Introduction to ETL and Data Integration
Introduction to ETL and Data IntegrationIntroduction to ETL and Data Integration
Introduction to ETL and Data Integration
 
ETL Process
ETL ProcessETL Process
ETL Process
 
Le processus ETL (Extraction, Transformation, Chargement)
Le processus ETL (Extraction, Transformation, Chargement)Le processus ETL (Extraction, Transformation, Chargement)
Le processus ETL (Extraction, Transformation, Chargement)
 

Similar to Migrazione della base di dati operativa di un'assicurazione vita diretta

Tesi di laurea - Progettazione e realizzazione di un portale per la gestione ...
Tesi di laurea - Progettazione e realizzazione di un portale per la gestione ...Tesi di laurea - Progettazione e realizzazione di un portale per la gestione ...
Tesi di laurea - Progettazione e realizzazione di un portale per la gestione ...BravinDavide
 
L'impatto dei Servizi Applicativi
L'impatto dei Servizi ApplicativiL'impatto dei Servizi Applicativi
L'impatto dei Servizi Applicativimichelemanzotti
 
Cecutti Federico - Progetto e sviluppo di un'applicazione domotica per telefo...
Cecutti Federico - Progetto e sviluppo di un'applicazione domotica per telefo...Cecutti Federico - Progetto e sviluppo di un'applicazione domotica per telefo...
Cecutti Federico - Progetto e sviluppo di un'applicazione domotica per telefo...guest86388a
 
Cecutti Federico - Progetto e sviluppo di un'applicazione domotica per telefo...
Cecutti Federico - Progetto e sviluppo di un'applicazione domotica per telefo...Cecutti Federico - Progetto e sviluppo di un'applicazione domotica per telefo...
Cecutti Federico - Progetto e sviluppo di un'applicazione domotica per telefo...guest86388a
 
Anteprima modulo 5
Anteprima modulo 5Anteprima modulo 5
Anteprima modulo 5eAgisco
 
Database Project in Visual Studio 2010
Database Project in Visual Studio 2010Database Project in Visual Studio 2010
Database Project in Visual Studio 2010Gian Maria Ricci
 
Implementare e mantenere un progetto azure sql database v.2
Implementare e mantenere un progetto azure sql database v.2Implementare e mantenere un progetto azure sql database v.2
Implementare e mantenere un progetto azure sql database v.2Emanuele Zanchettin
 
Modernize Legacy Systems with Kubernetes
Modernize Legacy Systems with KubernetesModernize Legacy Systems with Kubernetes
Modernize Legacy Systems with KubernetesGiulio Roggero
 
Tesi: Progetto e realizzazione di un sistema robusto di gestione dei dati per...
Tesi: Progetto e realizzazione di un sistema robusto di gestione dei dati per...Tesi: Progetto e realizzazione di un sistema robusto di gestione dei dati per...
Tesi: Progetto e realizzazione di un sistema robusto di gestione dei dati per...Paolo Morandini
 
Progetto SOD Davide Sito
Progetto SOD Davide SitoProgetto SOD Davide Sito
Progetto SOD Davide SitoDavide Sito
 
Realizzazione di una base di dati per la gestione delle valutazioni di proget...
Realizzazione di una base di dati per la gestione delle valutazioni di proget...Realizzazione di una base di dati per la gestione delle valutazioni di proget...
Realizzazione di una base di dati per la gestione delle valutazioni di proget...Efrem Venturuzzo
 
Xen benchmark sistemi paravirtualizzati
Xen benchmark sistemi paravirtualizzatiXen benchmark sistemi paravirtualizzati
Xen benchmark sistemi paravirtualizzatiunicondor
 
Webinar: "Il database: l’equipaggiamento su cui fare affidamento"
Webinar: "Il database: l’equipaggiamento su cui fare affidamento"Webinar: "Il database: l’equipaggiamento su cui fare affidamento"
Webinar: "Il database: l’equipaggiamento su cui fare affidamento"Emerasoft, solutions to collaborate
 
SQL Server Benchmarking, Baselining and Workload Analysis
SQL Server Benchmarking, Baselining and Workload AnalysisSQL Server Benchmarking, Baselining and Workload Analysis
SQL Server Benchmarking, Baselining and Workload AnalysisGianluca Sartori
 

Similar to Migrazione della base di dati operativa di un'assicurazione vita diretta (20)

Tesi di laurea - Progettazione e realizzazione di un portale per la gestione ...
Tesi di laurea - Progettazione e realizzazione di un portale per la gestione ...Tesi di laurea - Progettazione e realizzazione di un portale per la gestione ...
Tesi di laurea - Progettazione e realizzazione di un portale per la gestione ...
 
TesiEtta
TesiEttaTesiEtta
TesiEtta
 
Database Data Aggregator
Database Data AggregatorDatabase Data Aggregator
Database Data Aggregator
 
Relazione Agic
Relazione AgicRelazione Agic
Relazione Agic
 
L'impatto dei Servizi Applicativi
L'impatto dei Servizi ApplicativiL'impatto dei Servizi Applicativi
L'impatto dei Servizi Applicativi
 
Cecutti Federico - Progetto e sviluppo di un'applicazione domotica per telefo...
Cecutti Federico - Progetto e sviluppo di un'applicazione domotica per telefo...Cecutti Federico - Progetto e sviluppo di un'applicazione domotica per telefo...
Cecutti Federico - Progetto e sviluppo di un'applicazione domotica per telefo...
 
Cecutti Federico - Progetto e sviluppo di un'applicazione domotica per telefo...
Cecutti Federico - Progetto e sviluppo di un'applicazione domotica per telefo...Cecutti Federico - Progetto e sviluppo di un'applicazione domotica per telefo...
Cecutti Federico - Progetto e sviluppo di un'applicazione domotica per telefo...
 
Anteprima modulo 5
Anteprima modulo 5Anteprima modulo 5
Anteprima modulo 5
 
Database Project in Visual Studio 2010
Database Project in Visual Studio 2010Database Project in Visual Studio 2010
Database Project in Visual Studio 2010
 
Implementare e mantenere un progetto azure sql database v.2
Implementare e mantenere un progetto azure sql database v.2Implementare e mantenere un progetto azure sql database v.2
Implementare e mantenere un progetto azure sql database v.2
 
Akka.net & Actor Model
Akka.net & Actor ModelAkka.net & Actor Model
Akka.net & Actor Model
 
Modernize Legacy Systems with Kubernetes
Modernize Legacy Systems with KubernetesModernize Legacy Systems with Kubernetes
Modernize Legacy Systems with Kubernetes
 
C# 3.0 e LINQ
C# 3.0 e LINQC# 3.0 e LINQ
C# 3.0 e LINQ
 
Tesi: Progetto e realizzazione di un sistema robusto di gestione dei dati per...
Tesi: Progetto e realizzazione di un sistema robusto di gestione dei dati per...Tesi: Progetto e realizzazione di un sistema robusto di gestione dei dati per...
Tesi: Progetto e realizzazione di un sistema robusto di gestione dei dati per...
 
Progetto SOD Davide Sito
Progetto SOD Davide SitoProgetto SOD Davide Sito
Progetto SOD Davide Sito
 
Realizzazione di una base di dati per la gestione delle valutazioni di proget...
Realizzazione di una base di dati per la gestione delle valutazioni di proget...Realizzazione di una base di dati per la gestione delle valutazioni di proget...
Realizzazione di una base di dati per la gestione delle valutazioni di proget...
 
Xen benchmark sistemi paravirtualizzati
Xen benchmark sistemi paravirtualizzatiXen benchmark sistemi paravirtualizzati
Xen benchmark sistemi paravirtualizzati
 
Webinar: "Il database: l’equipaggiamento su cui fare affidamento"
Webinar: "Il database: l’equipaggiamento su cui fare affidamento"Webinar: "Il database: l’equipaggiamento su cui fare affidamento"
Webinar: "Il database: l’equipaggiamento su cui fare affidamento"
 
SQL Server Benchmarking, Baselining and Workload Analysis
SQL Server Benchmarking, Baselining and Workload AnalysisSQL Server Benchmarking, Baselining and Workload Analysis
SQL Server Benchmarking, Baselining and Workload Analysis
 
Scenario Framework
Scenario FrameworkScenario Framework
Scenario Framework
 

Recently uploaded

Alessio Mazzotti, Aaron Brancotti; Writer, Screenwriter, Director, UX, Autore...
Alessio Mazzotti, Aaron Brancotti; Writer, Screenwriter, Director, UX, Autore...Alessio Mazzotti, Aaron Brancotti; Writer, Screenwriter, Director, UX, Autore...
Alessio Mazzotti, Aaron Brancotti; Writer, Screenwriter, Director, UX, Autore...Associazione Digital Days
 
Edoardo Di Pietro – “Virtual Influencer vs Umano: Rubiamo il lavoro all’AI”
Edoardo Di Pietro – “Virtual Influencer vs Umano: Rubiamo il lavoro all’AI”Edoardo Di Pietro – “Virtual Influencer vs Umano: Rubiamo il lavoro all’AI”
Edoardo Di Pietro – “Virtual Influencer vs Umano: Rubiamo il lavoro all’AI”Associazione Digital Days
 
ScrapeGraphAI: a new way to scrape context with AI
ScrapeGraphAI: a new way to scrape context with AIScrapeGraphAI: a new way to scrape context with AI
ScrapeGraphAI: a new way to scrape context with AIinfogdgmi
 
Daniele Lunassi, CEO & Head of Design @Eye Studios – “Creare prodotti e servi...
Daniele Lunassi, CEO & Head of Design @Eye Studios – “Creare prodotti e servi...Daniele Lunassi, CEO & Head of Design @Eye Studios – “Creare prodotti e servi...
Daniele Lunassi, CEO & Head of Design @Eye Studios – “Creare prodotti e servi...Associazione Digital Days
 
Alessandro Nasi, COO @Djungle Studio – “Cosa delegheresti alla copia di te st...
Alessandro Nasi, COO @Djungle Studio – “Cosa delegheresti alla copia di te st...Alessandro Nasi, COO @Djungle Studio – “Cosa delegheresti alla copia di te st...
Alessandro Nasi, COO @Djungle Studio – “Cosa delegheresti alla copia di te st...Associazione Digital Days
 
Federico Bottino, Lead Venture Builder – “Riflessioni sull’Innovazione: La Cu...
Federico Bottino, Lead Venture Builder – “Riflessioni sull’Innovazione: La Cu...Federico Bottino, Lead Venture Builder – “Riflessioni sull’Innovazione: La Cu...
Federico Bottino, Lead Venture Builder – “Riflessioni sull’Innovazione: La Cu...Associazione Digital Days
 
Luigi Di Carlo, CEO & Founder @Evometrika srl – “Ruolo della computer vision ...
Luigi Di Carlo, CEO & Founder @Evometrika srl – “Ruolo della computer vision ...Luigi Di Carlo, CEO & Founder @Evometrika srl – “Ruolo della computer vision ...
Luigi Di Carlo, CEO & Founder @Evometrika srl – “Ruolo della computer vision ...Associazione Digital Days
 
Gabriele Mittica, CEO @Corley Cloud – “Come creare un’azienda “nativa in clou...
Gabriele Mittica, CEO @Corley Cloud – “Come creare un’azienda “nativa in clou...Gabriele Mittica, CEO @Corley Cloud – “Come creare un’azienda “nativa in clou...
Gabriele Mittica, CEO @Corley Cloud – “Come creare un’azienda “nativa in clou...Associazione Digital Days
 
Mael Chiabrera, Software Developer; Viola Bongini, Digital Experience Designe...
Mael Chiabrera, Software Developer; Viola Bongini, Digital Experience Designe...Mael Chiabrera, Software Developer; Viola Bongini, Digital Experience Designe...
Mael Chiabrera, Software Developer; Viola Bongini, Digital Experience Designe...Associazione Digital Days
 

Recently uploaded (9)

Alessio Mazzotti, Aaron Brancotti; Writer, Screenwriter, Director, UX, Autore...
Alessio Mazzotti, Aaron Brancotti; Writer, Screenwriter, Director, UX, Autore...Alessio Mazzotti, Aaron Brancotti; Writer, Screenwriter, Director, UX, Autore...
Alessio Mazzotti, Aaron Brancotti; Writer, Screenwriter, Director, UX, Autore...
 
Edoardo Di Pietro – “Virtual Influencer vs Umano: Rubiamo il lavoro all’AI”
Edoardo Di Pietro – “Virtual Influencer vs Umano: Rubiamo il lavoro all’AI”Edoardo Di Pietro – “Virtual Influencer vs Umano: Rubiamo il lavoro all’AI”
Edoardo Di Pietro – “Virtual Influencer vs Umano: Rubiamo il lavoro all’AI”
 
ScrapeGraphAI: a new way to scrape context with AI
ScrapeGraphAI: a new way to scrape context with AIScrapeGraphAI: a new way to scrape context with AI
ScrapeGraphAI: a new way to scrape context with AI
 
Daniele Lunassi, CEO & Head of Design @Eye Studios – “Creare prodotti e servi...
Daniele Lunassi, CEO & Head of Design @Eye Studios – “Creare prodotti e servi...Daniele Lunassi, CEO & Head of Design @Eye Studios – “Creare prodotti e servi...
Daniele Lunassi, CEO & Head of Design @Eye Studios – “Creare prodotti e servi...
 
Alessandro Nasi, COO @Djungle Studio – “Cosa delegheresti alla copia di te st...
Alessandro Nasi, COO @Djungle Studio – “Cosa delegheresti alla copia di te st...Alessandro Nasi, COO @Djungle Studio – “Cosa delegheresti alla copia di te st...
Alessandro Nasi, COO @Djungle Studio – “Cosa delegheresti alla copia di te st...
 
Federico Bottino, Lead Venture Builder – “Riflessioni sull’Innovazione: La Cu...
Federico Bottino, Lead Venture Builder – “Riflessioni sull’Innovazione: La Cu...Federico Bottino, Lead Venture Builder – “Riflessioni sull’Innovazione: La Cu...
Federico Bottino, Lead Venture Builder – “Riflessioni sull’Innovazione: La Cu...
 
Luigi Di Carlo, CEO & Founder @Evometrika srl – “Ruolo della computer vision ...
Luigi Di Carlo, CEO & Founder @Evometrika srl – “Ruolo della computer vision ...Luigi Di Carlo, CEO & Founder @Evometrika srl – “Ruolo della computer vision ...
Luigi Di Carlo, CEO & Founder @Evometrika srl – “Ruolo della computer vision ...
 
Gabriele Mittica, CEO @Corley Cloud – “Come creare un’azienda “nativa in clou...
Gabriele Mittica, CEO @Corley Cloud – “Come creare un’azienda “nativa in clou...Gabriele Mittica, CEO @Corley Cloud – “Come creare un’azienda “nativa in clou...
Gabriele Mittica, CEO @Corley Cloud – “Come creare un’azienda “nativa in clou...
 
Mael Chiabrera, Software Developer; Viola Bongini, Digital Experience Designe...
Mael Chiabrera, Software Developer; Viola Bongini, Digital Experience Designe...Mael Chiabrera, Software Developer; Viola Bongini, Digital Experience Designe...
Mael Chiabrera, Software Developer; Viola Bongini, Digital Experience Designe...
 

Migrazione della base di dati operativa di un'assicurazione vita diretta

  • 1. UNIVERSITÀ DEGLI STUDI DI TRIESTE FACOLTÀ DI INGEGNERIA Corso di laurea triennale in Ingegneria Informatica Tesi di laurea in Sistemi Informativi Aziendali “Migrazione della base di dati operativa di un’ assicurazione vita diretta” Laureando: Relatore: Piero De Tomi chiar.mo prof. Leonardo Felician Anno Accademico 2008-2009 2008-
  • 2. Migrazione della base di dati operativa di un’ assicurazione vita diretta
  • 3. Indice Pg. 1. Perché migrare da Access a SQL Server? 1 2. Gli obiettivi della migrazione del sistema informativo di OnLife 3 3. I tool di migrazione “già pronti” e la scelta di una soluzione “ibrida” 6 3.1 Considerazioni e conclusione 7 4. Elaborazione e pianificazione di una strategia di migrazione ben 9 pensata e ordinata 5. Le cose che bisogna sapere prima di iniziare la migrazione 11 5.1 Le “debolezze” dell’ Upsizing Tool di MS Access 11 5.1.1 Gestione dei valori NULL sulle tabelle esportate 11 5.1.2 Datatype corrispondenti su SQL Server 12 5.1.3 Migrazione delle relazioni 14 - Relazioni tra campi di precisione diversa 14 - Relazioni in cui la Foreign Key ammette valori 15 NULL - Conclusione 15 5.2 Le principali differenze nelle query tra Access ed SQL Server 16 5.2.1 L’ istruzione IIF 16 5.2.2 L’ istruzione SWITCH 16 5.2.3 La funzione ISNULL 17 5.2.4 Confronti sulle date 17 5.2.5 Filtri su query con valori booleani 18 5.2.6 Subqueries nella clausola FROM della query madre 18 5.2.7 Uso della funzione InStr 19 5.2.8 Uso della funzione Format nelle date 19
  • 4. 5.2.9 Uso della funzione DateAdd 20 5.2.10 Uso delle funzioni come CInt e CLng 21 5.2.11 Query con l’ operatore LIKE 21 5.2.12 Concatenazione di stringhe: "&" e "+" 21 5.2.13 Casting di un valore numerico a stringa 22 5.2.14 Utilizzare nelle subquery gli alias definiti nella 23 query madre 5.2.15 Le funzioni First e Last 23 6. La migrazione “in locale” 26 6.1 Creazione di un nuovo database su SQL Server 26 6.2 Creazione di un nuovo Progetto di Microsoft Access (*.adp) e 27 collegamento al server in locale 6.2.1 Importazione dei moduli e delle classi nel progetto 29 Access 6.3 Migrazione della struttura della base di dati 29 6.3.1 Migrazione delle tabelle 30 6.3.2 Ricostruzione delle relazioni 31 6.3.3 Migrazione delle query 32 - Query parametriche e di data manipulation 32 - Query non parametriche 33 6.3.4 Controlli e modifiche eventuali sulla nuova struttura 34 creata - Valori NULL 34 - Modifiche sui datatype 34 6.4 Aggiunta di nuove funzionalità al database migrato 35 6.4.1 Nuovi vincoli e proprietà per le tabelle e i lori campi 35 6.4.2 Creazione di Triggers per la gestione di eventi 35 6.5 Migrazione del back end del sistema informativo 39
  • 5. 6.5.1 Importazione dei moduli/classi e maschere “vecchi” 40 nel nuovo progetto Access *.adp 6.5.2 Modifica del codice contenuto nei moduli per la 41 compatibilità con il nuovo database su SQL Server - La funzione ApreTabella 42 - Modifica delle query annidate nel codice 44 - La proprietà RowSourceType 46 - Caso particolare: l’ oggetto DAO.Database 47 6.5.3 Il meccanismo di pseudo-paginazione dei risultati 49 nel back end di OnLife 6.5.4 Test e Debug 50 7. La migrazione vera e propria 52 7.1 Creazione della struttura del database sul server in rete 52 7.1.1 La funzione “Script Table as...” di SQL Server 53 7.1.2 Esecuzione degli script sul server in rete 53 - L’ ordine di esecuzione degli statements CREATE 54 7.2 Scrittura di un piccolo software “ad-hoc” per la migrazione 54 dei dati 7.2.1 La necessità di introdurre un meccanismo di 55 automazione per la migrazione dei dati 7.2.2 Il problema dell’ IDENTITY_INSERT e la sua 56 soluzione 7.2.3 Stima del tempo di migrazione del database di 59 OnLife 7.3 Installazione del sistema informativo in ambiente aziendale 62 7.3.1 Collaudo e manutenzione 63 Conclusioni 64 Bibliografia 65
  • 6. Indice delle figure Figura 1 – Un estratto della struttura del database di OnLife……….8 Fonte : database del sistema informativo di OnLife. Figura 2 – Creazione di un nuovo database tramite Microsoft SQL Server Management Studio……….27 Fonte : elaborazione propria. Figura 3 – La situazione dopo la migrazione del database di OnLife……….28 Fonte : http://office.microsoft.com. Figura 4 – Creazione di un nuovo progetto *.adp: schermata in cui vengono richiesti i parametri di connessione ad SQL Server……….28 Fonte : elaborazione propria. Figura 5 – Esportazione dei moduli e delle maschere dal file *.mdb……….29 Fonte : elaborazione propria. Figura 6 – Alcuni passi seguiti durante l’ upsizing del database……….30 Fonte : elaborazione propria. Figura 7 – Tabella di appoggio in cui sono state memorizzate le informazioni relative alle relazioni del database di OnLife……….31 Fonte : elaborazione propria. Figura 8 – Il primo passo per l’ importazione di moduli, maschere e classi……….40 Fonte : elaborazione propria. Figura 9 – Il secondo passo per l’ importazione dei moduli/classi e delle maschere……….41 Fonte : elaborazione propria. Figura 10 – La schermata dei Partner con i primi 50 risultati visualizzati……….49 Fonte : Sistema Informativo di OnLife. Figura 11 – Il software di migrazione sviluppato per la migrazione della base di dati di OnLife……….55 Fonte : elaborazione propria.
  • 7. Figura 12 – Il log del software di migrazione per OnLife……….59 Fonte : elaborazione propria. Figura 13 – Variazione del tempo di migrazione delle singole tabelle in funzione del numero di record……….61 Fonte : elaborazione propria. Indice delle tabelle Tabella 1 – Tavola delle corrispondenze tra i datatype di Access ed SQL Server……….13 Fonte : http://sqlserver2000.databases.aspfaq.com. Tabella 2 – Esempio di tabella con ordinamento crescente secondo il campo “ID”……….24 Fonte : elaborazione propria. Tabella 3 – Tabella di esempio, con identità sul campo ID……….56 Fonte : elaborazione propria. Tabella 4 – Schema dei tempi medi di migrazione di alcune tabelle del database……….60 Fonte : elaborazione propria.
  • 8. CAPITOLO 1 Perché migrare da Access a SQL Server? La migrazione di un sistema informativo da un ambiente ad un altro è un problema che spesso si presenta nelle aziende, quando si vede crescere con sempre maggior velocità la mole di dati che il sistema stesso deve trattare e quindi il carico delle applicazioni - in termini di dati - inizia ad incidere in maniera significativa sulle prestazioni del sistema. È questo il caso di OnLife, il cui sistema informativo inizialmente era composto principalmente da un database e da un back end, usato per accedere ai suoi dati. Sia il database che l’ applicativo sono stati sviluppati in Microsoft Access 2003, uno strumento tanto semplice quanto potente per lo sviluppo veloce di buoni prototipi di applicazioni. Tuttavia, quando è stato sviluppato questo prototipo, il carico previsto inizialmente non era lo stesso che il sistema deve sopportare oggi: nel tempo si è passati da tabelle con qualche migliaia di record a tabelle (la situazione attuale) con centinaia di migliaia di record. Si intuisce facilmente che un sistema informativo realizzato con uno strumento come Access, più adatto a soluzioni prototipali che a soluzioni “definitive”, non è più adatto ad una situazione del genere. È questo il motivo che ha dato la spinta decisiva verso la migrazione dei dati del sistema da ambiente Access a SQL Server: un RDBMS (Relational Data Base Management System) professionale, più adatto a gestire grandi quantità di dati in maniera efficiente, robusta ed affidabile. 1
  • 9. Bisogna però operare una distinzione importante tra Access ed SQL Server: mentre Access offre la possibilità di definire strutture di database e al tempo stesso sviluppare velocemente interfacce visuali (le cosiddette Maschere) tramite cui accedere ai dati definiti, SQL Server è un RDBMS, ovvero un sistema per la gestione di database. Ciò significa che con SQL Server non si possono sviluppare interfacce per accedere ai dati. Proprio per questo motivo, nel voler affrontare una migrazione del sistema di OnLife da Access ad SQL Server, si sono presentate essenzialmente due possibilità: • Migrazione della base di dati e sviluppo completo di un nuovo back end in un altro ambiente, eventualmente usando un linguaggio di programmazione diverso da quello usato precedentemente (si ricorda che il linguaggio nativo usato all’ interno di MS Access è il VBA, ovvero Visual Basic for Applications). • Migrazione della base di dati e modifica del codice del back end preesistente, al fine di renderne corretto l’ interfacciamento con il nuovo database su SQL Server. La scelta effettuata e la sua motivazione saranno oggetto del prossimo capitolo. 2
  • 10. CAPITOLO 2 obiettivi Gli obiettivi della migrazione del sistema informativo di OnLife Di fronte a due possibili modalità di migrazione, la cosa più corretta da fare era valutare tutti i pro e i contro per ognuna delle due soluzioni, per arrivare ad una conclusione ragionevole. Fermo restando il fatto che entrambe le alternative avevano in comune la migrazione dei dati da Access a SQL Server, rimaneva da effettuare la scelta riguardo il back end. Il vantaggio dello sviluppo di un nuovo applicativo per l’ accesso ai dati risiedeva nella possibilità di riprogettare completamente il sistema, rendendolo adatto – in tutte le sue funzionalità – all’ interazione con il nuovo database su SQL Server. Inoltre, dovendo partire da zero, sarebbe stato possibile scegliere un linguaggio di programmazione più performante e adatto a questo tipo di lavoro. D’ altra parte, scegliendo questa soluzione i tempi di sviluppo si sarebbero dilungati notevolmente, il che costituiva un fattore di cui certamente si doveva tenere conto, dal momento che la necessità di una migrazione era sempre più incombente. Il mantenimento dell’ applicativo originale comportava essenzialmente uno svantaggio: il lavoro non sarebbe stato di sviluppo – come invece lo sarebbe stato nel primo caso –, bensì di manutenzione adattativa/evolutiva: ed è chiaro che solitamente, quando si effettua un qualsiasi tipo di manutenzione su un software, c’ è una grossa percentuale di rischio di incorrere in regressioni e comportamenti anomali del sistema in seguito ai cambiamenti operati. 3
  • 11. Tuttavia bisognava considerare il fatto che un sistema già pronto e con una logica applicativa già funzionante – su cui eventualmente fare manutenzione per ottenere la compatibilità con SQL Server - era un buonissimo punto di partenza e, probabilmente, anche un grosso risparmio di tempo. Con queste considerazioni alla mano, la scelta non era per niente facile, anzi: entrambe le alternative presentavano delle valide motivazioni per essere scelte ed allo stesso tempo dei piccoli svantaggi da prendere in considerazione. Un fattore che ha inciso molto nella predilezione di una soluzione piuttosto che l’ altra è stata la necessità di migrare il sistema in tempi contenuti, al massimo qualche mese: la quantità di dati che il sistema doveva gestire e il carico che doveva sopportare stavano crescendo ad una velocità considerevole. Per questo motivo la scelta finale è caduta sulla seconda alternativa: mantenere il sistema originale ed effettuare su di esso la manutenzione necessaria. In questo modo il requisito della velocità dei tempi di migrazione sarebbe stato soddisfatto, non dovendo progettare ex novo lo sviluppo di un nuovo applicativo. Pertanto, l’ obiettivo stabilito per la migrazione della base di dati di OnLife era arrivare ad un sistema con le seguenti caratteristiche: • Database (migrato) su SQL Server. • Back End su Access (opportunamente modificato), per accedere al database su SQL Server. • I tempi di risposta dell’ applicazione dovevano migliorare o, al più, rimanere invariati. Un sistema con queste caratteristiche sarebbe stato in grado di gestire la grande mole di dati presente nel database con maggiore affidabilità, robustezza e velocità; inoltre, esso avrebbe seguito a pieno il principio del buon senso nello sviluppo di ogni software: mantenere sempre separati i dati e l’ interfaccia utente. Le scelte tecniche riguardo le versioni dei software da utilizzare sono state valutate in funzione delle necessità e per mantenere la compatibilità con la situazione preesistente in azienda: si è scelto di utilizzare la versione 2003 di 4
  • 12. Microsoft Access (in quando già precedentemente in uso) e la versione 2005 di Microsoft SQL Server. 5
  • 13. CAPITOLO 3 I tool di migrazione “già pronti” e la scelta di una soluzione “ibrida” Nel voler migrare un database da Access a SQL Server, ci si trova di fronte a diverse possibilità, che vanno prese in considerazione e valutate di volta in volta, a seconda delle caratteristiche che presenta la base di dati. Le principali alternative si possono distinguere essenzialmente in tre categorie: • Migrazione completamente manuale: si tratta di ricostruire manualmente tutta la struttura del database su SQL Server (tabelle e relazioni), per poi importare i dati nella nuova struttura con delle query ad-hoc. Naturalmente questa è una soluzione che ben si adatta a database di piccole dimensioni (al più una ventina di tabelle), per cui il lavoro di migrazione può essere svolto in un tempo relativamente piccolo e prestando una cura massimale ad ogni minimo dettaglio. Al crescere delle dimensioni della base di dati, però, questa non è più una soluzione praticabile e, in ogni caso, non la migliore. • Migrazione totalmente automatizzata: si tratta di una migrazione effettuata completamente da uno strumento software, preposto a questo tipo di operazioni. Il software in questione si occupa della migrazione sia della struttura del database, sia dei dati contenuti al suo interno. Una migrazione di questo tipo non si può in ogni caso definire “completamente automatizzata”: essa necessita comunque di un controllo finale, per accertarsi che ogni tabella sia stata esportata senza commettere 6
  • 14. errori e che, nel processo di migrazione, non siano in quache modo stati persi dei dati delle tabelle (perdita di informazioni). Per questo motivo nemmeno questa alternativa si adatta a database di grosse dimensioni, in quanto si rischia – in fase finale – di aver ottenuto una struttura compromessa, a causa dei troppi errori (non gestiti) commessi in fase di esportazione. • Migrazione “ibrida”: in questo caso la migrazione viene effettuata manualmente, ma con l’ ausilio di uno strumento software. Ci si serve di un tool di migrazione per l’ esportazione della struttura della base di dati; successivamente si controlla che la struttura sia stata ricreata correttamente (correggendo eventuali errori o anomalie). Infine, si effettua manualmente la migrazione dei dati, con delle query ad-hoc. Questa soluzione si adatta meglio a database di grandi dimensioni, per i quali è necessario procedere passo-passo, valutando di volta in volta il risultato ottenuto e correggendo (ove necessario) gli errori, per arrivare ad una struttura finale solida e stabile. 3.1 Considerazioni e conclusione Il database di OnLife si componeva di 70 tabelle e 74 relazioni (figura 1): una struttura piuttosto complicata e di grandi dimensioni, che sicuramente escludeva una migrazione completamente manuale. Anche la soluzione automatizzata era da escludere, in quanto si incorreva nel rischio già descritto in precedenza. Infine, la scelta è ricaduta su una migrazione ibrida, effettuata manualmente e con l’ affiancamento di uno strumento software. Nel caso di Access 2003 ed SQL Server 2005, era possibile utilizzare l’ Upsizing Tool di Microsoft Access 2003 oppure l’ SQL Server Import and Export Wizard: si è scelto di affiancare alla migrazione manuale l’ Upsizing Tool di Access. 7
  • 15. Figura 1 - Un estratto della struttura del database di OnLife 8
  • 16. CAPITOLO 4 Elaborazione e pianificazione di una strategia di migrazione ben pensata e ordinata Tanti sono i fattori da prendere in considerazione quando si deve effettuare una migrazione: le caratteristiche e la configurazione del sistema di partenza, gli obiettivi che si vogliono raggiungere, gli strumenti a disposizione, e così via… Tuttavia, il fattore che incide in maniera significativa su una migrazione di successo è l’ elaborazione di una buona strategia d’ azione: non bisogna mai lasciare tutto al caso. In quest’ ottica è necessario iniziare il lavoro solo dopo aver pianificato ogni dettaglio, essersi posti degli obiettivi, delle scadenze, aver organizzato tutto il lavoro in modo ordinato, preciso e schematico, essersi preparati ad ogni imprevisto. Solo così facendo si possono ottenere ottimi risultati, accompagnati dalla sicurezza di aver sfruttato tutto il tempo e le risorse a disposizione in modo efficiente. Nel caso specifico di OnLife è stato fatto proprio questo. In particolare, la strategia elaborata prevedeva i seguenti punti: • Migrazione delle tabelle da Access a SQL Server in locale, utilizzando l’ Upsizing Tool di Microsoft Access 2003; • Controllo manuale della correttezza della struttura creata, ovvero controllo sulla qualità della struttura: eventuali correzioni di errori; 9
  • 17. Controllo che nel processo di migrazione non sia stata persa informazione, ovvero controllo sulla quantità dei dati: eventuali correzioni di errori; • Creazione manuale delle relazioni sul nuovo database su SQL Server, modificando eventualmente i vincoli preesistenti sulle tabelle, dove necessario. Infatti Microsoft Access permette di mettere il relazione due campi dello stesso datatype, ma di precisione diversa. Ad esempio si possono relazionare una Foreign Key testo(5) ed una Primary Key testo(3): per ricreare tale relazione su SQL Server, invece, sarà necessario che entrambi i campi abbiano non solo lo stesso tipo di dati, ma anche la stessa precisione. Pertanto dovranno essere entrambi testo(5) oppure testo(3). Il motivo per cui si è deciso di migrare le relazioni manualmente sarà spiegato nel prossimo capitolo; • Migrazione di tutte le query dal database Access a quello su SQL Server, modificandone il codice SQL per renderle funzionanti su SQL Server; • Eventuale creazione di nuovi vincoli e funzionalità aggiuntive (ad esempio i Triggers) sul database su SQL Server; • Modifica del codice del Back End applicativo per renderlo compatibile e adatto all’ interfacciamento con SQL Server; • Test e debug del sistema. Questa è la fase centrale, che richiede una quantità maggiore di tempo. • Migrazione vera e propria dei dati al database creato sul server in rete; • Installazione del sistema informativo in ambiente aziendale, test e collaudo. Questi sono i punti salienti del lavoro svolto sul sistema informativo di OnLife, ma costituiscono anche delle linee guida che possono ritenersi valide per ogni migrazione di un grosso sistema, dove è necessaria una pianificazione molto precisa e rigorosa. 10
  • 18. CAPITOLO 5 Le cose che bisogna sapere prima di iniziare la migrazione 5.1 Le “debolezze” dell’ Upsizing Tool di MS Access Come già spiegato in precedenza, prima di intraprendere il processo di migrazione di un qualsiasi sistema informativo bisogna prepararsi, documentarsi, effettuare qualche test sugli strumenti a disposizione al fine di comprenderne le potenzialità ed i limiti. Questo è ciò che è stato fatto prima di iniziare la migrazione del sistema informativo OnLife: più precisamente, si è testato l’ Upsizing Tool di Microsoft Access 2003, in modo da scoprirne le effettive potenzialità e gli accorgimenti da adottare nell’ uso di questo strumento. Le scoperte che ne sono derivate sono state di sorprendente importanza. Effettuando un piccolo upsizing di prova, interessando esclusivamente la struttura delle tabelle del database con le relative relazioni, si sono scoperte alcune “mancanze” che il tool di Access presenta: queste mancanze verranno esposte nei capitoli seguenti. 5.1.1 Gestione dei valori NULL sulle tabelle esportate Dopo aver effettuato l’ upsizing, se si va ad analizzare la nuova struttura delle tabelle ricreata (all’ apparenza perfettamente) su SQL Server, si nota che questa ha “perso” le informazioni riguardanti la gestione dei valori NULL: ovvero, ad 11
  • 19. eccezione della Primary Key, tutti i campi ammettono valori nulli, anche quelli che in Access erano stati definiti come “richiesti”. Questa è una situazione anomala e certamente un risultato indesiderato; tuttavia non vi è alcun modo di ovviare a questo problema a priori: l’ unica possibile soluzione è correggere manualmente gli errori a posteriori, cioè dopo aver effettuato l’ esportazione delle tabelle. 5.1.2 Datatype corrispondenti su SQL Server Ogni datatype di Access trova un suo corrispondente tra i datatype di SQL Server (Tabella 1). Bisogna però prestare attenzione ad un particolare: la stessa Microsoft afferma che “i tipi di dati TEXT, NTEXT ed IMAGE verranno rimossi a partire da una delle prossime versioni di Microsoft SQL Server”; è questo il motivo per cui conviene “evitare di utilizzare questi tipi di dati in un nuovo progetto di sviluppo e prevedere interventi di modifica nelle applicazioni che attualmente li utilizzano”. Quando si effettua l’ upsizing di una tabella con il tool di Access, ogni campo di tipo MEMO viene trasformato in un campo di tipo NTEXT; ma stando a quanto detto in precedenza, questa associazione non è del tutto corretta: sarà pertanto necessario, una volta esportate le tabelle, cambiare manualmente il datatype da NTEXT a NVARCHAR(max). Una cosa analoga succede con i campi OLE Object di Access: essi, nel processo di esportazione, vengono convertiti nell’ equivalente (secondo la Tabella 1) IMAGE, anch’ esso un tipo di dati candidato alla rimozione a partire dalle prossime versioni di SQL Server. In questo caso, è conveniente assegnare il tipo di dati VARBINARY ai campi che precedentemente erano stati definiti come IMAGE. Infine, è utile sapere cosa succede ai campi che contengono delle date dopo aver effettuato l’ upsizing di una tabella. 12
  • 20. Microsoft Access permette di definire dei campi contenenti date nel formato "gg/mm/aaaa" (o anche "mm/gg/aaaa", "aaaa/mm/gg", ecc…), ovvero delle date dove non viene specificato l’ orario. In SQL Server non si possono specificare date senza l’ orario: infatti, il tipo di dati DATETIME ha sempre il formato "gg/mm/aaaa hh.mm.ss". Pertanto un campo data che in Access aveva valore "12/03/2009", in SQL Server verrà trasformato automaticamente in un campo DATETIME con valore "12/03/2009 0.00.00": l’ orario con tutte le cifre poste a zero indica che non è stata specificata l’ ora. Access SQL Server Yes/No BIT Number (Byte) TINYINT Number (Integer) SMALLINT Number (Long Integer) INT (no equivalent) BIGINT Number (Single) REAL Number (Double) FLOAT Currency MONEY Currency SMALLMONEY Decimal DECIMAL Numeric NUMERIC Date/Time DATETIME Date/Time SMALLDATETIME Text(n) CHAR(n) Text(n) NCHAR(n) Text(n) VARCHAR(n) Text(n) NVARCHAR(n) Text(n) NVARCHAR(max) Memo TEXT Memo NTEXT OLE Object BINARY OLE Object VARBINARY(max) OLE Object IMAGE Tabella 1 - Tavola delle corrispondenze tra i datatype di Access ed SQL Server 13
  • 21. 5.1.3 Migrazione delle relazioni Come già affermato in precedenza, decidendo di utilizzare l’ Upsizing Tool ci si trova di fronte a due possibilità: • Migrare le tabelle e le relazioni; • Migrare solamente le tabelle, creando manualmente a posteriori tutte le relazioni. Mentre nel secondo caso l’ operazione di migrazione, se ben organizzata, non presenta particolari rischi di imprevisti, nel primo caso c’ è la possibilità di incorrere in errori durante l’ esportazione. Relazioni tra campi di precisione diversa Si è già visto che Access si rivela più “flessibile” per quanto riguarda la creazione di relazioni tra campi che hanno diversa precisione (seppur aventi lo stesso tipo di dati); SQL Server invece permette di creare relazioni solamente tra campi che hanno lo stesso datatype e la stessa precisione. È un comportamento rigido da parte di SQL Server, che ne decreta l’ affidabilità e le prestazioni di un motore di database professionale. Effettuando alcuni test di utilizzo dell’ Upsizing Tool, si è scoperto che quando si verificano errori di questo tipo Access si può comportare in due modi diversi: 1. Visualizzare un messaggio di errore (che verrà poi anche incluso nel report finale di migrazione), avvisando che la relazione non è stata creata a causa di un errore. In tal caso se ne può prendere atto e correggere l’ errore sulla nuova struttura. 2. Non visualizzare alcun messaggio di errore (sebbene si sia verificato) e non creare la relazione. 14
  • 22. Questo caso costituisce un comportamento anomalo del tool e si rivela alquanto problematico: non ci si accorge che una relazione del database non è stata creata, ma si è convinti del contrario, in quanto non è stato dato alcun messaggio di errore durante la migrazione o nel report finale. Il problema maggiore è che non c’ è una precisa regola secondo cui lo strumento di upsizing si comporta in un modo o nell’ altro, ne una statistica che possa aiutare a prevederne il comportamento. Relazioni in cui la Foreign Key ammette valori NULL La flessibilità di Access si manifesta anche in un’ altra occasione, cioè in relazioni in cui la Foreign Key ammette valori NULL. Quando si crea una relazione su SQL Server, di default essa viene creata usando l’ integrità referenziale senza permettere la presenza di valori nulli sulla chiave esterna. Per questo motivo, quando ci si appresta a migrare relazioni di questo tipo con lo strumento di upsizing di Access si incorre in un errore. Anche in questa occasione, l’ errore può essere segnalato da Access oppure no. Conclusione Alla luce di quanto detto sopra, si conclude che è più conveniente creare le relazioni tra le tabelle del database manualmente, dopo aver effettuato la migrazione delle tabelle stesse. In questo modo si ha la certezza che non si avrà alcun errore non rivelato e che, qualora se ne verificasse qualcuno, si avrà la possibilità di correggerlo. 15
  • 23. 5.2 Le principali differenze nelle query tra Access ed SQL Server Sebbene l’ SQL sia un linguaggio standard per l’ interrogazione delle basi di dati, ne esistono diverse implementazioni che, se pure solo per qualche piccolo dettaglio, differiscono tra di loro. In questo senso, la sintassi SQL che viene utilizzata all’ interno di Access spesso presenta delle differenze col Transact-SQL (o anche, più brevemente, T-SQL), la sintassi SQL utilizzata dal motore di database SQL Server. Nel seguito verranno descritti alcuni casi particolari di fronte a cui ci si può trovare quando si devono modificare delle query SQL progettate in Access per renderle compatibili e funzionanti su SQL Server. 5.2.1 L’ istruzione IIF L’ istruzione IIF è usata in Access per restituire un valore in funzione del verificarsi o meno di una condizione. La sua sintassi è la seguente: IIF (condizione, risultato se TRUE, risultato se FALSE) È uno statement molto utile e molto usato nelle query Access. Il suo equivalente in SQL Server è lo statement CASE, che ha la seguente sintassi: CASE WHEN condizione THEN risultato se condizione = ‘True’ ELSE risultato se condizione = ‘False’ END 5.2.2 L’ istruzione SWITCH Questa è un’ istruzione utilizzata quando si vuole testare il verificarsi di diverse condizioni (dove l’ una esclude l’ altra) e restituire un risultato in funzione della condizione che si è verificata. 16
  • 24. La sua sintassi è la seguente: SWITCH(condizione1,ris1,condizione2,ris2,condizione3,ris3,...) Come l’ istruzione IIF, SWITCH non esiste nel T-SQL, dove invece il suo equivalente è ancora lo statement CASE, in cui ci si serve di clausole WHEN/THEN multiple, in questo modo: CASE WHEN condizione 1 THEN ris 1 WHEN condizione 2 THEN ris 2 WHEN condizione 3 THEN ris 3 ... [opzionale: ELSE risultato alternativo] END 5.2.3 La funzione ISNULL La sintassi Access-SQL è la seguente: ISNULL(valore) Le keywords IS NULL vengono poste nel codice T-SQL dopo il valore da testare: valore IS NULL 5.2.4 Confronti sulle date In Access i valori delle date vengono solitamente indicati delimitandoli col carattere "#", mentre SQL Server utilizza l’ apice singolo. Esempio di sintassi Access-SQL: SELECT ... FROM ... WHERE data = [oppure <, >, <>] #02/12/2009# 17
  • 25. Esempio di sintassi T-SQL: SELECT ... FROM ... WHERE data = [oppure <, >, <>] '02/12/2009' 5.2.5 Filtri su query con valori booleani Sintassi Access-SQL: SELECT ... FROM ... WHERE field = True [oppure False] Sintassi T-SQL: SELECT ... FROM ... WHERE field = 'True' [oppure 'False'] Si noti l’ utilizzo degli apici singoli a delimitare i valori True e False: un piccolo dettaglio che, se omesso, compromette il funzionamento della query. 5.2.6 Subquery nella clausola FROM della query madre In Access è possibile utilizzare una subquery all’ interno della clausola FROM della query madre senza associarle alcun alias: SELECT ... FROM ..., (SELECT ... FROM ... WHERE ...), ... WHERE ... 18
  • 26. In SQL Server è invece obbligatorio associare alla subquery in questione un alias: SELECT ... FROM ..., (SELECT ... FROM ... WHERE ...) AS tblAlias, ... WHERE ... 5.2.7 Uso della funzione InStr In Access è possibile utilizzare le buil-in functions di Access stesso: una di queste è la funzione InStr(), che verifica se all’ interno di una stringa sia presente la sottostringa che si sta cercando. La sintassi Access-SQL per l’ uso di questa funzione è la seguente: SELECT ... FROM ... WHERE ... AND/OR InStr(stringa, stringa_da_cercare) Naturalmente, essendo InStr una funzione nativa di Access, essa non esiste in SQL Server; perciò bisogna trovare una forma equivalente, che sarà data da: SELECT ... FROM ... WHERE ... AND/OR CHARINDEX(stringa, stringa_da_cercare) 5.2.8 Uso della funzione Format nelle date In Access può capitare di vedere utilizzata, all’ interno di una query, la funzione Format per manipolare il formato di una data. Mentre Access accetta il formato di data "dd/mm/yyyy hh.mm.ss", SQL Server accetta invece un formato del tipo "dd/mm/yyyy hh:mm:ss". Si noti la sottile differenza tra i due formati: il primo richiede che ci sia un punto a separare le cifre delle ore/minuti/secondi, mentre il formato di SQL Server utilizza il carattere doppio-punto. 19
  • 27. Pertanto, per ottenere un formato corretto da utilizzare nelle query eseguite da codice su SQL Server, è opportuno ricorrere alla funzione Replace() di VBA: si sostituisce il carattere "." restituito dalla Format() con il carattere ":" prima di inviare la query al server. Ad esempio, il codice Access-VBA Format(Now(),"dd/mm/yyyy hh.mm.ss") verrà modificato nel codice Access-VBA, compatibile con SQL Server Replace((Format(Now(),"dd/mm/yyyy hh.mm.ss")), ".", ":") 5.2.9 Uso della funzione DateAdd La funzione DateAdd esiste sia in Access SQL che nel T-SQL. Tuttavia vi è una leggera differenza nella sintassi con cui viene usata questa funzione. La sintassi Access è DateAdd('d ', 5, Date()) oppure anche DateAdd('d', 5, Now()) Mentre il suo corrispondente Transact-SQL si differenzia così: DateAdd(day, 5, GetDate()) oppure anche DateAdd(day, 5, { fn Now() }) Come si può notare, la parte di data (day, month oppure year) viene specificata per esteso e senza gli apici singoli (day invece di 'd') e differisce anche il modo in cui si ricava la data o il timestamp corrente. 20
  • 28. funzioni 5.2.10 Uso delle funzioni come CInt e CLng Con queste funzioni si può convertire un valore numerico ad una certa precisione, a seconda della funzione usata (conversione al tipo Int con la funzione CInt, al tipo Long con la funzione CLng) In SQL Server la CLng e la CInt possono essere sostituite, ottenendo lo stesso risultato, dalla funzione CAST, la cui sintassi è: CAST(valore_da_convertire AS DataType) Dove DataType può essere uno dei tipi supportati da SQL Server. 5.2.11 Query con l’ operatore LIKE Sintassi Access-SQL: SELECT ... FROM ... WHERE ... AND value LIKE '*stringa' Sintassi T-SQL: SELECT ... FROM ... WHERE ... AND value LIKE '%stringa' Si noti la differenza del carattere jolly utilizzato nei due casi: "*" per Access, "%" per SQL Server. Concatenazione 5.2.12 Concatenazione di stringhe: "&" e "+" In Access, il concatenamento tra stringhe nelle query si effettua mediante il carattere "&", mentre su SQL Server è richiesto l’ uso del carattere "+". 21
  • 29. Ad esempio la query Access SELECT ..., (string1 & " " & string2) AS string3, ... FROM ... WHERE ... Troverà il suo equivalente nel codice T-SQL SELECT ..., (string1 + ' ' + string2) AS string3, ... FROM ... WHERE ... numeric ico 5.2.13 Casting di un valore numerico a stringa In Access è permesso effettuare il casting di un valore numerico a stringa semplicemente concatenandolo ad un’ altra stringa, come se fosse anch’ esso tale. SQL Server, invece, non permette questo e pertanto è necessario forzare il casting del numero a stringa prima di concatenarlo con un’ altra stringa. Si consideri il seguente codice SQL: SELECT (val_numerico & " " & val_stringa) AS stringa, ... FROM ... WHERE ... Il suo equivalente in SQL Server sarà: SELECT (CAST(val_numerico AS VARCHAR) + ' ' + val_stringa) AS stringa, ... FROM ... WHERE ... 22
  • 30. Utilizzare 5.2.14 Utilizzare nelle subquery gli alias definiti nella query madre In SQL Server non è possibile utilizzare direttamente in una subquery gli alias definiti nella query madre. Si prenda come esempio la query: SELECT (SELECT First(...) FROM ... WHERE ...) AS alias, alias & " " & value, ... FROM ... WHERE ... Essa, se eseguita su SQL Server, darà l’ errore: Il nome di colonna 'alias' non è valido. Per funzionare correttamente, la query dovrà essere opportunamente modificata: SELECT (SELECT TOP (1) ... FROM ... WHERE ...) AS alias, (SELECT TOP (1) ... FROM ... WHERE ...) + ' ' + value, ... FROM ... WHERE ... Pertanto, la subquery dovrà essere riscritta al posto del suo alias. 5.2.15 Le funzioni First e Last La funzione First di Access restituisce il primo record di un resultset. Essa si usa con la sintassi: SELECT First(field_name) FROM table_name WHERE conditions 23
  • 31. Si consideri, ad esempio, la seguente tabella: Table ID Field 1 value1 3 value2 7 value3 Tabella 2 – Esempio di tabella con ordinamento crescente secondo il campo “ID” La tabella è ordinata secondo il campo ID in modo crescente: una query di selezione che usa la funzione First restituirà il primo record, con la coppia di valori <1, value1>. Per ottenere un risultato equivalente in SQL Server si può utilizzare lo statement TOP, che permette di estrarre un numero di record dal resultset della query, partendo dall’ inizio del resultset: per questo motivo è importante prima di tutto fare attenzione all’ ordinamento della tabella; se esso, una volta migrata ad SQL Server, risultasse differente, si dovrà eseguire anche un ordinamento nella query. Nell’ esempio appena visto, la query T-SQL sarebbe la seguente: SELECT TOP (1) ID, Field FROM Table Volendo essere sicuri che tutto funzioni correttamente, si può aggiungere una clausola ORDER BY per forzare l’ ordinamento crescente secondo il campo ID: SELECT TOP (1) ID, Field FROM Table ORDER BY ID ASC La funzione Last dà il risultato opposto a quello della funzione First: essa restituisce l’ ultimo record di un insieme di risultati di una query. Non esiste un suo diretto equivalente in SQL Server, tuttavia si può arrivare al risultato desiderato in un altro modo. Si prenda nuovamente in considerazione la tabella dell’ esempio precedente: la query con la Last restituirebbe il record con la coppia di valori <7, value3>. 24
  • 32. Riflettendo qualche istante, si può concludere che lo stesso risultato si può ottenere ordinando il risultato della query secondo il campo ID decrescente e applicando successivamente il filtro TOP (1): SELECT TOP (1) ID, Field FROM Table ORDER BY ID DESC 25
  • 33. CAPITOLO 6 La migrazione “in locale” I dati di cui si vuole effettuare la migrazione sono vitali per il funzionamento dell’ azienda, pertanto non è pensabile effettuare subito una migrazione dei dati “reali”, in quanto ciò comporterebbe il blocco della produzione per tutta la durata della migrazione: ciò non è chiaramente tollerabile. Per questo motivo si è pensato ad una soluzione molto più efficiente: lavorare in un calcolatore con una copia del database di produzione. In questo modo si era liberi di lavorare e mettere a punto la migrazione in tutti i suoi dettagli, senza bloccare la produzione o “sporcare” i dati. Terminato il lavoro in locale, si sarebbe effettuata la vera migrazione, passando così al nuovo sistema in non più di una giornata. 6.1 Creazione di un nuovo Database su SQL Server La prima cosa da fare era creare un nuovo database su SQL Server. Nella macchina sulla quale si sarebbero effettuati tutti i test e le prove prima della vera migrazione, è stato installato Microsoft SQL Server 2005, utilizzando come strumento gestionale il software SQL Server Management Studio: un’ interfaccia visuale che permette di creare e gestire i database sul motore SQL Server. Per creare un nuovo database utilizzando l’ SQL Server Management Studio, è sufficiente cliccare col tasto destro sulla voce “Databases” nella schermata principale del programma e selezionare dal menu che compare la voce “New Database…”, come si può notare osservando la figura 2. 26
  • 34. Figura 2 – Creazione di un nuovo database tramite Microsoft SQL Server Management Studio 6.2 Creazione di un nuovo Progetto di Microsoft Creazione Access (*.adp) e collegamento al server in locale Come già spiegato, l’ obiettivo della migrazione era avere un database su SQL Server a cui si voleva accedere tramite un’ applicazione Access/VBA, pertanto si presentavano due possibilità: mantenere il vecchio applicativo *.mdb, apportando le dovute modifiche al codice VBA, oppure trasformarlo in un nuovo progetto di Microsoft Access (ADP, ovvero Access Data Program). Ora, mentre i progetti *.mdb vengono solitamente utilizzati in applicazioni sviluppate totalmente all’ interno di Access, i progetti *.adp consentono di accedere in modo efficiente e nativo a un database di Microsoft SQL Server mediante l'architettura dei componenti OLE DB (msdn.microsoft.com). Pertanto si è concluso che i progetti *.adp si adattavano meglio agli obiettivi che si volevano raggiungere: è per questo motivo che si è scelto di trasformare il vecchio back end in un nuovo progetto Access *.adp. Prima della migrazione, il sistema di OnLife era composto da tre file Access *.mdb: due di essi contenevano esclusivamente il database coi dati, mentre il terzo 27
  • 35. conteneva tutte le query di accesso/modifica/definizione di dati e il software applicativo. Dopo la migrazione la situazione sarebbe cambiata: Figura Figura 3 – La situazione dopo la migrazione del database di OnLife il database (e tutti i dati in esso contenuti) e le query sarebbero stati gestiti dal motore SQL Server, mentre nel nuovo progetto *.adp sarebbero rimaste solamente le maschere di accesso ai dati che costituivano di fatto l’ intero back end di OnLife. Per creare un nuovo progetto Access si accede al menu File > Nuovo… e si seleziona la voce “Progetto che utilizza dati esistenti…”: Figura 4 – Creazione di un nuovo progetto *.adp: schermata in cui vengono richiesti i parametri di connessione ad SQL Server 28
  • 36. 6.2.1 Importazione dei moduli e delle classi nel progetto Access Una volta creato il progetto Access, bisogna importare in esso i moduli associati alle maschere e le classi presenti nel file *.mdb. Per fare ciò è sufficiente cliccare col tasto destro sul modulo (o classe) del file *.mdb che si vuole esportare e successivamente selezionare la voce “Esporta…” (figura 5): infine viene chiesta la destinazione verso cui esportare il modulo, che può essere un altro file di tipo *.mdb oppure *.adp (o altri formati). Figura 5 – Esportazione dei moduli e delle maschere dal file *.mdb 6.3 Migrazione della struttura della base di dati Fino a questo punto sono stati creati un nuovo database sul server in locale ed un progetto Access *.adp (che si connette ad esso), in cui sono stati importati tutti i moduli delle maschere per l’ accesso ai dati e tutte le classi: l’ ambiente per la migrazione è pronto e correttamente settato. 29
  • 37. delle 6.3.1 Migrazione delle tabelle La migrazione delle tabelle del database, utilizzando l’ Upsizing Tool, è un’ operazione piuttosto semplice e che presenta una bassa probabilità di errore. Per utilizzare l’ Upsizing Tool si seleziona la voce “Strumenti > Utilità database > Upsize guidato” dal menu principale di Access: si avvierà una procedura che, attraverso piccoli steps, guiderà l’ utente nell’ esportazione del database ad SQL Server. In figura 6 si possono vedere alcuni dei passi seguiti nel processo di esportazione: Figura Figura 6 – Alcuni passi seguiti durante l’ upsizing del database Alcuni upsizing La prima informazione che viene richiesta è se si vuole utilizzare un database esistente o crearne uno nuovo: avendone creato già uno in precedenza, non rimane che collegarsi ad esso, tramite il driver ODBC presente nel calcolatore. Successivamente viene richiesto di indicare quali tabelle si vuole esportare nel database su SQL Server ed infine qualche opzione aggiuntiva: tra queste è presente l’ opzione “Relazioni delle tabelle”, sotto la voce “Indicare gli attributi 30
  • 38. delle tabelle di cui eseguire l’ upsize”; questa voce deve essere deselezionata qualora si voglia esportare solo le tabelle, senza le relazioni. Al termine dell’ upsize viene presentato un report, in cui sono elencate tutte le tabelle che sono state esportate, i loro vincoli, i campi ed eventualmente la segnalazione di errori che si sono verificati durante il processo di migrazione. È sempre buona norma leggere attentamente questo report prima di proseguire con il lavoro: in tal modo si evita di trascurare errori di cui probabilmente ci si accorgerebbe ad uno stadio più avanzato, producendo così effetti ancor peggiori sull’ intero lavoro svolto fino a quel momento. 6.3.2 Ricostruzione delle relazioni Questa operazione viene effettuata sulla nuova base di dati gestita dal motore SQL Server. Una tecnica efficiente è quella di annotarsi (anche su un foglio excel, oppure memorizzando le informazioni in una tabella di appoggio) tutte le relazioni e le loro proprietà (come, ad esempio, se è presente l’ integrità referenziale e, se si, di che tipo, ecc…). Figura 7 – Tabella di appoggio in cui sono state memorizzate le informazioni relative alle relazioni del database di OnLife 31
  • 39. Infine, servendosi delle informazioni appena annotate, si ricorstruiscono una ad una le relazioni nel database su SQL Server. Durante questo processo, se la relazione che (di volta in volta) si cerca di creare presenta incoerenze o errori, SQL Server lo segnala e si può immediatamente provvedere a correggere l’ errore. Seguendo un procedimento di questo tipo si ha la massima sicurezza che la struttura finale che si otterrà sarà solida e affidabile e non presenterà incoerenze. 6.3.3 Migrazione delle query Il precedente file *.mdb aveva definite al suo interno tutte le query che venivano utilizzate per la lettura e la manipolazione dei dati. In Access non si fa una particolare distinzione tra gli oggetti di tipo query: si distingue solamente in query di selezione, aggiornamento, modifica e cancellazione dei dati. In SQL Server, invece, intercorre una sostanziale differenza tra una Vista (o View) ed una Stored Procedure: in prima approssimazione, una query Access di selezione trova quasi sempre il suo corrispondente in una vista di SQL Server, mentre una query di aggiornamento, modifica o cancellazione dei dati diventerà in SQL Server per lo più una Stored Procedure, un oggetto programmabile mantenuto all’ interno del database stesso. Query parametriche e di data manipulation Quanto detto sopra non è sempre vero. Vi è un caso in cui una query Access di selezione non diventa una vista in SQL Server: è questo il caso particolare delle query parametriche, ovvero delle query che accettano dei parametri in input. Queste, per essere migrate al database gestito da SQL Server, dovranno essere trasformate in Stored Procedure. Per quanto riguarda le query cosiddette di “data manipulation”, ovvero quelle query che contengono degli statement di insert, delete o update e che, pertanto, 32
  • 40. permettono la manipolazione dei dati, queste dovranno essere sempre trasformate in Stored Procedure nel passaggio al nuovo database. Un esempio su tutti, la query dm2_controllo_email_di_partner, una query di aggiornamento che in Access aveva la sintassi: UPDATE Partner SET [Evidenza?] = True, Note = "CONTROLLARE INDIRIZZO EMAIL" & chr$(13) & chr$(10) & Note WHERE (Note NOT LIKE "*CONTROLLARE INDIRIZZO EMAIL*") AND (IDStatoPartner = 2 OR IDStatoPartner = 3) AND (UsoPartner <> 3) Essa è stata trasformata in SQL Server nella stored procedure: SET ANSI_NULLS ON SET QUOTED_IDENTIFIER ON GO CREATE PROCEDURE [dbo].[dm2_controllo_email_di_partner] AS BEGIN SET NOCOUNT ON; UPDATE Partner SET [Evidenza?] = 'True', Note = 'CONTROLLARE INDIRIZZO EMAIL' + char(13) + char(10) + [Note] WHERE (Note NOT LIKE '%CONTROLLARE INDIRIZZO EMAIL%') AND (IDStatoPartner = 2 OR IDStatoPartner = 3) AND (UsoPartner <> 3) END Query non parametriche Le rimanenti query, ovvero tutte quelle di selezione non parametriche, possono invece essere migrate al nuovo database creando per ognuna una vista e correggendo opportunamente il codice SQL contenuto in esse, al fine di ottenere la compatibilità col T-SQL. 33
  • 41. 6.3.4 Controlli e modifiche eventuali sulla nuova struttura creata La nuova struttura creata su SQL Server non si presenta ancora robusta ed affidabile, necessita di qualche perfezionamento: in seguito sono riportati alcuni accorgimenti che vanno seguiti al fine di ottenere il miglior risultato possibile dalla migrazione effettuata. Valori NULL Nel capitolo 5 sono state citate le “debolezze” dell’ Upsizing Tool di Microsoft Access 2003. Una di queste debolezze è la totale mancanza nel migrare le informazioni riguardanti la gestione dei valori nulli sui campi delle tabelle. Pertanto alla luce di quanto detto sarà necessario, una volta terminata la migrazione, controllare manualmente ogni tabella del database e modificare queste informazioni (riferendosi ovviamente alla struttura originale del database stesso). Questo è un passo molto importante: trascurarlo porterebbe certamente a seri problemi e incoerenze nella struttura della base di dati. Modifiche sui datatype Sebbene sia vero che lo strumento per l’ upsize esporti molto bene le informazioni riguardanti i datatype dei campi delle tabelle, tuttavia per ottimizzare la base di dati al meglio (anche in vista di passaggi futuri a versioni successive di SQL Server) è bene prestare attenzione a due dettagli. In primo luogo, l’ Upsizing Tool trasforma i campi Access MEMO in campi NTEXT di SQL Server: sarebbe preferibile, invece, impostare il tipo di dati di questi campi a NVARCHAR(max); in secondo luogo, i campi OLE Object vengono esportati come campi IMAGE, mentre un’ ulteriore ottimizzazione vedrebbe questi campi trasformati a VARBINARY(max) (a tal proposito si veda anche il Capitolo 5). 34
  • 42. 6.4 Aggiunta di nuove funzionalità al database migrato Spesso la migrazione di una base di dati non rappresenta solo il passaggio di un sistema da un ambiente ad un altro, ma costituisce anche una buona occasione per apportare migliorie e aggiungere nuove funzionalità al database stesso: questo è ciò che è stato fatto anche nella migrazione del database di OnLife, introducendo nuovi vincoli, proprietà e controlli azionati dagli eventi sulle tabelle (Triggers). vincoli 6.4.1 Nuovi vincoli e proprietà per le tabelle e i loro campi In primo luogo, si desiderava effettuare un controllo sui campi di alcune tabelle, affinchè si fosse certi che i valori contenuti in essi non fossero errati o incoerenti con la reale situazione. Ad esempio, nella tabella dei Carichi Contabili si desiderava che, qualora il valore del campo MezzoPagamento fosse 'B' (ovvero Bonifico), il campo IBAN fosse assolutamente NULL e, viceversa, qualora MezzoPagamento fosse 'R' (ovvero RID) si voleva che il campo IBAN fosse assolutamente valorizzato: in effetti non avrebbe avuto alcun senso, qualora il pagamento fosse stato bonifico, che il campo IBAN fosse stato valorizzato. Questo vincolo (ed altri simili) sono stati implementati a livello di tabella; ed in particolare, il vincolo sopra citato è stato espresso dalla seguente relazione: (MezzoPagamento = 'R' AND IBAN IS NOT NULL) OR (MezzoPagamento = 'B' AND IBAN IS NULL) 6.4.2 Creazione di Triggers per la gestione di eventi Una funzionalità implementata dall’ RDBMS SQL Server, che in Access invece non si ritrova, è quella dei Triggers: apposite procedure programmabili che vengono eseguite in funzione del verificarsi di certi eventi (come, ad esempio, l’ inserimento/cancellazione o la modifica di un record di una tabella). 35
  • 43. I Triggers sono una funzionalità molto potente che rende il database capace di “reagire” a certe situazioni, risultando in tal modo più dinamico; inoltre, essi costituiscono uno strumento in più per specificare e mantenere vincoli di integrità anche complessi. Si è deciso così di avvalersi di queste procedure per rafforzare, ad esempio, il vincolo di integrità sul campo Email della tabella delle email; questo trigger effettua un controllo in fase di inserimento e di aggiornamento del record della tabella, verificando ogni volta che l’ indirizzo email specificato sia (almeno) formalmente valido. Il codice del trigger è il seguente: CREATE TRIGGER [dbo].[chk_Email] ON [dbo].[Email] FOR INSERT,UPDATE AS declare @email nvarchar(80) declare @start int declare @end int declare @tld nvarchar(40) declare @tld_tmp nvarchar(40) declare @id int set @email = (SELECT email FROM inserted) set @end = (SELECT LEN(email) FROM inserted) set @start = (SELECT (CHARINDEX('@',email)+1) FROM inserted) set @tld = SUBSTRING(@email,@start,@end) BEGIN SET NOCOUNT ON; -- Controllo della presenza della chiocciola e che ci sia almeno -- una lettera prima di essa SET @id = (SELECT ID FROM inserted) IF(((SELECT CHARINDEX('@',email) FROM inserted) = 0) OR ((SELECT CHARINDEX('@',email) FROM inserted) = 1)) 36
  • 44. BEGIN UPDATE Email SET UsoEmail = 1 WHERE ID = @id END -- Se si arriva al prossimo IF allora la chiocciola è presente -- nell'indirizzo email e prima di essa c'è almeno una lettera. -- Controlliamo ora che ci sia una stringa anche dopo la chiocciola -- e che vi sia almeno un punto al suo interno. -- ************************************************************** -- La stringa dovrà essere lunga come minino 3 caratteri, se -- consideriamo il seguente esempio: -- Un indirizzo email dove il nome del dominio (es: yahoo, -- hotmail, gmail, ecc..) è lungo solamente un carattere -- (anche se è una situazione abbastanza improbabile!) e il -- tld (es: .it, .com, .org, ecc..) ha almeno 2 caratteri -- (non esistono certamente nomi di tld che consistono di -- un solo carattere!!) -- Effettuando un controllo di questo tipo, esempi di validi -- indirizzi email potrebbero essere: -- +----------------------+ -- | 1. a@b.it | -- | 2. io@z.ru | -- | 3. qualcuno@a.it | -- +----------------------+ -- I quali sono indirizzi improbabili, ma per lo meno -- formalmente validi -- ************************************************************** ELSE IF(((SELECT (LEN(email)+1) FROM inserted) - (SELECT (CHARINDEX('@',email)+1) FROM inserted)) < 3) BEGIN UPDATE Email SET UsoEmail = 1 WHERE ID = @id END 37
  • 45. -- Controlliamo che nella stringa successiva alla chiocciola -- non vi sia un'ulteriore chiocciola, altrimenti l'indirizzo -- non sarebbe formalmente valido: ELSE IF((SELECT CHARINDEX('@',@tld) FROM inserted) <> 0) BEGIN UPDATE Email SET UsoEmail = 1 WHERE ID = @id END -- Controlliamo che ci sia almeno un punto nella stringa che segue -- la chiocciola: ELSE IF((SELECT CHARINDEX('.',@tld) FROM inserted) = 0) BEGIN UPDATE Email SET UsoEmail = 1 WHERE ID = @id END -- Se siamo arrivati fino a qui significa che l'indirizzo immesso -- ha le seguenti caratteristiche: -- +---------------------------------------------------------+ -- | > Ha SOLO una chiocciola | -- | > Prima della chiocciola c'è ALMENO 1 lettera | -- | > Dopo la chiocciola ci sono ALMENO 3 lettere | -- | > Nella stringa dopo la chiocciola c'è ALMENO 1 punto | -- +---------------------------------------------------------+ -- Ora però dobbiamo pensare al caso in cui il dominio non sia -- di primo livello, quindi l' email potrebbe essere della forma: -- > someone@livello2.livello1.it -- oppure addirittura: -- > someone@livello3.livello2.livello1.it -- e così via... -- Memorizzeremo nella variabile @tld la sottostringa che parte -- dal punto e va fino alla fine dell'indirizzo, e poi agiremo così: 38
  • 46. -- +---------------------------------------------------------+ -- | > Se nella sottostringa è presente un punto, otteniamo | -- | una nuova sottostringa come fatto precedentemente | -- | > Se nella sottostringa non è presente nessun punto e | -- | non è nulla (es: “someone@yahoo.” non è valido, | -- | perchè dopo il punto non c'è niente!) allora abbiamo | -- | finito. | -- +---------------------------------------------------------+ ELSE BEGIN WHILE (CHARINDEX('.',@tld) <> 0) begin set @start = CHARINDEX('.',@tld) + 1 set @end = LEN(@tld) set @tld_tmp = SUBSTRING(@tld,@start,@end) set @tld = @tld_tmp end IF(LEN(@tld) < 2) begin UPDATE Email SET UsoEmail = 1 WHERE ID = @id end END END In caso di inserimento di un indirizzo email formalmente non valido, viene visualizzato un errore e l’ azione non viene eseguita: il vincolo di integrità sul campo Email risulta quindi rafforzato ulteriormente con questo trigger. 6.5 Migrazione del back end del Sistema Informativo Una volta migrata la base di dati, bisogna esaminare il back end: naturalmente ci saranno delle modifiche da fare nel codice VBA dei moduli/classi del software, soprattutto per quanto riguarda le query annidate al loro interno (si veda il capitolo 5.2, “Le principali differenze nelle query tra Access ed SQL Server”). 39
  • 47. 6.5.1 Importazione dei moduli/classi e maschere “vecchi” nel nuovo Progetto Access *.adp La prima cosa da fare è importare nel nuovo progetto i moduli, le classi e le maschere presenti nel file *.mdb. Fare questo è molto semplice: è sufficiente aprire il file *.adp, cliccare col tasto destro nella finestra interna di progettazione del database e selezionare la voce “Importa…” (figura 8) dal menu visualizzato. Figura 8 – Il primo passo per l’ importazione di moduli, maschere e classi Verrà richiesto da quale file si desidera effettuare l’ importazione e successivamente si aprirà una finestra, dalla quale si possono selezionare gli oggetti che si desidera importare (tabelle, moduli e classi, maschere…): basterà selezionare tutte le maschere ed i moduli ed infine premere il tasto “OK” per procedere. 40
  • 48. Figura 9 – Il secondo passo per l’ importazione dei moduli/classi e delle maschere codice nei 6.5.2 Modifica del codice contenuto nei moduli per la database compatibilità con il nuovo database su SQL Server A questo punto il nuovo progetto è completo di tabelle (sono solo tabelle collegate al progetto, si ricorda che le tabelle sono fisicamente gestite dal motore SQL Server), maschere, moduli e classi. La modifica del codice VBA è un lavoro che, come tutto il resto della migrazione, va affrontato con una certa metodologia sistematica ed una buona preparazione: 41
  • 49. bisogna avere ben chiaro, ancor prima di cominciare, quali saranno le parti di codice interessate maggiormente dalle modifiche. Come si può intuire dalle cose dette nei precedenti capitoli, è chiaro che le parti di codice che verranno cambiate principalmente saranno quelle in cui appaiono delle query, dal momento che queste erano state originariamente pensate per essere eseguite in Access e, pertanto, non sempre saranno compatibili con il linguaggio T-SQL che SQL Server si aspetta di ritrovare in una query. Una volta fatta la manutenzione sulle query, si analizzerà il resto del codice nell’ insieme, entrando man mano nel dettaglio, per capire se esso necessita di ulteriori modifiche di altro tipo: tuttavia questo resta un passo secondario, dal momento che la logica applicativa che non coinvolge direttamente i dati difficilmente avrà bisogno di essere cambiata. La funzione ApreTabella Riguardo le query, un ruolo centrale nel software applicativo di OnLife veniva svolto dalla funzione ApreTabella, che aveva principalmente il compito di aprire un recordet ADODB e di farlo puntare ad una tabella o query specificata: quasi tutte le query venivano eseguite dal codice VBA tramite questa funzione, che però necessitava di una modifica per funzionare nel nuovo progetto. Il codice originale della funzione era il seguente: Public Function ApreTabella(rst As ADODB.Recordset, _ strCriterio As String, _ Optional NumeroRecord As Long = 0, _ Optional nomedB As String = "", _ Optional ByRef errDecode As String = "") _ As Boolean Set rst = New ADODB.Recordset Set rst.ActiveConnection = CurrentProject.Connection ' se la tabella è in un DB diverso If nomedB <> "" Then 42
  • 50. strCriterio = ApreDBDiverso(strCriterio, nomedB) End If rst.CursorType = adOpenKeyset rst.LockType = adLockOptimistic ApreTabella = False On Error GoTo esci_apretabella rst.Open strCriterio, Options:=adCmdTableDirect If rst.RecordCount >= 0 Then NumeroRecord = rst.RecordCount ApreTabella = True End If Exit Function esci_apretabella: errDecode = err.Description End Function Come si può notare, c’ è una riga marcata in rosso: l’ istruzione adCmdTableDirect non funzionava nel nuovo *.adp, in quanto questa opzione di apertura delle tabelle viene tipicamente usata per connessioni al motore Jet (il motore usato all’ interno di Microsoft Access). Pertanto il codice della funzione ApreTabella è stato modificato nel modo che segue: Public Function ApreTabella(rst As ADODB.Recordset, _ strCriterio As String, _ Optional NumeroRecord As Long = 0, _ Optional nomedB As String = "", _ Optional ByRef errDecode As String = "") _ As Boolean Set rst = New ADODB.Recordset Set rst.ActiveConnection = CurrentProject.Connection ' se la tabella è in un DB diverso If nomedB <> "" Then 43
  • 51. strCriterio = ApreDBDiverso(strCriterio, nomedB) End If rst.CursorType = adOpenKeyset rst.LockType = adLockOptimistic ApreTabella = False On Error GoTo esci_apretabella rst.Open strCriterio, CurrentProject.Connection If rst.RecordCount >= 0 Then NumeroRecord = rst.RecordCount ApreTabella = True End If Exit Function esci_apretabella: errDecode = err.Description End Function In tal modo, viene specificato che la connessione su cui agisce il metodo Open del recordset rst è la connessione corrente del progetto Access, ovvero la connessione al server SQL. Era fondamentale effettuare questa modifica sulla funzione ApreTabella, in quanto altrimenti non si sarebbe stati in grado di eseguire quasi nessuna query dal codice VBA, rendendo in questo modo praticamente impossibile il funzionamento del nuovo sistema. Modifica delle query annidate nel codice Un altro passo fondamentale nel lavoro di manutenzione del software di OnLife era, come affermato in precedenza, la modifica delle query eseguite a livello di codice. Questo passo si rivela non molto difficoltoso, se eseguito con ordine e con sistematicità: è necessario, per ogni query presa in esame, verificare se il suo codice sia compatibile con il T-SQL (eventualmente effettuando anche un test 44
  • 52. pratico della query su SQL Server): in caso negativo, bisognerà provvedere a modificare la query secondo le considerazioni già eseposte al capitolo 5.2. Un esempio di query eseguita a livello di codice che necessitava di modifiche per l’ adattamento al T-SQL è il seguente∗: ... sqlstr = "SELECT ID " & _ "FROM PartnerTeam " & _ "WHERE Username = '" & _ credenziali.Username & "' AND " & _ " Password = '" & _ credenziali.Password & "' AND " & _ " DataInizioValidita <= #" & _ Format(Date,"mm/dd/yyyy") & "# AND " & _ " DataFineValidita >= #" & _ Format(Date, "mm/dd/yyyy") & "#" ... Questa query, per poter essere eseguita su SQL Server con esito positivo, è stata trasformata in questo modo*: ... sqlstr = "SELECT ID " & _ "FROM PartnerTeam " & _ "WHERE Username = '" & _ credenziali.Username & "' AND " & _ " Password = '" & _ credenziali.Password & "' AND " & _ " DataInizioValidita <= '" & _ Format(Date, "dd/mm/yyyy") & "' AND " & _ " DataFineValidita >= '" & _ Format(Date, "dd/mm/yyyy") & "'" ... ∗ La sintassi SQL è stata evidenziata al fine di facilitarne la lettura 45
  • 53. Come si può notare, dove nella query Access si utilizzava il simbolo "#" per i confronti sulle date, nel Transact-SQL i confronti sulle date si effettuano utilizzando gli apici singoli. Inoltre, si noti il cambio di formato utilizzato per le date: in Access veniva precedentemente utilizzato il formato mese/giorno/anno (mm/dd/yyyy), mentre per fare funzionare la stessa query su SQL Server è stato necessario cambiare il formato della data a giorno/mese/anno (dd/mm/yyyy). La proprietà RowSourceType Spesso si ha la necessità di impostare come fonte di un oggetto di una maschera (una textbox, combobox, ecc…) una tabella o una query. Normalmente nei progetti Access *.mdb ciò viene fatto impostando la proprietà RowSourceType dell’ oggetto in questione: elemento.RowSourceType = "Table/Query" D’ altra parte i progetti *.adp si collegano ad SQL Server e, pertanto, il concetto di “Query” com’ era inteso in Access non ha più senso, essendo sostituito da quello di “Vista”. È per questo motivo che, per rendere correttamente funzionante un oggetto in cui viene utilizzata la proprietà RowSourceType, sarà opportuno modificare la precedente riga di codice in questo modo: elemento.RowSourceType = "Table/View/StoredProc" Si può facilmente intuire che la sigla "Table/View/StoredProc" indica come sorgente per un controllo una tabella, una vista oppure una stored procedure, il che è corretto per un progetto che si interfaccia con SQL Server. 46
  • 54. Caso particolare: l’ oggetto DAO.Database Esistono due differenti librerie per l’ accesso programmato ai dati in Access: i Data Access Objects, più comunemente DAO, e gli ActiveX Data Objects, meglio chiamati ADO. Le versioni precedenti di Access facevano largo uso della libreria DAO, usata come interfaccia al motore di database Jet. Se è vero che i DAO sono ancora presenti in Access, tuttavia non sono la miglior libreria da utilizzare per le nuove applicazioni: infatti per esse è preferibile usare la metodologia ADO, più recente. Nella manutenzione del codice del back end di OnLife è stata osservata qualche occasione in cui veniva utilizzata ancora la vecchia metodologia DAO. Di seguito viene riportato il codice della funzione QueryComando che, come suggerisce il nome stesso, aveva il compito di eseguire sul database quelle che in Access vengono definite “Query di comando”: Public Function QueryComando(strsql As String) As Boolean Dim dbs As DAO.Database QueryComando = False On Error GoTo segnala Set dbs = CurrentDb dbs.Execute strsql Set dbs = Nothing QueryComando = True Exit Function segnala: Messaggio msgDialog, "Non eseguita causa errore la " & _ "query di comando " & strsql End Function 47
  • 55. Il codice appena visto, se già non era più considerato adatto per i nuovi progetti Access, nell’ *.adp che si collegava ad SQL Server non funzionava: in particolare l’ errore si incontrava all’ istruzione contrassegnata in rosso, ove (evidentemente) Access si aspettava che l’ oggetto CurrentDb fosse un database Access, pertanto l’ istruzione non funzionava correttamente. È per questo motivo che la precedente funzione (e così tutte le funzioni analoghe, facenti uso della libreria DAO) è stata modificata nel modo seguente: Public Function QueryComando(strsql As String) As Boolean Dim rst As ADODB.Recordset Set rst = New ADODB.Recordset QueryComando = False On Error GoTo segnala rst.Open strsql, CurrentProject.Connection Set rst = Nothing QueryComando = True Exit Function segnala: Messaggio msgDialog,"Non eseguita causa errore la " & _ "query di comando " & strsql End Function Si nota che la metodologia di accesso ai dati è stata cambiata da DAO ad ADO: in particolare si è fatto uso dell’ ADODB Recordset, un oggetto usato molto frequentemente per l’ accesso ai dati in Access. Nel metodo Open del recordset è stata specificata come connessione attiva la CurrentConnection, ovvero la connessione corrente ad SQL Server, pertanto il codice così strutturato può funzionare correttamente. 48
  • 56. pseudo- 6.5.3 Il meccanismo di pseudo-paginazione dei risultati nel back end di OnLife Nel vecchio sistema, il modo in cui venivano visualizzati i dati nelle maschere era il seguente: veniva eseguita una query e si visualizzavano tutti i risultati restituiti da essa. Se per query strutturalmente semplici e che restituivano al più una centinaia di risultati questo meccanismo si rivelava tutto sommato efficace, per query che restituivano qualche migliaia di risultati o che, pur restituendo pochi risultati, avevano una complessità strutturale (a livello di codice SQL) piuttosto elevata questo modo di visualizzare le informazioni si rivelava tutt’ altro che efficiente, sollevando seri problemi performance (soprattutto in termini di tempo di attesa per la visualizzazione delle informazioni). Si è pensato pertanto ad una soluzione che permettesse di migliorare le performance del sistema in questo senso, giungendo alla seguente idea: su ogni maschera inizialmente si sarebbero visualizzati soltanto i primi 50 risultati della query, rendendo così l’ esecuzione della stessa (e di conseguenza anche l’ apertura della relativa maschera) molto più veloce. Figura 10 – La schermata dei Partner con i primi 50 risultati visualizzati. In basso a sinistra di può basso notare la nuova combobox inserita nell’ interfaccia. 49
  • 57. Successivamente l’ utente avrebbe potuto scegliere, mediante un’ apposita combobox se visualizzare più risultati o addirittura l’ intero set di risultati. Si potrebbe obiettare che questo meccanismo non è l’ ideale, in quanto parte già dal presupposto che l’ utente voglia visualizzare solo i primi 50 risultati di una query: e l’ obiezione sarebbe corretta, se non fosse che da un’ analisi è risultato che gli utenti del sistema informativo raramente hanno bisogno di visionare una quantità maggiore dei primi 50 record proposti con questo meccanismo. A livello di implementazione, questa pseudo-paginazione è relizzata con una variabile globale numerica, inizializzata a 50, il cui valore può essere cambiato mediante la già citata combobox: questa variabile sarà poi utilizzata, a livello di codice, per limitare i risultati della query eseguita con uno statement (T-SQL) TOP. Per fare un esempio che possa rendere più chiare le idee, supponendo che la variabile numero_risultati abbia correntemente il valore di 50 e che venga eseguita una query sulla tabella Partner per la maschera dei Partners, il codice VBA∗ che eseguirà la query sarà di questo tipo: rst.Open "SELECT TOP (" & numero_risultati & ") " & _ "FROM Partner " La pseudo-paginazione introdotta ha migliorato notevolmente le performance in termini di velocità del sistema: basti pensare che, prima della modifica, l’ accesso alla maschera Contratti richiedeva un tempo medio di attesa di 10 secondi mentre, dopo la modifica, questo tempo si è ridotto a circa 5 secondi. 6.5.4 Test e Debug Sebbene questo argomento sia discusso alla fine del capitolo, ciò non significa che il lavoro di test e debug vada fatto solamente alla fine di tutte le modifiche. ∗ La sintassi SQL è stata evidenziata al fine di facilitarne la lettura 50
  • 58. Al contrario, è di assoluta importanza effettuare numerosi test anche durante tutto lo sviluppo e la manutenzione del software, analizzando gli errori e ciò che non funziona correttamente e intervenendo ove opportuno. In particolare è bene riflettere sull’ importanza di uno strumento molto semplice – ma di grande aiuto per lo sviluppatore – messo a disposizione da Access: lo strumento di debug. Utilizzando il debugger è possibile seguire passo-passo (con l’uso di breakpoints) l’ esecuzione delle istruzioni del software scritto, in modo tale da permettere allo sviluppatore di: • Scoprire errori di cui non si era accorto; • Capire in che punto del codice si verifica un errore di cui non si riusciva a capire la causa. È pertanto di grande importanza comprendere l’ utilità di uno strumento di questo tipo, al fine di sviluppare software in modo efficiente, ordinato e serio. 51
  • 59. CAPITOLO 7 La migrazione vera e propria Esportato il database in locale e testato il back end e verificato che tutto funzioni correttamente, si è finalmente pronti per la migrazione vera e propria. Una buona strategia per questa fase del lavoro è composta dai passi di seguito esposti: • Ricreazione della struttura della base di dati sul server in rete; • Migrazione dei dati dal vecchio database Access al nuovo database su SQL Server; • Installazione del sistema informativo sulle macchine aziendali; • Collaudo ed eventuale manutenzione del sistema messo in funzione. 7.1 Creazione della struttura del database sul server in rete rete È certamente impensabile ricreare manualmente per la seconda volta tutta la struttura della base di dati, agendo sul server in rete: ciò comporterebbe uno spreco di tempo che si può facilmente evitare. In questo senso, fortunatamente SQL Server mette a disposizione una funzione che eviterà molto lavoro che altrimenti si sarebbe dovuto svolgere manualmente. 52
  • 60. 7.1.1 La funzione “Script table as…” di SQL Server La funzione usata è la “Script table as…”: essa crea un file *.sql con uno script in linguaggio Transact-SQL, contenente degli statements che, una volta eseguito lo script, creeranno la struttura della tabella e dei suoi vincoli. In realtà è un po’ approssimativo dire solamente che esiste la funzione “Script Table as…”; in realtà esistono le: • “Script Table as…”, per le tabelle e le relazioni; • “Script View as…”, per le viste; • “Script Stored Procedure as…”, per le stored procedures; • “Script Function as…”, per le user defined functions. Per creare lo script *.sql sopra citato, è necessario selezionare tutte le tabelle del database e cliccare col tasto destro sulle tabelle selezionate: dal menu che appare si seleziona a questo punto la voce “Script Table as…”, si sceglie tra le diverse opzioni quella “CREATE To” e infine si sceglie l’ opzione “File…”. Eseguendo lo script così ottenuto sul server in rete, verrà ricreata la stessa struttura della base di dati che risiede correntemente sulla macchina locale usata fino a questo punto. Per quanto riguarda la creazione delle viste, stored procedures e user defined functions sul nuovo database, il procedimento da seguire è esattamente lo stesso di quello già seguito per le tabelle: naturalmente ogni oggetto avrà la sua opzione “Script…”, a seconda che sia una vista, stored procedure oppure user defined function. 7.1.2 Esecuzione degli script sul server in rete A questo punto non rimane che un semplice passo: eseguire gli scripts creati sul server in rete. Tuttavia, anche in tale occasione bisogna prestare attenzione a ciò che si sta facendo, in quanto c’ è ancora una probabilità che si verifichi un errore. 53
  • 61. L’ ordine di esecuzione degli statements CREATE Come tutti gli strumenti automatizzati ad uso generico (e pertanto non pensati, progettati e realizzati specificamente di volta in volta per il caso considerato), anche la funzione “Script…” a volte può presentare qualche sorpresa. Nel caso specifico di OnLife, nell’ esecuzione dello script per ricreare le viste sul server di produzione si è verificato un errore, dovuto ad un errato ordine di alcuni statements CREATE nello script T-SQL. Ad esempio, l’ istruzione CREATE per la vista MailOfPartnerQry, che utilizzava al suo interno le viste MailOfPartnerQryArch, MailOfPartnerQryIN e MailOfPartnerQryOUT, si trovava prima delle istruzioni che avrebbero duvuto creare le altre tre viste coinvolte: l’ istruzione CREATE in questione restituiva quindi un errore, in quanto utilizzava delle viste che non erano ancora state create. La soluzione a questo problema è abbastanza ovvia: infatti è stato sufficiente spostare le istruzioni per la creazione delle tre viste (MailOfPartnerQryArch, MailOfPartnerQryIN e MailOfPartnerQryOUT) prima delle istruzioni per la creazione della vista MailOfPartnerQry stessa. 7.2 Scrittura di un piccolo software “ad - hoc” per la dati migrazione dei dati Le stesse considerazioni fatte in precedenza per la modalità di migrazione, valgono anche in questo caso: si potrebbe decidere di esportare i dati al nuovo database utilizzando il tool di Access o quello messo a disposizione da SQL Server, tuttavia per grosse moli di dati è preferibile scegliere una strada che permetta un maggior controllo e una maggior sicurezza sul risultato ottenuto. Per questo motivo, in occasione della migrazione dei dati del database di OnLife si è deciso di sviluppare un piccolo software ad-hoc, progettato e realizzato specificamente per il caso corrente (figura 11). 54
  • 62. Figura 11 – Il software di migrazione sviluppato per la migrazione della base di dati di OnLife 7.2.1 La necessità di introdurre un meccanismo di la automazione per la migrazione dei dati In presenza di più di una ventina di tabelle (70 nel caso specifico di OnLife), non sarebbe una buona soluzione realizzare un software che esegua la migrazione dei dati una tabella alla volta, richiedendo ad ogni passo la conferma per procedere; il motivo è essenzialmente uno: ciò richiederebbe troppo tempo. Quando si decide di entrare in produzione con un nuovo sistema bisogna farlo velocemente, in modo che l’ attività dell’ azienda non risenta di spiacevoli disagi (o, ad ogni modo, ne risenta in minima parte) e di problematici rallentamenti della produttività. Inoltre, migrare una tabella con centinaia di migliaia di record ad una base di dati su un server installato in locale può richiedere in media anche solo un tempo di attesa di 15 minuti: la situazione è ben diversa quando si vuole eseguire la stessa operazione collegandosi ad un server che si trova in rete, dove il tempo di migrazione della stessa quantità di record potrebbe trasformarsi addirittura in un’ ora o più. 55
  • 63. Delle considerazioni più dettagliate in merito alla stima dei tempi di migrazione verranno esposte al capitolo 7.2.3. In base ai ragionamenti appena fatti, si conclude che non è possibile eseguire la migrazione manualmente, tabella per tabella, bensì si rende necessaria l’ introduzione (nel software di migrazione) di un meccanismo di automazione. Nel caso di OnLife, si è pensato alla seguente strategia: si è scelto un giorno prestabilito in cui, a fine giornata lavorativa, si sarebbe eseguito il software automatizzato per la migrazione, lasciandolo in esecuzione durante tutta la notte. In tal modo, nella mattinata della giornata seguente, con ogni probabilità la migrazione sarebbe già stata completata e si sarebbe potuto procedere senza intoppi all’ installazione del nuovo back end del sistema informativo sui calcolatori aziendali. Un’ ottima soluzione quella appena descritta, che avrebbe permesso (a meno di imprevisti) di eseguire la migrazione della base di dati al server di produzione senza “sacrificare” preziose ore lavorative. 7.2.2 Il problema dell’ IDENTITY_INSERT e la sua soluzione Volendo realizzare un software che gestisca la migrazione dei dati dalle tabelle vecchie a quelle nuove, non bisogna lasciare niente al caso. In particolare bisogna considerare che, generalmente, non è possibile in una tabella modificare il valore di un campo di tipo contatore con una query di inserimento. Si consideri, ad esempio, la seguente tabella: ExampleTable Field DataType ID INT, AUTO_INCREMENT Field 1 VARCHAR Field 2 BIT ... ... Tabella 3 – Tabella di esempio, su cui è definita un’ identità sul campo ID 56
  • 64. La query di inserimento INSERT INTO ExampleTable (ID, Field1, Field2, ...) VALUES (45, 'stringa', 'False', ...) restituirà l’ errore Quando IDENTITY_INSERT è OFF non è possibile inserire un valore esplicito per la colonna Identity nella tabella 'ExampleTable'. Sarà pertanto necessario introdurre una modifica nelle query, che permetta di inserire i valori desiderati anche in campi di tipo contatore (Identity). Tale obiettivo viene raggiunto impostando la proprietà IDENTITY_INSERT a ON per la tabella su cui si vuole eseguire la query di inserimento. L’ estratto di codice VBA∗ che segue è stato ripreso dal software scritto per la migrazione delle tabelle del database di OnLife: rstRem.Open "DECLARE @err INT " & _ "BEGIN TRY " & _ "SET IDENTITY_INSERT " & tableName & " ON " & _ "END TRY " & _ "BEGIN CATCH " & _ "SET @err = ERROR_NUMBER() " & _ "END CATCH " & _ "IF @err <> 0 " & _ "BEGIN " & _ "INSERT INTO " & tableName & " (" & fields_ & ") " & _ "VALUES (" & values_ & ") " & _ "END " & _ "ELSE " & _ "BEGIN " & _ ∗ La sintassi SQL è stata evidenziata al fine di facilitarne la lettura 57
  • 65. "SET IDENTITY_INSERT " & tableName & " ON " & _ "INSERT INTO " & tableName & " (" & fields_ & ") " & _ "VALUES (" & values_ & ") " & _ "SET IDENTITY_INSERT " & tableName & " OFF " & _ "END" Di fronte a questa query sembra quasi naturale chiedersi perché non ci si sia limitati ad eseguire il solo statement per impostare l’ IDENTITY_INSERT ad ON, seguito dalla query di inserimento. Il motivo è che non tutte le tabelle del database avevano un’ identità con auto-incremento definita su di esse: questo fatto ha reso necessaria l’ introduzione di un’ ulteriore modifica della query. In tal senso, viene prima eseguita un’ istruzione T-SQL per testare se esiste sulla tabella corrente un’ identità, generando così due possibili casi: • Si verifica un errore nel test dell’ istruzione "SET IDENTITY_INSERT nome_tabella ON": ciò significa che non era definita alcuna identità; l’ errore viene catturato con l’ apposita istruzione CATCH. A questo punto viene eseguita la sola query di inserimento ed infine termina lo statement. • Il test non genera alcun errore: è definita un’ identità sulla tabella. Viene eseguita nuovamente l’ istruzione per impostare IDENTITY_ INSERT a ON e successivamente si esegue la query di inserimento. Una volta terminata l’ esecuzione della query, la proprietà IDENTITY_ INSERT viene reimpostata al valore OFF (se era stata precedentemente impostata a ON): se non si facesse questo, cambiando successivamente la tabella sulla quale eseguire le query ed eseguendo nuovamente l’ istruzione "SET IDENTITY_INSERT nome_tabella ON" si riceverebbe l’ errore IDENTITY_INSERT è già impostata su ON per la tabella 'Tabella1'. Impossibile eseguire l'operazione SET per la tabella 'Tabella2' 58
  • 66. in quanto la proprietà IDENTITY_INSERT può essere impostata a ON solo su una tabella alla volta. tempo 7.2.3 Stima del tempo di migrazione del database di OnLife In genere potrebbe essere utile farsi un’ idea dei tempi medi di migrazione delle singole tabelle, in modo da poter fare una stima del tempo totale richiesto per l’ operazione relativa all’ intera base di dati. In particolare, sarebbe opportuno osservare in funzione di quali parametri varia il tempo di migrazione di una singola tabella e se queste variazioni siano lineari oppure no. Il software sviluppato per la migrazione del database di OnLife era stato progettato in modo da visualizzare a schermo, durante la sua esecuzione, una traccia delle operazioni effettuate di volta in volta (Figura 12). Figura 12 – Il log del software di migrazione per OnLife 59
  • 67. Tre informazioni molto importanti venivano visualizzate dal log: • Il numero di record della tabella da migrare; • L’ ora di inizio della migrazione della tabella; • L’ ora in cui è stata completata la migrazione della tabella. Schematizzando queste informazioni, facendo dei test per un numero significativo di tabelle, si è ottenuto il seguente schema (vengono trascurati i nomi delle tabelle, in quanto non sono rilevanti in questo contesto): Quantità record Ora inizio Ora fine Tempo totale (s) Tempo singolo record (s) 34 23.05.25 23.05.26 1 0,029 59 18.07.52 18.07.54 2 0,033 74 18.07.35 18.07.37 2 0,027 85 18.07.46 18.07.49 3 0,035 111 18.07.28 18.07.32 4 0,036 115 18.07.40 18.07.44 4 0,034 180 17.16.27 17.16.33 6 0,033 343 23.05.11 23.05.22 11 0,032 515 23.04.53 23.05.11 18 0,034 2.239 1.29.54 1.31.50 120 0,053 2.315 1.31.50 1.33.17 120 0,051 4.896 18.07.57 18.10.56 180 0,036 6.292 23.05.26 23.10.43 300 0,047 6.374 18.40.08 18.43.44 180 0,028 33.862 17.48.29 18.07.28 1.140 0,033 50.103 18.10.56 18.40.08 1.800 0,035 50.122 18.43.44 19.11.50 1.680 0,033 52.331 22.35.18 23.04.53 1.140 0,021 56.111 17.16.33 17.48.28 1.920 0,034 80.634 21.50.15 22.35.17 2.700 0,033 132.959 20.34.32 21.50.15 3.960 0,029 132.959 19.11.50 20.34.32 4.380 0,032 236.580 23.10.43 1.29.54 4.740 0,020 alcune Tabella 4 – Schema dei tempi medi di migrazione di alcune tabelle del database 60