Come scrivere una query select mysql efficiente e sicura

Possiamo migliorare le nostre query SELECT in MySQL in modo sicuro?

Sì, gli script possono essere ottimizzati in diversi modi per renderli più robusti, sicuri e leggibili.


Ecco alcune raccomandazioni

-

E' possibile quindi migliorare query SELECT scritta in questo modo?

<?php $stmt = $conn->prepare("SELECT * FROM user WHERE token = ?");
$stmt->bind_param("s", $token); 
$stmt->execute();
$result = $stmt->get_result();
$nrows = $result->num_rows;
if($nrows > 0){
while($row = $result->fetch_assoc()){   
    ///row    
   }
}  
$stmt->close(); 
$conn->close(); 
?>

 

 

Possiamo ottimizzare in vari modi ecco i miglioramenti:

  1. Gestione degli errori: Aggiungi il controllo degli errori per sapere se la query o la preparazione della query falliscono.
  2. Usare `store_result()`: Se vuoi solo contare il numero di righe e non hai bisogno dei dati completi subito, puoi usare `$stmt->store_result()` per evitare di caricare tutti i dati immediatamente.
  3. Usare `fetch()` in combinazione con `bind_result()`: È leggermente più efficiente di `get_result()` per ottenere i dati. Anche se `get_result()` è semplice, l'uso di `bind_result()` e `fetch()` evita di convertire i dati in array associativi quando non è necessario.
  4. Chiudere la connessione e lo statement in modo sicuro: Anche se lo stai già facendo, è sempre una buona pratica chiudere gli statement e le connessioni dopo l'uso.

Ecco una versione del codice migliorato: 

<?php

// Preparazione della query con controllo degli errori
$stmt = $conn->prepare("SELECT * FROM user WHERE token = ?");

if ($stmt === false) {
    die('Errore nella preparazione della query: ' . $conn->error);
}

// Bind del parametro
$stmt->bind_param("s", $token);

// Esecuzione della query con controllo degli errori
if (!$stmt->execute()) {
    die('Errore nell\'esecuzione della query: ' . $stmt->error);
}

// Ottenimento dei risultati
$result = $stmt->get_result();

// Controllo se ci sono righe
if ($result && $result->num_rows > 0) {
    // Iterazione sui risultati
    while ($row = $result->fetch_assoc()) {
        // Utilizzo dei dati della riga (ad esempio, puoi usare $row['nome_colonna'])
        // echo $row['nome'];
    }
} else {
    echo "Nessun risultato trovato.";
}

// Chiusura dello statement
$stmt->close();

// Chiusura della connessione
$conn->close();

Cosa abbiamo migliorato:

1. Gestione degli errori: Aggiungiamo un controllo per assicurarci che la preparazione e l'esecuzione della query non falliscano. Questo ti fornisce un messaggio di errore utile in caso di problemi, ad esempio con query o parametri non corretti.
   
2. Controllo del risultato: Verifichiamo se `$result` è valido prima di tentare di accedere a `num_rows`. Questo evita problemi nel caso in cui la query non restituisca risultati o il risultato sia `false`.

3. Usare `fetch_assoc()` direttamente in un ciclo: Anche se il tuo approccio funziona bene, verificare l'esistenza dei dati (`num_rows > 0`) prima di ciclare può essere evitato. Se non ci sono righe, il ciclo `while` non verrà eseguito comunque, quindi il controllo `num_rows` può essere rimosso per semplificare.


Questa che vediamo qui sotto è un'altra versione con un'ulteriore semplificazione: 


<?php

// Preparazione della query
$stmt = $conn->prepare("SELECT * FROM user WHERE token = ?");

if ($stmt === false) {
    die('Errore nella preparazione della query: ' . $conn->error);
}

// Bind del parametro
$stmt->bind_param("s", $token);

// Esecuzione della query
if (!$stmt->execute()) {
    die('Errore nell\'esecuzione della query: ' . $stmt->error);
}

// Ottenimento del risultato
$result = $stmt->get_result();

// Iterazione sui risultati (il ciclo non verrà eseguito se non ci sono righe)
while ($row = $result->fetch_assoc()) {
    // Processa i dati della riga
    // echo $row['nome'];
}

// Chiusura dello statement
$stmt->close();

// Chiusura della connessione
$conn->close();
 


 Se vuoi ottimizzare ulteriormente l'uso della memoria, puoi utilizzare `bind_result()` anziché `get_result()` e `fetch_assoc()`: 


<?php

// Preparazione della query
$stmt = $conn->prepare("SELECT id, username, email FROM user WHERE token = ?");

if ($stmt === false) {
    die('Errore nella preparazione della query: ' . $conn->error);
}

// Bind del parametro
$stmt->bind_param("s", $token);

// Esecuzione della query
if (!$stmt->execute()) {
    die('Errore nell\'esecuzione della query: ' . $stmt->error);
}

// Memorizza i risultati
$stmt->store_result();

// Verifica se ci sono righe
if ($stmt->num_rows > 0) {
    // Associa le variabili ai risultati
    $stmt->bind_result($id, $username, $email);

    // Iterazione sui risultati
    while ($stmt->fetch()) {
        // Ora puoi usare $id, $username e $email
        echo "ID: $id, Username: $username, Email: $email\n";
    }
} else {
    echo "Nessun utente trovato.";
}

// Chiusura dello statement
$stmt->close();

// Chiusura della connessione
$conn->close();

Quali sono i vantaggi di `bind_result():

- Efficienza: Non crea array associativi per ogni riga, quindi è più efficiente in termini di memoria.
- Controllo sui tipi di dati: Puoi specificare esattamente le variabili da associare e avere più controllo sui risultati.

In sintesi, queste modifiche migliorano la robustezza del codice, la gestione degli errori e l'efficienza.


 


Lascia un commento