All posts

Two SQL Reviews Every Query Should Pass

July 31, 2026 · DevTools

sql
sql-injection
performance
security
databases

Every SQL query deserves two reviews before it ships: one for security (does it let an attacker in?) and one for performance (does it scale past a few rows?). Neither needs a running database — the dangerous patterns are well known and easy to spot in the text. Here is what to look for in each.

Review 1: Is it injectable?

SQL injection happens when untrusted input is concatenated into a query and the database interprets it as code. The payloads are remarkably consistent, which makes them easy to scan for:

  • TautologiesOR '1'='1', OR 1=1 — make a WHERE clause always true, bypassing logins and filters.
  • UNION SELECT — appends a second result set to exfiltrate data from other tables.
  • Stacked queries — a ; followed by a new statement (; DROP TABLE users).
  • Comments-- and /* */ to truncate or break up the original query.
  • Time-based blindSLEEP(), WAITFOR DELAY, pg_sleep() to infer data through response timing.
  • Schema enumerationinformation_schema, sysobjects to map the database.

Paste a suspect payload, a form value, or a query fragment into the SQL Injection Detector and it runs these signatures, reports each match with an explanation, classifies the injection type, and scores the payload 0–100. A classic login bypass scores critical:

admin' OR '1'='1' --

The important caveat: a clean scan is not proof of safety. Heuristics catch the obvious, not every obfuscated variant. The real fix is always parameterized queries (prepared statements) — bind variables can't become code no matter what the input contains. Use the detector to prioritize and to demonstrate the risk, then fix the construction.

Review 2: Is it fast?

Performance problems also cluster into a small set of anti-patterns, and you can find most of them by reading the query:

  • SELECT * — fetches every column, more I/O than needed and brittle when the schema changes.
  • Leading-wildcard LIKELIKE '%term' can't use a normal index and forces a full scan.
  • No WHERE — a read or modify with no predicate scans every row.
  • Comma cross joinsFROM users, orders with no join condition produces a Cartesian product.
  • NOT IN — breaks entirely if the subquery returns a NULL; NOT EXISTS is safer and often faster.
  • Functions on columnsWHERE LOWER(name) = ? disables the index on name.
  • ORDER BY without LIMIT — sorts an unbounded set.

The SQL Performance Analyzer flags each of these, ranks them by severity with a concrete suggestion, and scores the query 0–100. A query like:

SELECT * FROM users WHERE name LIKE '%ada%'

loses points twice — for SELECT * and for the leading-wildcard LIKE. The analyzer tells you exactly which penalties apply and why.

This review is schema-agnostic, so it points at likely problems fast. The final verdict still depends on indexes, row counts, and the real execution plan — confirm each change with EXPLAIN on production-sized data.

Two reviews, one habit

Run the injection check on anything that touches user input, and run the performance check on anything that might touch a large table. Both run in your browser, neither needs a database, and together they catch the two failure modes that embarrass teams in production. And if you've moved to documents, the NoSQL Validator does the same shape-check for MongoDB $jsonSchema.