Importare un file CSV all’interno del database

Spesso risulta necessario importare grosse moli di dati direttamente nel database passando da una form.

Nel caso di grosse mole di dati, l’utilizzo di oggetti rischia di sovraccaricare il sistema pertanto l’utilizzo delle funzioni native del DBMS (nel caso di MySQL) spesso si traduce in una ottima soluzione.

Supponiamo quindi di aver caricato tramite form un file CVS nel sistema ecco come dovrà essere il metodo da inserire nella actions.class.php per gestire l’importazione.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
public function executeImport()
{
  if ($this->getRequest()->hasFiles())
  {
    $filename = date('Ymd').'-'.$tipo.'-filename.csv';
    $this->getRequest()->moveFile('file_import', sfConfig::get('sf_upload_dir').'/'.$filename);
 
    // elimino tutti i vecchi dati
    TabellaPeer::doDeleteAll();	
 
    // inizializzo la gestione del db			
    $databaseManager = new sfDatabaseManager();
    $databaseManager->initialize();		
    $connection = Propel::getConnection();
 
    // creo la query di import del file usando la sintassi di LOAD FILE di MySQL
    $query = 'LOAD DATA INFILE "'.sfConfig::get('sf_upload_dir').'/'.$filename.'" ';
    $query.= ' INTO TABLE '.TabellaPeer::TABLE_NAME .' FIELDS TERMINATED BY "|" ENCLOSED BY "" LINES TERMINATED BY "\n" ';
    $query.= '(campo1,campo2,campo3) SET campo4 = "costante"';
 
    $statement = $connection->prepareStatement($query);
    $resultset = $statement->executeQuery();
  }
}

Analizziamo passo passo cosa facciamo nel metodo

if ($this->getRequest()->hasFiles())

Innanzitutto verifichiamo che il file sia stato caricato correttamente, in realtà potremmo inserire ulteriori controlli come ad esempio che i META-TYPE corrispondano a quelli di un file CSV, ma per ora soprassediamo.

$filename = date('Ymd').'-'.$tipo.'-filename.csv';
$this->getRequest()->moveFile('file_import', sfConfig::get('sf_upload_dir').'/'.$filename);

Generiamo il nome del file e lo spostiamo nella directory di upload impostata nel file di configurazione della nostra applicazione

// elimino tutti i vecchi dati
TabellaPeer::doDeleteAll();

Questo passaggio è opzionale, facendo così vengono cancellati tutti i vecchi dati relativi alla tabella su cui vogliamo lavorare, utile nel caso di aggiornamenti massicci (ad esempio da gestionali), meno utile se importiamo sempre nuovi dati.

$databaseManager = new sfDatabaseManager();
$databaseManager->initialize();		
$connection = Propel::getConnection();

Inizializzamo la connessione al database usando Propel e prepariamo la query.

// creo la query di import del file usando la sintassi di LOAD FILE di MySQL
$query = 'LOAD DATA INFILE "'.sfConfig::get('sf_upload_dir').'/'.$filename.'" ';
$query.= ' INTO TABLE '.TabellaPeer::TABLE_NAME .' FIELDS TERMINATED BY "|" ENCLOSED BY "" LINES TERMINATED BY "\n" ';
$query.= '(campo1,campo2,campo3) SET campo4 = "costante"';

Qui generiamo la query che verrà eseguita su MySQL. Utilizzando il metodo LOAD carichiamo il file creato poco prima successivamente andiamo ad indicare il nome della tabella su cui vogliamo lavorare, il separatore tra un campo e l’altro (ad esempio | ), il carattere all’interno del quale il campo è racchiuso (alcuni file CSV ad esempio usano ' o "), ed il carattere di fine linea (nel nostro caso l’andata a capo).

Infine nell’ultima riga della query andiamo ad indicare a cosa corrispondono i campi del CSV rispetto a quelli della tabella. E’ interessante notare che è possibile anche forzare una variabile nel caso che quest’ultima non sia presente nel file.

$statement = $connection->prepareStatement($query);
$resultset = $statement->executeQuery();

Infine andiamo ad inserire la query nel metodo prepareStatement() che si occupa di tradurla per CREOLE e di eseguirla successivamente.

2 Replies to “Importare un file CSV all’interno del database”

  1. bel tutorial, complimenti!
    ma come fare se volessi creare ogni volta una nuova tabella con il nome dei campi importato della prima riga del csv?

Leave a Reply

Your email address will not be published. Required fields are marked *