Crea sito

Pillole di PHP e MySQL – Query tramite Begin, Commit e Rollback con gestione dei Warning

| 25 aprile 2012 | 0 Comments

PHP LogoOggi mi è stato fatto notare da una semplice query Update che sarebbe stato interessante un articolo sulla gestione del begin, commit e rollback in MySQL. Qui sotto mostrerò come effettuare query MySQL tramite le funzioni standard PHP. In aggiunta, dato che il modulo di connessione standard al DB fornisce solo la gestione degli errori, ho interfacciato anche una gestione dei warning che, al pari degli errori, ferma l’esecuzione delle query in corso.

L’utilizzo della transaction permette di eseguire una serie di query come fossero state realmente eseguite ed, in caso di errori, di ritornare indietro riportando tutto alla situazione iniziale. Tramite il comando begin è come se avviassimo una sorta di registratore in registrazione. Lanciato si eseguono le varie query in successione cercando di prendere eventuali errori (o warning) che potrebbero inficiare il risultato finale. Una volta effettuate tutte le query si può decidere, se tutto è andato come doveva, di rendere i cambiamenti effettivi con il comando commit, oppure di ritarnare alla situazione precedente con il rollback.

L’utilità di questo sistema sta nel fatto che qualora vi sia un errore, sia in esecuzione delle query, sia nel collegamento stesso col server, le query non verranno rese esecutive fino al comando commit finale. L’unico punto contro di questo sistema è che, in caso di rollback, gli indici autoincrementali creati nelle tabelle utilizzate aumenteranno senza tornare all’indice iniziale. Niente che possa preoccupare comunque, ma è meglio saperlo da principio.

Prima di tutto create un database di nome test. Dopo averlo creato, entrateci ed eseguite le seguenti query per la creazione delle tabelle di esempio con i dati inseriti:

--
-- Struttura della tabella `controllo`
--

CREATE TABLE IF NOT EXISTS `controllo` (
`codice_isbn` varchar(20) NOT NULL,
`quantita` int(11) NOT NULL,
`data_controllo` date NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=latin1;

--
-- Dump dei dati per la tabella `controllo`
--

INSERT INTO `controllo` (`codice_isbn`, `quantita`, `data_controllo`) VALUES
('978-88-429-1660-4', 7, '2012-04-23'),
('978-88-429-1672-7', 12, '2012-04-21'),
('978-88-429-1671-0', 13, '2012-04-24');

-- --------------------------------------------------------

--
-- Struttura della tabella `magazzino`
--

CREATE TABLE IF NOT EXISTS `magazzino` (
`id_magazzino` int(11) NOT NULL AUTO_INCREMENT,
`codice_isbn` varchar(20) NOT NULL,
`titolo` text NOT NULL,
`quantita` int(11) NOT NULL,
`ultimo_controllo` date NOT NULL,
PRIMARY KEY (`id_magazzino`)
) ENGINE=InnoDB  DEFAULT CHARSET=latin1 AUTO_INCREMENT=5 ;

--
-- Dump dei dati per la tabella `magazzino`
--

INSERT INTO `magazzino` (`id_magazzino`, `codice_isbn`, `titolo`, `quantita`, `ultimo_controllo`) VALUES
(1, '978-88-429-1606-2', 'La Biblioteca dei Morti', 10, '2011-05-14'),
(2, '978-88-429-1660-4', 'Il Libro delle Anime', 13, '2011-07-22'),
(3, '978-88-429-1671-0', 'La Mappa del Destino', 5, '2011-12-05'),
(4, '978-88-429-1672-7', 'Il Marchio del Diavolo', 23, '2011-03-12');

Ecco invece il sorgente del codice php per l’esecuzione delle query MySQL di INSERT ed UPDATE tramite begin, commit e rollback:

<?php

// PARAMETRI DI CONNESSIONE
$db_host = 'localhost';
$db_user = 'root';
$db_pwd = '';

$database = 'test';

// TENTA CONNESSIONE AL SERVER MYSQL
$dbconn = mysql_connect($db_host, $db_user, $db_pwd);
if (!$dbconn) {
    die("<font color='red'>Impossibile connettersi al server.</font>");
} else {
    echo "<font color='green'>Connessione al server effettuata</font><br />";
}

// TENTA LA CONNESSIONE AL DATABASE
if (!mysql_select_db($database)) {
    die("<font color='red'>Impossibile connettersi al database</font>");
} else {
    echo "<font color='green'>Connessione al database effettuata</font><br />";
}

// IMPOSTA OPERAZIONE STANDARD DI INVIO
$check = Array();

// TENTA LA QUERY DI INIZIO
if (!mysql_query("begin", $dbconn)) {
    die("<font color='red'>Impossibile eseguire la query di avvio</font>");
} else {
    echo "<font color='green'>Query di avvio eseguita con successo</font><br />";
}

// TENTA L'ESECUZIONE DELLA QUERY
$query = "INSERT INTO magazzino (titolo,codice_isbn,quantita,ultimo_controllo) VALUES ('Angeli e Demoni','88-04-53167-3',9,'2010-02-17')";
if (!mysql_query($query)) {
    $check[]['error'] = mysql_error($dbconn);
} else {
    $warning = mysql_warning($dbconn);
    if (count($warning) > 0) {
        $check[]['warning'] = $warning;
    } else {
        $check[] = 'ok';
    }
}

// TENTA L'ESECUZIONE DELLA QUERY
$query = "UPDATE magazzino M, controllo C SET M.quantita = C.quantita, M.ultimo_controllo = C.data_controllo WHERE M.codice_isbn = C.codice_isbn";
if (!mysql_query($query)) {
    $check[]['error'] = mysql_error($dbconn);
} else {
    $warning = mysql_warning($dbconn);
    if (count($warning) > 0) {
        $check[]['warning'] = $warning;
    } else {
        $check[] = 'ok';
    }
}

// DECOMMENTARE IL PRINT_R PER DEBUGGARE
//print_r($check);

// CAPISCE SE ROLLBACK O NO
if (!mysql_check($check)) {
    mysql_query("rollback", $dbconn);
    echo "<font color='red'>Errore nell'operazione: ripristinata la situazione precedente</font><br />";
} else {
    if (!mysql_query("commit", $dbconn)) {
        echo "<font color='red'>Errore nell'operazione: ripristinata la situazione precedente</font><br />";
    } else {
        echo "<font color='green'>Operazioni effettuate correttamente<br />";
    }
}

// TENTA LA CONNESSIONE AL DATABASE
if (!mysql_close($dbconn)) {
    die("<font color='red'>Impossibile disconnettersi dal server</font>");
} else {
    echo "<font color='green'>Disconnessione dal server effettuata</font><br />";
}

function mysql_check($check) {
    $return = true;
    foreach ($check as $checked) {
        if (is_array($checked)) {
            if ($return === true) {
                $return = false;
            }
        }
    }
    return $return;
}

function mysql_warning($dbconn) {
    $messages = Array();
    $warningCountResult = mysql_query("SELECT @@warning_count", $dbconn);
    if ($warningCountResult) {
        $warningCount = mysql_fetch_row($warningCountResult);
        if ($warningCount[0] > 0) {
            $warningDetailResult = mysql_query("SHOW WARNINGS");
            if ($warningDetailResult) {
                while ($warning = mysql_fetch_assoc($warningDetailResult)) {
                    $messages[] = $warning['Message'];
                }
            }
        }
    }
    return $messages;
}
?>

Nel seguente codice, le due query utilizzate di esempio sono tutte e due senza errori, ma, nel caso in cui siano inseriti errori che generino error o warning di MySQL, il codice richiamerà il rollback. Per vedere l’array di warning ed errori basta semplicemente decommentare la linea contenente il comando print_r.

Buon proseguimento! 😉

ATTENZIONE: prima di fare qualsiasi aggiornamento su un database, fare sempre una copia dei dati. Questo evita spiacevoli conseguenze in caso di malfunzionamenti o query scritte male o con errori di battitura. Fate sempre le prove su un database di test e, se funziona, lo riportate su quello di lavoro.

VN:F [1.9.22_1171]
Rating: 9.5/10 (4 votes cast)
VN:F [1.9.22_1171]
Rating: +1 (from 1 vote)
Pillole di PHP e MySQL - Query tramite Begin, Commit e Rollback con gestione dei Warning, 9.5 out of 10 based on 4 ratings

Tags: , , , , , ,

Category: Informatica

About the Author ()

Leave a Reply