SQL injection happens when user input becomes part of a query:
Vulnerable code:
query = "SELECT * FROM users WHERE id = " + userId
// userId = "1; DROP TABLE users;--"
Prevention:
Parameterized queries (prepared statements):
query = "SELECT * FROM users WHERE id = ?"
db.execute(query, [userId])
ORM methods: Most ORMs parameterize automatically
Input validation: Reject non-numeric user IDs
Least privilege: Database user can't DROP tables
Parameterized queries separate code from data. The database knows userId is a value, not SQL.