Lezione Precedente Elenco Lezioni Lezione Successiva

Laboratorio di Sistemi Informativi

Importazione ed esportazione dei dati

Inserire i dati con i comandi INSERT INTO ... VALUES o con un client grafico è abbastanza complesso, ed in genere adatto quando i valori da inserire non sono eccessivamente numerosi. Se i dati sono però già disponibili, magari in un altro formato, esistono dei modi per importarli direttamente, senza doverli riscrivere.

Analogamente, è possibile esportare in formato testo i dati presenti nelle tabelle, in modo da renderli utilizzabili da altri programmi.

Script SQL

Uno dei modi più semplici per importare dati in un server MySQL è utilizzare uno script, ovvero un file di testo che include i comandi SQL necessari per creare gli schemi, le tabelle ed eventualmente inserire al loro interno dei dati. Ad esempio, lo script aerei.sql serve a creare la tabella aerei vista nelle lezioni precedenti, insieme a tutti i dati in essa contenuti. All'interno dello script vi sono una serie di comandi SQL che abbiamo già incontrato, ma con un paio di novità:
  1. DROP TABLE IF EXISTS <nometabella> : cancella la tabella <nometabella>, se esiste. A differenza di DROP TABLE <nometabella>, la variante con IF EXISTS  non da errore nel caso <nometabella> non esista. Per questo è particolarmente utile per script che ricreano uno schema da zero, senza che si sappia in anticipo se alcune tabelle esistono o meno.
  2. INSERT INTO <nometabella> VALUES (<lista1>), (<lista2>), ... : il comando INSERT consente di inserire più righe nella tabella. Inserire più righe con un singolo comando comporta una maggiore velocità di esecuzione e un risparmio sul numero di caratteri da digitare sulla tastiera.

Si tratta di due estensioni non standard di MySQL, quindi è bene non utilizzarle all'interno di programmi che potrebbero essere portati a DBMS differenti.

Una volta che uno script è creato, bisogna avere un modo per eseguirlo. In MySQL di modi ce n'è essenzialmente due:
  1. dal prompt del monitor di MySQL eseguire il comando source <nomefile> (o il sinonimo \. <nomefile>);
  2. dal prompt della shell di Linux, eseguire il programma monitor mysql con i seguenti parametri: mysql <nome_schema> < <nomefile>, dove <nome_schema> è il nome dello schema all'interno del quale si vuole eseguire lo script. Il simbolo < tra <nome_schema> e <nomefile> va inserito così com'è, e prende il nome di operatore di redirezione dell'input: dice al sistema operativo che l'input del programma mysql non deve provenire da tastiera, come è normalmente, ma dal file indicato.

    In aula informatizzata il comando deve essere ovviamente mysql -h goemon -p <nome_schema> < <nomefile>, dove <nome_schema> è il vostro numero di matricola. Nel seguito, daremo sempre per scontato l'uso delle opzioni -h e -p quando necessarie.

Perché questi comandi funzionino, il file contenente lo script deve essere nella directory corrente. Se così non fosse, si potrebbe inserire, invece del semplice nome del file dello script, il percorso completo (assoluto o relativo) dello stesso.

Le due varianti per l'esecuzione di uno script sono simili. Tuttavia, il comando SOURCE restituisce un messaggio di errore (o di corretta esecuzione) alla fine di ogni comando SQL. Se lo script è lungo, questo può rallentarne di molto l'esecuzione. È preferibile, in tal caso, usare la seconda variante.

Talvolta, lo script che si vuole leggere contiene al suo interno il comando USE necessario a selezionare lo schema opportuno. In tal caso, si può omettere il nome dello schema dalla riga di comando del programma mysql e usare semplicemente mysql < <nomefile>.


ATTENZIONE. Uno script SQL per poter essere eseguito deve essere memorizzato in un file di testo. Questo vuol dire che deve essere privo di qualsiasi tipo di formattazione. Ad esempio un testo in HTML non può essere eseguito nè con il comando SOURCE nè con mysql < <nomefile>. La stessa cosa vale per i file di Microsoft Word (.doc), OpenDocument (.odw), AbiWord (.abw) e altri. In generale, se un file è visibile senza "stranezze" con il comando cat dalla shell di Linux, o con l'editor di testi usato a lezione, allora si può usare come script SQL.

Dump degli schemi

Una delle applicazioni principali degli script SQL è quella di trasferire uno schema da un server MySQL ad un altro. Per far ciò, serve un modo di generare uno script SQL a partire da uno schema già presente nel server. A questo scopo può servire egregiamente il programma mysqldump. Ad esempio

mysqldump <nome_schema>

visualizza l'elenco dei comandi necessari per ricostruire esattamente lo schema <nome_schema> allo stato attuale. Questo elenco tecnicamente prende il nome di dump dello schema. Possiamo anche salvare il dump, invece di guardarlo sullo schermo, con

mysqldump <nome_schema> > <nome_file>

Per mysqldump, come per mysql, occorre utilizzare le opzioni -h e -p quando si lavora in aula informatizzata.

Il carattere > prende il nome di operatore di redirezione dell'output. È il duale dell'operatore <. Indica al sistema operativo di non inviare l'output sulla finestra del terminale, ma su di un file. Il file che si è ottenuto può essere letto con il comando SOURCE da dentro il monitor di MySQL. Bisogna prima ricordarsi di selezionare lo schema in cui si vogliono inserire i dati con il comando USE. Alternativamente, dalla shell di Linux possiamo usare mysql <nome_schema> < <nome_file>.

Con la sintassi

mysqldump <nome_schema> --databases <db1>...<dbn>

si può effettuare il dump di più schemi contemporaneamente. In questo modo mysqldump genera anche i comandi CREATE DATABASE (che, se ricordate, è un sinonimo di CREATE SCHEMA) necessari per la creazione degli schemi ed i comandi USE. Il file generato può essere letto con il monitor di MySQL, sempre con il comando SOURCE, o dalla shell con mysql < <nomefile>.

Esportare i dati con mysqldump e rileggerli da un altra macchina è il modo migliore per trasferire dati da un sistema ad un altro, in quanto funziona indipendentemente dal tipo di sistema operativo o processore utilizzato nei due sistemi.

Redirezione dell'input e dell'output

Prima di andare avanti, facciamo notare brevemente che gli operatori di redirezione < e > non sono specifici di MySQL, ma si possono applicare a qualsiasi programma eseguibile dalla shell di Linux. Ad esempio, mentre normalmente il programma ls visualizza su schermo il contenuto di una directory, un comando come ls > catalogo non visualizza nulla, ma crea un file di nome catalogo il cui contenuto è l'elenco generato da ls.

Notare che alcune volte l'uso della redirezione cambia leggermente il funzionamento dei programmi. Ad esempio, l'output di ls e di ls > catalogo non è esattamente uguale. L'output di ls è a colori, e i file sono visualizzati su più colonne. Il file catalogo ottenuto da ls > catalogo non ha colori e presenta i file su di una sola colonna.

output a confronto tra "ls" e "ls > catalogo"

Di contro, l'output su schermo di mysqldump è esattamente identico a quello che si ottiene se lo si redirige su un file.

Dati in formato CSV

Il formato CSV e il comando LOAD DATA LOCAL INFILE

Supponiamo ora di voler aggiungere altri elementi alla tabella aerei, e di avere i dati in un file datiaerei.txt. Notare che nel file sono presenti gli stessi campi della tabella (eccetto id e commento): ogni campo è separato da un altro da una tabulazione (attenzione una tabulazione, non uno spazio), e ogni riga rappresenta una nuova istanza.

Il comando SQL che utilizziamo per inserire questi dati è

LOAD DATA LOCAL INFILE 'datiaerei.txt' INTO TABLE aerei (produttore,modello, dataimm,numposti);

LOAD DATA LOCAL INFILE è il comando per caricare i dati da un file di testo. Nel comando specifichiamo:
Notare che non inseriamo nulla per il campo id perchè esso viene generato automaticamente grazie alla funzione auto_increment. Allo stesso modo, il campo commento viene automaticamente settato a NULL che è il valore di default.

Ci sono altri parametri che posso essere specificati, dopo il nome della tabella e prima dell'elenco dei campi:
Ad esempio, supponiamo che il file datiaerei2.txt contenga queste informazioni

produttore,modello,data immatricolazione,numposti
xyz,"columbia shuttle",1999-6-4,5
boeing,B600,1920-2-23
                                                                                                    
È possibile importare questi dati usando il comando:

LOAD DATA LOCAL INFILE 'datiaerei2.txt' INTO TABLE aerei FIELDS TERMINATED BY ',' ENCLOSED BY '"' IGNORE 1 LINES (produttore,modello,dataimm,numposti);

Notare che la parola FIELDS non va ripetuta in FIELDS ENCLOSED BY poiché è già presente in FIELDS TERMINATED BY.

Il risultato finale dovrebbe essere qualcosa del tipo:
+----+------------+------------------+------------+----------+---------+
| id | produttore | modello          | dataimm    | numposti | charter |
+----+------------+------------------+------------+----------+---------+
|  1 | boeing     | 747              | 2000-10-10 |      350 | n       |
|  2 | MDD        | Super80          | NULL       |     NULL | n       |
|  3 | boeing     | 747m             | 2000-01-01 |      200 | n       |
|  4 | boeing     | 747m             | 2000-01-01 |      200 | n       |
|  5 | airbus     | b200             | NULL       |     NULL | n       |
|  6 | xyz        | concorde         | 1980-07-03 |      110 | n       |
|  7 | xyz        | columbia shuttle | 1999-06-04 |        5 | n       |
|  8 | boeing     | B600             | 1920-02-23 |     NULL | n       |
+----+------------+------------------+------------+----------+---------+

Un file come datiaerei2.txt si dice essere in formato CSV (Comma Separated Values). In realtà, si usa il nome di formato CSV anche per un file come datiaerei.txt, nel quale i dati non sono separati da virgole ma da tabulazioni. In generale con formati CSV si intende un qualunque formato tabellare in cui ogni riga contiene una istanza, e gli attributi delle istanze sono separate da qualche carattere separatore (che può essere virgola, tabulazione, spazio, punto e virgola o altro).

Esempio: importazione dati da OpenOffice

Il metodo visto sopra può anche essere utilizzato per importare dati da altri programmi, ad esempio da fogli elettronici o da altri DBMS. Supponiamo di avere una tabella OpenOffice contenente i seguenti dati:

OpenOffice Calc screenshot

Sono possibili due strade per importare questi dati in MySQL

Esportazione di un file CSV

Veniamo ora al problema opposto: vogliamo spostare i dati presenti in una tabella in un foglio di calcolo, o in un altro software che non intepreta il linguaggio SQL ma accetta file in formato CSV. Come fare a generare il tipo di file richiesto? Utilizziamo di nuovo l'operatore < per la redirezione dell'input.

Supponiamo di voler esportare in formato CSV il contenuto della tabella aerei. Prepariamo uno script SQL contenente il comando SELECT * FROM AEREI; . Supponiamo che questo file si chiami comando.sql. Adesso dalla shell di Linux diamo il seguente comando (con l'aggiunta degli opportuni parametri di connessione):

mysql gamato < comando.sql

Il programma monitor di MySQL si collega allo schema gamato, esegue il comando SELECT * FROM aerei e visualizza il seguente output sullo schermo, ritornando immediatamente alla shell di Linux:

id	produttore	modello	dataimm	numposti	commento
1	boeing	747	2000-10-10	350	
2	MDD	Super80	NULL	NULL	prova
3	boeing	747m	2000-01-01	200	NULL
4	boeing	747m	2000-01-01	200	NULL
5	airbus	b200	NULL	NULL	NULL
6	xyz	concorde	1980-07-03	110	NULL
7	xyz	columbia shuttle	1999-06-04	5	NULL
8	boeing	B600	1920-02-23	NULL	NULL
9	cessna	b71	1920-02-12	2	NULL
10	cessna	b72	1930-02-02	4	NULL

Possiamo combinare la redirezione dell'input con quella dell'output e inviare il risultato ad un file, da utilizzare poi in OpenOffice, MySQL o in qualunque altro programma che legga i file CSV:

mysql gamato < comando.sql > out.csv

Scrivere un file di testo con il comando SQL da eseguire e poi invocare il programma mysql può essere un po' farraginoso. Fortunatamente si può fare tutto con la sola invocazione di mysql utilizzando l'opzione aggiuntiva -e. Questa consente di eseguire un comando SQL, specificato tra virgolette dopo -e, in maniera non interattiva. Ad esempio:

mysql gamato -e "SELECT * FROM aerei" > out.csv

ha esattamente lo stesso effetto del comando mysql gamato < comando.sql > out.csv visto precedentemente.

Se invece l'output di mysql con l'opzione -e non viene rediretto ma viene inviato normalmente sullo schermo, allora avremo questo risulato:

+----+------------+------------------+------------+----------+----------+
| id | produttore | modello          | dataimm    | numposti | commento |
+----+------------+------------------+------------+----------+----------+
|  1 | boeing     | 747              | 2000-10-10 |      350 |          | 
|  2 | MDD        | Super80          | NULL       |     NULL | prova    | 
|  3 | boeing     | 747m             | 2000-01-01 |      200 | NULL     | 
|  4 | boeing     | 747m             | 2000-01-01 |      200 | NULL     | 
|  5 | airbus     | b200             | NULL       |     NULL | NULL     | 
|  6 | xyz        | concorde         | 1980-07-03 |      110 | NULL     | 
|  7 | xyz        | columbia shuttle | 1999-06-04 |        5 | NULL     | 
|  8 | boeing     | B600             | 1920-02-23 |     NULL | NULL     | 
|  9 | cessna     | b71              | 1920-02-12 |        2 | NULL     | 
| 10 | cessna     | b72              | 1930-02-02 |        4 | NULL     | 
+----+------------+------------------+------------+----------+----------+

Le linee orizzontali e verticali aiutano un essere umano nella lettura del file ma non sono interpretate dai programmi che leggono il formato CSV. Questo non è comunque un problema perché, se l'output viene rediretto su un file come è stato fatto prima, allora cambia e diventa un file CSV standard.

Esportazione diretta dei file dati

Tutta quello che è scritto in questa sezione non è applicabile in aula informatizzata, perché la macchina dove risiede il server MySQL non è accessibile direttamente.

Un altra possibilità per esportare i propri dati è copiare manualmente i file che contengono gli schemi e le tabelle presenti nel server. Il server MySQL conserva tutti i propri dati nella directory /var/lib/mysql. Qui sono presenti varie directory, una per ogni schema creato nel sistema. Dentro ogni directory, e per ogni tabella, vi sono tre file: <tabella>.frm, <tabella>.MYD e <tabella>.MYI.

Se si copiano questi file su di un altro server, quest'ultimo vedrà il nuovo schema esattamente nello stato in cui era nel server originale. Tuttavia, questo metodo ha alcuni svantaggi:
  1. nella maggior parte dei casi, solo il super-utente ha il diritto di accedere alla directory /var/lib/mysql/<schema>.
  2. prima di copiare i dati dal server origine è necessario che il processo server di MySQL venga disattivato, altrimenti si rischia di copiare dei file corrotti. Analogamente, prima di copiare i file nel server destinazione, è bene che anche qui il processo server venga disattivato.
Normalmente, spostando file binari da un sistema ad un altro, c'è anche il rischio che, cambiando processore o sistema operativo, il file non sia più leggibile. Questo non succede di solito con MySQL perchè il formato di memorizzazione dei dati è standardizzato ed è esattamente uguale per tutte le macchine su cui esso gira.

Esercizi e Soluzioni

Esercizio 1

Si vuole affiancare alla tabella aerei una nuova tabella che contiene informazioni sui posti a sedere disponibili in ogni aereo. La tabella è composta dai seguenti campi:
I dati per alcuni aerei sono stati raccolti nel file datiposti.txt di cui riportiamo alcune linee:

1 1 first
1 2 first
...
1 121 turistica
1 122 turistica
1 123 turistica
...

Creare una nuova tabella "posti" con i campi opportuni e inserire i valori generati dal programma di sopra. Qual è una possibile chiave primaria per la tabella posti?

Per controllare se i dati sono inseriti si può usare il seguente comando:

SELECT * FROM posti LIMIT <n1>,<n2>

che visualizza solo i primi n2 elementi della tabella posti a partire dall'elemento n1-esimo.

Lezione Precedente Elenco Lezioni Lezione Successiva

Valid HTML 4.01 Transitional Valid CSS!