SQL Security: Prevent Injection and Unsafe Queries

SQL security starts with a simple rule: do not build SQL by concatenating visitor input. Validate input for business rules, then pass values through prepared statements.

Do not use escaping as your primary SQL-injection defense. The old mysql_real_escape_string() API belongs to the removed legacy MySQL extension. Use PDO or MySQLi prepared statements for values.

Use prepared statements for values

<?php
require "config.php";

$catId = filter_input(INPUT_GET, 'cat_id', FILTER_VALIDATE_INT);
if ($catId === false || $catId === null) {
    http_response_code(400);
    exit('Invalid category');
}

$stmt = $dbo->prepare('SELECT id, name FROM category WHERE id = :id');
$stmt->execute([':id' => $catId]);
$row = $stmt->fetch(PDO::FETCH_ASSOC);
?>

Validate numeric input when the application requires a number

<?php
$id = filter_input(INPUT_GET, 'id', FILTER_VALIDATE_INT);
if ($id === false || $id === null) {
    exit('Data error');
}
?>

Validate a list of integer IDs

The old tutorial used removed split() and each(). Use explode()/foreach, validate each element, and create one placeholder per value.

<?php
$raw = '2,3,5';
$ids = array_values(array_filter(array_map('trim', explode(',', $raw)), 'strlen'));
foreach ($ids as $id) {
    if (filter_var($id, FILTER_VALIDATE_INT) === false) {
        exit('Data error');
    }
}

$placeholders = implode(',', array_fill(0, count($ids), '?'));
$stmt = $dbo->prepare("SELECT id, name FROM student WHERE id IN ($placeholders)");
$stmt->execute(array_map('intval', $ids));
?>

Validate text for the rule you actually need

Validation and SQL safety are different layers. If a username is defined as letters and digits only, ctype_alnum() can enforce that rule; the database query should still use parameters.

<?php
$username = trim((string)($_POST['username'] ?? ''));
if ($username === '' || !ctype_alnum($username)) {
    exit('Data error');
}
?>

For letters, numbers, spaces, dots, hyphens and underscores:

<?php
$value = trim((string)($_POST['value'] ?? ''));
if (!preg_match('/^[a-z0-9 ._-]+$/i', $value)) {
    exit('Data error');
}
?>

Identifiers cannot be bound like values

Prepared placeholders represent data values, not table names, column names or SQL keywords. For user-selectable sorting or columns, map the request to a fixed allow-list.

<?php
$allowedSort = ['name', 'mark', 'class'];
$requested = (string)($_GET['sort'] ?? 'name');
$sort = in_array($requested, $allowedSort, true) ? $requested : 'name';

$sql = "SELECT id, name, class, mark FROM student ORDER BY $sort";
$stmt = $dbo->query($sql);
?>

Do not expose database errors to visitors

Log technical details server-side and return a generic message to the visitor. Avoid publishing connection strings, SQL text, stack traces or database credentials in browser output.

PDO · MySQLi · IN() · Safe dynamic ORDER BY · Record existence checks




Subscribe to our YouTube Channel here



plus2net.com
lija

14-07-2009

its very use full
pdemmy

24-08-2009

the resources here are useful...thanhs
DEE

02-03-2010

Well its really gud.......but it should b more comprehensive.
Ali Mohamed Omar

22-05-2010

the resources here are useful...thanhs
John

09-05-2012

thank you - this will help
Rayon

04-05-2013

Nice one..
Sanju

09-10-2014

its very use full thanks for posting.......
vveer

16-10-2014

Thanks for the info. Very useful




SQL Video Tutorials










✖
We use cookies to improve your browsing experience. . Learn more
HTML MySQL PHP JavaScript ASP Photoshop Articles Contact us
© 2000-2026 plus2net.com All rights reserved worldwide Privacy Policy Disclaimer