Your SlideShare is downloading. ×
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
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
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
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
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
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
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
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
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
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
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
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
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
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
Migrazione della base di dati operativa di un'assicurazione vita diretta
Migrazione della base di dati operativa di un'assicurazione vita diretta
Upcoming SlideShare
Loading in...5
×

Thanks for flagging this SlideShare!

Oops! An error has occurred.

×
Saving this for later? Get the SlideShare app to save on your phone or tablet. Read anywhere, anytime – even offline.
Text the download link to your phone
Standard text messaging rates apply

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

1,353

Published on

Published in: Technology
0 Comments
0 Likes
Statistics
Notes
  • Be the first to comment

  • Be the first to like this

No Downloads
Views
Total Views
1,353
On Slideshare
0
From Embeds
0
Number of Embeds
0
Actions
Shares
0
Downloads
24
Comments
0
Likes
0
Embeds 0
No embeds

Report content
Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
No notes for slide

Transcript

  • 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
  • 68. Tempo di migrazione delle singole tabelle in funzione del numero di record Tempo migrazione 5000 4000 3000 Tempo totale migrazione 2000 tabella 1000 0 1 0 5 15 92 2 2 13 1 23 9 80 34 74 86 12 11 5 11 18 51 29 65 23 62 33 50 56 Quantità record tempo Figura 13 – Variazione del tempo di migrazione delle singole tabelle in funzione del numero di record (i tempi sono espressi in secondi) In base ai dati iniziali sono stati calcolati anche: • Tempo totale (s) : il tempo totale richiesto per la migrazione della tabella considerata, espresso in secondi; • Tempo singolo record (s) : il tempo medio richiesto per la migrazione di un singolo record della tabella considerata, espresso in secondi. Questo tempo è stato ottenuto dividendo il tempo totale di migrazione per il numero di record migrati. Si può notare che il tempo medio per la migrazione di un singolo record non varia molto da tabella a tabella: ciò può portare alla conclusione che evidentemente gli unici fattori che incidono in maniera relativamente significativa su questa variazione sono il numero di campi di cui è composto il record e il carico del server al momento in cui si sta effettuando la migrazione. Assumendo che, quando si effettua la migrazione, questi due fattori non varino in modo drastico nel tempo (il che è abbastanza verosimile), si può calcolare il tempo medio approssimativo per la migrazione di un singolo record al server, indifferentemente dalla tabella: 61
  • 69. 0,029 + 0,033 + 0,027 + 0,035 + 0,036 + 0,034 + 0,033 + 0,032 + 0,034 t= + 23 0,053 + 0,051 + 0,036 + 0,047 + 0,028 + 0,033 + 0,035 + 0,033 + 0,021 + 0,034 + + 23 0,033 + 0,029 + 0,032 + 0,020 + = 0,034 s 23 A questo punto, si potrebbe pensare di fare una stima del tempo totale di migrazione: calcolando che il numero totale di record, sommando i contributi di ogni singola tabella del database, è numero records = 849.810 il tempo totale per la migrazione di questo numero di record sarebbe dato dal seguente calcolo: tempo totale migrazione = (numero records) * t = = (849.810 * 0,034) s = 28.893,54 s ≈ 8h e 1 min Questa stima si rivela sorprendentemente verosimile. Infatti la migrazione della base di dati di OnLife, essendo iniziata alle ore 17:16 ed essendo terminata alle ore 01:33, è stata completata in 7 ore e 34 minuti: ciò vuol dire che nella stima (si ricorda che essa è, per natura, approssimativa) è stato commesso un errore di soli 27 minuti. 7.3 Installazione del Sistema Informativo in ambiente aziendale A questo punto, il nuovo sistema è completo e pronto per la messa in funzione: il passo successivo è la sua installazione sulle macchine aziendali. Questo è un passo molto importante nell’ arco di tutto il lavoro: infatti in questa occasione avviene il test da parte degli utenti finali, coloro che dovranno utilizzare il sistema ogni giorno svolgendo il loro lavoro. 62
  • 70. 7.3.1 Collaudo e manutenzione Gli utilizzatori finali, ovvero coloro che già in precedenza utilizzavano il “vecchio” sistema, sono le persone che meglio conoscono il software nel suo utilizzo più dettagliato: generalmente ci si aspetta che loro trovino la maggior parte degli errori di cui non ci si era ancora accorti nelle prime fasi di test (durante lo sviluppo). Per questo motivo si dice che la fase di collaudo è la più importante, cioè perché determinerà la bontà con cui è stato svolto il lavoro di sviluppo, rivelando una quantità variabile di errori più o meno gravi e rilevanti. Nel caso specifico di OnLife, nell’ ultima settimana del mese di Settembre è stata effettuata la migrazione della base di dati sul server in rete, è stato installato il software di back end nei calcolatori aziendali e si è iniziato il collaudo: in questa occasione gli utenti hanno rilevato una serie di errori (o dimenticanze) non gravi, la cui correzione ha richiesto all’ incirca 5-6 giorni. A questo punto il sistema era operativo e correttamente funzionante, pronto per entrare in produzione. 63
  • 71. Conclusioni Dopo il lavoro svolto, i tempi di risposta del Sistema Informativo sono migliorati, pertanto si conclude che il principale obiettivo che ci si era posti inizialmente è stato raggiunto. Di fatto, il nuovo database su SQL Server e il Sistema Informativo su cui è stata fatta la manutenzione sono attualmente utilizzati in produzione presso l’ azienda La Vita S.p.A a Trieste, un’ assicurazione vita diretta. 64
  • 72. Bibliografia Ken Getz, Paul Litwin, Mike Gilbert Access 2000, Manuale di programmazione Jackson Libri – Sybex, 2000 Russel Sinclair Da Access a SQL Server Mondadori Informatica, 2006 Sito internet ASPFAQ What are the main differences between Access and SQL Server? http://sqlserver2000.databases.aspfaq.com Sito internet MSDN della Microsoft http://msdn.microsoft .com Sito internet Microsoft Office Online http://office.microsoft.com Maurizio Fermeglia Dispense del corso di Basi di Dati e del corso di Complementi di Basi di Dati 65

×