@Murloc: Nej, det är inte säkert. Den säkerhetsmässiga fördelen med prepared statements kommer utav att frågans struktur separeras från de värden som ska skickas; när strukturen har tolkats kan värdena inte påverka denna och även om värdena i sig kan vara något än vad du har tänkt dig så kan de inte direkt påverka vad som ska utföras.
I ditt exempel är det viktigt att separera vad som händer i PHP från vad som händer i databasen. Din sträng kommer expanderas till att inkludera vad nu $var
innehåller innan databasen kan bedöma den alls, och den har ingen möjlighet att veta om detta påverkar vad du avsett att frågan ska göra eller ej. Ponera att du vill förbereda en fråga likt "DELETE FROM yourTable WHERE id = ".$var.";"
men att $var = "1 OR id > 0"
, din fråga kommer alltså expanderas till DELETE FROM yourTable WHERE id = 1 OR id > 0;
och blir det du säger till databasen att förbereda; det är uppenbarligen inte vad du hade tänkt dig men det finns inget databasen kan göra för att förhindra det.
Lösningen är att använda platshållare för att berätta för databasen var du vill använda egna värden, inte vad dessa ska vara: DELETE FROM yourTable WHERE id = ?;
Nu kan databasen förstå frågans struktur oberoende av värdet, och inte göra något annat än radera rader med id motsvarande värdet.
#
# Exempel med PDO
#
$stmt = $conn->prepare("DELETE FROM yourTable WHERE id = :id;");
$stmt->bindParam(":id", $id, \PDO::PARAM_INT);
$stmt->execute();
#
# Exempel med Mysqli
#
$stmt = $conn->prepare("DELETE FROM yourTable WHERE id = ?;");
$stmt->bind_param("i", $id);
$stmt->execute();
Det är dock viktigt att ha i åtanke att detta endast hjälper till med att skydda mot så kallad SQL injection; det är fortfarande ditt ansvar att kontrollera att värdet är giltigt innan du skickar det till databasen. Det involverar bland annat att kontrollera om det är av rätt typ, inom ett rimligt intervall, av rätt teckenkodning (särskilt om du använder Unicode), att du hanterar fel korrekt om frågan skulle misslyckas, att användaren ö.h.t. har rätt att utföra operationen på det objektet etc. Prepared statements ersätter aldrig korrekt validering av användarinput, de gör det bara lite svårare att göra fel.