MySQL Prepared Statements
Prepared statements separate the SQL from the data. The database parses the SQL once and binds your values safely — no string concatenation, no injection.
Why prepared
| Concat (DON'T) | Prepared (DO) |
|---|---|
"SELECT * FROM users WHERE email = '$email'" | $pdo->prepare('SELECT * FROM users WHERE email = ?')->execute([$email]) |
| Injection-prone. | Driver handles escaping. |
| Parsed each call. | Parsed once, executed many. |
Positional placeholders
PHP
$stmt = $pdo->prepare('SELECT id, name FROM customers WHERE country = ?');
$stmt->execute(['AU']);
print_r($stmt->fetchAll());
Named placeholders
PHP
$stmt = $pdo->prepare(
'SELECT * FROM customers WHERE country = :c AND active = :a'
);
$stmt->execute([':c' => 'AU', ':a' => 1]);
bindValue vs bindParam vs execute(array)
| Method | Notes |
|---|---|
execute([$v1, $v2]) | Shortest; binds everything as string. |
bindValue(1, $v, PDO::PARAM_INT) | Binds a value with explicit type. |
bindParam(1, $v, PDO::PARAM_INT) | Binds a variable by reference — value is read at execute() time. |
When the type matters
For LIMIT / OFFSET placeholders, MySQL needs an integer. With EMULATE_PREPARES = false, you must bind explicitly:
PHP
$stmt = $pdo->prepare('SELECT * FROM customers LIMIT ?');
$stmt->bindValue(1, 20, PDO::PARAM_INT);
$stmt->execute();
What you CAN'T bind
- Table or column names — only values.
ORDER BYdirection — that's part of the SQL grammar.- LIMIT inside an IN list — but you can build the placeholder string dynamically.
For these, use an allow-list — never accept user input directly into the SQL string.
Tip: Always set
PDO::ATTR_EMULATE_PREPARES => false. It pushes type checking to the server and prevents a few edge-case injection vectors.Example
Example
<?php
// ✗ injection risk
// $pdo->query("SELECT * FROM users WHERE email = '$email'");
// ✓ safe
$stmt = $pdo->prepare('SELECT * FROM users WHERE email = ?');
$stmt->execute([$email]);
Try it Yourself »
Exercise
Best emulation setting for security.
PDO::ATTR_EMULATE_PREPARES =>
Five letters.
Discussion
Loading…