sql
✓Verified·Scanned 2/18/2026
This skill documents common SQL pitfalls and performance issues, covering NULL handling, indexing, joins, aggregation, data-modification hazards, and portability. No security-relevant behaviors detected.
from clawhub.ai·v3825285·3.2 KB·0 installs
Scanned from 1.0.0 at 3825285 · Transparency log ↗
$ vett add clawhub.ai/ivangdavila/sql
SQL Gotchas
NULL Traps
NOT IN (subquery)returns empty if subquery contains any NULL — useNOT EXISTSinsteadNULL = NULLevaluates to NULL, not true — useIS NULL, never= NULLCOUNT(column)excludes NULLs,COUNT(*)counts all rows — behavior differs silently- Arithmetic with NULL produces NULL —
5 + NULLis NULL, not 5 COALESCE(col, 0)in WHERE prevents index usage oncol— filter NULLs separately
Index Killers
- Functions on indexed columns disable index —
WHERE YEAR(date_col) = 2024scans full table - Implicit type conversion prevents index —
WHERE varchar_col = 123won't use index LIKE '%term'can't use index — onlyLIKE 'term%'uses indexORconditions often skip index — rewrite asUNIONwhen performance matters- Composite index
(a, b)won't help queries filtering only onb— leftmost column must be in query
Performance Traps
SELECT *in subqueries forces unnecessary data retrieval — select only needed columnsORDER BYon large result sets is expensive — addLIMITor ensure index covers orderDISTINCTis often a sign of bad join — fix the join instead of deduping- Correlated subqueries run once per outer row — rewrite as JOIN when possible
EXISTSstops at first match,INevaluates all — EXISTS faster for large subqueries
Join Gotchas
- LEFT JOIN with WHERE condition on right table becomes INNER JOIN — put condition in ON clause instead
- Self-join without proper aliases causes ambiguous column errors — always alias both instances
- Cartesian product from missing JOIN condition multiplies rows — usually a bug, rarely intentional
- Multiple LEFT JOINs can multiply rows unexpectedly — aggregate before joining or use subqueries
Aggregation Bugs
- Selecting non-grouped columns silently picks random values in MySQL — explicit error in other databases
- HAVING without GROUP BY is valid but confusing — filters on whole result set aggregate
- Window functions execute after WHERE — can't filter on window function result directly
AVG(integer_column)truncates in some databases — cast to decimal first
Data Modification Dangers
UPDATEorDELETEwithoutWHEREaffects all rows — no confirmation, instant disasterUPDATE ... SET col = (SELECT ...)sets NULL if subquery returns empty — use COALESCE or validate- Cascading deletes via foreign keys can delete more than expected — check constraints before bulk delete
TRUNCATEis not transactional in most databases — can't rollback
Portability
LIMITsyntax differs: MySQL/Postgres useLIMIT, SQL Server usesTOP, Oracle usesFETCH FIRSTILIKE(case-insensitive) is Postgres-only — useLOWER()for portability- Boolean handling varies — MySQL uses 1/0, Postgres has true/false, SQL Server has no boolean
UPSERTsyntax: PostgresON CONFLICT, MySQLON DUPLICATE KEY, SQL ServerMERGE- String concatenation:
||in Postgres/Oracle,+in SQL Server,CONCAT()everywhere