I sistemi di gestione dei database (DBMS o Database Ma­na­ge­ment System) operanti con il lin­guag­gio di in­ter­ro­ga­zio­ne SQL, godono di grande ap­prez­za­men­to, ma da sempre sono anche soggetti a ma­ni­po­la­zio­ni al momento dell’im­mis­sio­ne dei dati. I record dati non suf­fi­cien­te­men­te protetti e con­te­nen­ti meta caratteri come le vir­go­let­te o il punto e virgola, sono una preda facile per i ma­lin­ten­zio­na­ti. Una possibile risposta a questo problema è l’utilizzo di Prepared Statement, ossia delle di­chia­ra­zio­ni pre­de­fi­ni­te ai database, dotate di valori che ne sta­bi­li­sco­no la durata.

Ma cosa rende questa tec­no­lo­gia così unica e in che si­tua­zio­ne viene prin­ci­pal­men­te adottata? Uti­liz­zan­do esempi in MySQL vi mostriamo come fun­zio­na­no i Prepared Statement e di come possono essere impiegati nella gestione delle basi di dati.

Che cosa sono i Prepared Statement

I Prepared Statement (let­te­ral­men­te “di­chia­ra­zio­ni preparate”) sono modelli già pronti all’uso per le in­ter­ro­ga­zio­ni nei sistemi di database in SQL, che non con­ten­go­no valori per i singoli parametri. Di­ver­sa­men­te dalle im­mis­sio­ni di dati manuali, in cui i valori vengono assegnati già al momento dell’ese­cu­zio­ne di un comando, i Prepared Statement uti­liz­za­no variabili o me­ta­ca­rat­te­ri che vengono poi so­sti­tui­ti con valori reali all’interno del sistema.

Tutti i più grandi sistemi di database basati su SQL come MySQL, MariaDB, Oracle, il server SQL di Microsoft o Post­gre­SQL sup­por­ta­no i Prepared Statement, per quanto la maggior parte di questi programmi uti­liz­zi­no a questo scopo un pro­to­col­lo binario NoSQL. Alcuni sistemi, tra i quali MySQL, impiegano so­prat­tut­to anche la comune sintassi SQL per l’im­ple­men­ta­zio­ne.

Inoltre, alcuni linguaggi di pro­gram­ma­zio­ne come Java, Perl, Python e PHP sup­por­ta­no i Prepared Statement grazie alle loro librerie standard o esten­sio­ni. Nel caso in cui uti­liz­zia­te quest’ultimo lin­guag­gio di scripting per l’accesso al database, potete scegliere di adoperare l’in­ter­fac­cia orientata agli oggetti PHP Data Objects (PDO) o l’esten­sio­ne PHP MySQLi, così da poter adottare i Prepared Statement.

Perché l’utilizzo dei Prepared Statement in MySQL e negli altri linguaggi è così im­por­tan­te

Il motivo decisivo che porta a lavorare con i Prepared Statement in sistemi di gestione dei database come MySQL è la sicurezza. Il problema in assoluto più grande in merito agli accessi ai database in lin­guag­gio SQL è infatti la facilità con la quale questi possono essere ma­ni­po­la­ti. In questi casi si parla di SQL Injection, ovvero quando vengono aggiunti o mo­di­fi­ca­ti codici in modo tale da riuscire a mettere mano su dati sensibili o a ottenere controllo sull’intero sistema di basi di dati.

I Prepared Statement in PHP, così come anche in altri linguaggi, sono privi di queste falle di sicurezza, poiché i valori concreti vengono assegnati solamente all’interno del sistema.

N.B.

Una con­di­zio­ne ne­ces­sa­ria per garantire gli elevati standard di sicurezza dei Prepared Statement è che nessuna delle com­po­nen­ti di queste di­chia­ra­zio­ni pre­de­fi­ni­te sia generata da fonti esterne.

La pro­te­zio­ne dalle SQL Injection non è però l’unica ragione per l’utilizzo dei Prepared Statement. Infatti, una volta ana­liz­za­ti e compilati, questi possono essere riu­ti­liz­za­ti nei propri sistemi di database tutte le volte che si vuole (cambiando di volta in volta i valori). Così facendo, i Prepared Statement consumano un quan­ti­ta­ti­vo si­gni­fi­ca­ti­vo di risorse in meno e sono più rapidi rispetto alle in­ter­ro­ga­zio­ni manuali dei database, qualora si tratti di attività in SQL che devono essere ripetute.

Il fun­zio­na­men­to dei Prepared Statement spiegato nel dettaglio

Se non si con­si­de­ra­no la sintassi del lin­guag­gio di scripting alla base e le ca­rat­te­ri­sti­che del sistema di database in questione, l’in­te­gra­zio­ne e l’utilizzo dei Prepared Statement si svolge ge­ne­ral­men­te nelle fasi qui in seguito il­lu­stra­te:

Fase 1: pre­pa­ra­zio­ne del Prepared Statement

Il primo passaggio con­si­ste­ste nella creazione di un template. In PHP a questo scopo viene uti­liz­za­ta la funzione prepare(). Al posto di digitare valori concreti per i parametri rilevanti vengono inseriti i me­ta­ca­rat­te­ri pre­ce­den­te­men­te men­zio­na­ti, definiti anche variabili Bind. Negli esempi suc­ces­si­vi queste sono con­trad­di­stin­te da un “?”:

INSERT INTO Prodotto (Nome, Prezzo) VALUES (?, ?);

I Prepared Statement completi saranno poi inoltrati al sistema di gestione dei database relativo.

Fase 2: ela­bo­ra­zio­ne del modello di di­chia­ra­zio­ne at­tra­ver­so il DBMS

Il modello di di­chia­ra­zio­ne viene dunque par­si­fi­ca­to, ovvero ana­liz­za­to, così da poter essere poi compilato, tra­sfor­man­do­lo in pratica una di­chia­ra­zio­ne ese­gui­bi­le. Questo pro­ce­di­men­to serve a ot­ti­miz­za­re il Prepared Statement.

Fase 3: ese­cu­zio­ne del Prepared Statement

In un secondo momento il modello elaborato può essere eseguito nel sistema di database tutte le volte che lo si desidera. L’unico requisito è l’input adeguato at­tra­ver­so l’ap­pli­ca­zio­ne associata, ossia una fonte dati che fornisca i valori cor­ri­spon­den­ti per il campo del me­ta­ca­rat­te­re. Facendo ri­fe­ri­men­to al codice di esempio sopra riportato (Fase 1), potrebbe trattarsi di un valore quale “Libro” (Nome) e “10” (Prezzo), o anche “Computer” e “1000”.

Tutorial: come uti­liz­za­re i Prepared Statement in MySQL con MySQLi

Dopo aver descritto il fun­zio­na­men­to dei Prepared Statement in generale, il qui presente tutorial con tanto di esempi concreti dovrebbe servire a chiarirvi l’utilizzo di queste pratiche direttiva. Gli esempi fanno ri­fe­ri­men­to a:

  • MySQL come sistema di gestione dei database
  • PHP come lin­guag­gio per i Prepared Statement

Le versioni attuali di MySQL sup­por­ta­no l’impiego lato server dei Prepared Statement basandosi su di un pro­to­col­lo binario con­te­nen­te i comandi SQL che ag­gior­na­no i dati e che inoltre pro­to­col­la­no tutti gli ag­gior­na­men­ti dall’ultima messa in sicurezza dei dati. Da in­ter­fac­cia d’accesso uti­liz­zia­mo l’esten­sio­ne PHP MySQLi per questo tutorial, che allo stesso modo supporta i Prepared Statement grazie al pro­to­col­lo binario.

N.B.

Una buona al­ter­na­ti­va a MySQLi come API (Ap­pli­ca­tion Pro­gram­ming Interface) per i Prepared Statement è l’in­ter­fac­cia orientata agli oggetti PDO (PHP Data Objects). Questa variante vale ge­ne­ral­men­te come soluzione adatta ai prin­ci­pian­ti.

PREPARE, EXECUTE e DEAL­LO­CA­TE PREPARE: i tre comandi ele­men­ta­ri di SQL per l’utilizzo dei Prepared Statement

Sono tre i comandi SQL a giocare un ruolo decisivo nell’utilizzo dei Prepared Statement nei database MySQL:

Il comando „PREPARE“ è ne­ces­sa­rio durante la fase di pre­pa­ra­zio­ne di un Prepared Statement e per assegnare a questo un nome univoco tramite il quale ritrovare lo statement anche in un secondo momento.

PREPARE stmt_name FROM preparable_stmt

Per l’ese­cu­zio­ne di una direttiva SQL pre­de­fi­ni­ta si ha invece bisogno del comando „EXECUTE“. Per ricorrere al relativo Prepared Statement dovete uti­liz­za­re il nome as­se­gna­to­gli, generato con il comando “PREPARE”. La frequenza con la quale eseguite un Prepared Statement dipende da voi: potete definire diverse variabili o conferire il­li­mi­ta­ta­men­te nuovi valori alle variabili uti­liz­za­te.

EXECITE stmt_name
[USING @var_name [, @var_name] …]

Per riat­ti­va­re un Prepared Statement in PHP c’è il comando „DEAL­LO­CA­TE PREPARE“. Poiché, al­tri­men­ti, gli Statement vengono terminati au­to­ma­ti­ca­men­te allo scadere di una sessione. La riat­ti­va­zio­ne è perciò rilevante, in quanto sennò viene ra­pi­da­men­te raggiunto il limite massimo pre­im­po­sta­to dalla variabile di sistema max_prepared_stmt_count, che im­pe­di­reb­be al­tri­men­ti di creare nuovi Prepared Statement.

{DEALLOCATE | DROP} PREPARE stmt_name

Uti­liz­za­re le di­chia­ra­zio­ni SQL come Prepared Statement MySQL

Pra­ti­ca­men­te tutti gli statement SQL sup­por­ta­ti da MySQL possono essere preparati ed eseguiti come Prepared Statement. L'unica eccezione è data delle direttive di diagnosi, escluse dai Prepared Statement per il man­te­ni­men­to degli standard SQL. Pre­ci­sa­men­te si tratta delle seguenti:

  • SHO WARNINGS
  • SHOW COUNT(*) WARNINGS
  • SHOW ERRORS
  • SHOW COUNT(*) ERRORS

Inoltre, non potete generale alcun modello di in­ter­ro­ga­zio­ne SQL che faccia ri­fe­ri­men­to alle variabili di sistema warning_count ed error_count.

Possono altresì essere uti­liz­za­ti i seguenti statement:

ALTER TABLE
ALTER USER
ANALYZE TABLE
CACHE INDEX
CALL
CHANGE MASTER
CHECKSUM {TABLE | TABLES}
COMMIT
{CREATE | DROP} INDEX
{CREATE | RENAME | DROP} DATABASE
{CREATE | DROP} TABLE
{CREATE | RENAME | DROP} USER
{CREATE | DROP} VIEW
DELETE
DO
FLUSH {TABLE | TABLES | TABLES WITH READ LOCK | HOSTS | PRIVILEGES
| LOGS | STATUS | MASTER | SLAVE | USER_RESOURCES}
GRANT
INSERT
INSTALL PLUGIN
KILL
LOAD INDEX INTO CACHE
OPTIMIZE TABLE
RENAME TABLE
REPAIR TABLE
REPLACE
RESET {MASTER | SLAVE}
REVOKE
SELECT
SET
SHOW {WARNINGS | ERRORS}
SHOW BINLOG EVENTS
SHOW CREATE {PROCEDURE | FUNCTION | EVENT | TABLE | VIEW}
SHOW {MASTER | BINARY} LOGS
SHOW {MASTER | SLAVE} STATUS
SLAVE {START | STOP}
TRUNCATE TABLE
UNINSTALL PLUGIN
UPDATE

Pe­cu­lia­ri­tà sin­tat­ti­che della sintassi SQL dei Prepared Statement in PHP

In confronto alla sintassi SQL standard, quella relativa ai Prepared Statement presenta un paio di par­ti­co­la­ri­tà, alle quali bisogna però prestare at­ten­zio­ne. Prima di tutto si segnala l’utilizzo di me­ta­ca­rat­te­ri per i valori parametro, che rendono le direttive pre­de­fi­ni­te così in­te­res­san­ti per l’accesso ai sistemi di gestione dei database. A partire da MySQL 8.0 è possibile uti­liz­za­re questi me­ta­ca­rat­te­ri per i parametri “OUT” e “INOUT”, ad esempio, negli statement “PREPARE” ed “EXECUTE”, mentre per il parametro “IN” questi sono in­di­pen­den­ti dalla versione del sistema di database. Ulteriori ca­rat­te­ri­sti­che spe­ci­fi­che della sintassi dei Prepared Statement sono le seguenti:

  • La sintassi SQL per i Prepared Statement in PHP non può essere doppiata. Quello che si intende qui è che una direttiva alla quale sia stata assegnata la funzione di “PREPARE”, non può con­tem­po­ra­nea­men­te essere un “PREPARE”, “EXECUTE” o “DEAL­LO­CA­TE PREPARE” statement.
  • I Prepared Statement possono essere uti­liz­za­ti anche nelle procedure ar­chi­via­te (funzione di richiamo di ese­cu­zio­ni complete delle di­chia­ra­zio­ni).
  • Non è possibile eseguire più di­chia­ra­zio­ni o direttive (Multi Statement) all’interno di uno stesso statement, ossia di una stringa di caratteri, se­pa­ran­do­lo per mezzo di un punto e virgola.

Prepared Statement in MySQL: esempio

In questo capitolo vi mostriamo che aspetto ha esat­ta­men­te l’im­mis­sio­ne di un Prepared Statement in PHP in MySQLi:

<?php
$servername = "localhost";
$username = "username";
$password = "password";
$dbname = "myDB";
// Connessione
$conn = new mysqli($servername, $username, $password, $dbname);
// Verifica della connessione
if ($conn->connect_error) {
    die("Connection failed: " . $conn->connect_error);
}
// Preparazione del Prepared Statements
$stmt = $conn->prepare("INSERT INTO Miocliente (Nome, Cognome, Email) VALUES (?, ?, ?)");
$stmt->bind_param("sss", $nome, $cognome, $email);
// Impostare i parametri e l’esecuzione
$Vorname = "Virgilio";
$Nachname = "Rossi";
$Mail = "m.rossi@esempio.it";
$stmt->execute();
$Vorname = "Rita";
$Nachname = "Bianchi";
$Mail = "r.bianchi@esempio.it";
$stmt->execute();
$Vorname = "Niccolò";
$Nachname = "Verdi";
$Mail = "n.verdi@esempio.it";
$stmt->execute();
echo "Nuovi records creati con successo";
$stmt->close();
$conn->close();
?>

Questo codice di scripting in PHP sta­bi­li­sce per prima cosa la con­nes­sio­ne al database in MySQL con ($conn), all’interno del quale voi dovete indicare i relativi dati del server, quali il nome host, il nome utente, la password e il nome del database.

Con la riga “INSERT INTO Mio­clien­te (Nome, Cognome, Email) VALUES (?, ?, ?)” inizia la parte relativa al Prepared Statement: il database cliente “Mio­clien­te" riceve l’input (INSERT INTO), ri­spet­ti­va­men­te per le colonne “Nome”, “Cognome” e “Email”. Per i valori (VALUES) vengono uti­liz­za­ti ini­zial­men­te dei me­ta­ca­rat­te­ri, con­tras­se­gna­ti dal simbolo di domanda (?).

Infine, i parametri devono essere collegati tra loro (bind_param). Per fare ciò il database necessita in­for­ma­zio­ni riguardo al tipo di dati. L'ar­go­men­to “sss” mostra ad esempio che, per tutti e tre i parametri, si tratta di una stringa di caratteri. Le al­ter­na­ti­ve sarebbero le seguenti:

  • i: INTEGER (valore intero)
  • d: DOUBLE (valori numerici ap­pros­si­ma­ti)
  • b: BLOB (oggetto binario di grandi di­men­sio­ni, dall’inglese “Binary Large OBject”)
aN5KqxK1slc.jpg Per visualizzare questo video, sono necessari i cookie di terze parti. Puoi accedere e modificare le impostazioni dei cookie qui.
Vai al menu prin­ci­pa­le