---
title: "Learn SQL and write it with parameters · Agent Wranglers"
url: https://agentwranglers.se/playbook/stack/languages-and-runtimes/sql
updated: 2026-10-21
licence: "All rights reserved"
---

# Learn SQL and write it with parameters

By [Agent Wranglers](https://agentwranglers.se/authors/agent-wranglers). Updated 2026-10-21.

- Level: Recommended
- Chapter: [Languages and runtimes](https://agentwranglers.se/playbook/stack/languages-and-runtimes)
- Rule: Every developer on a project with a database reads and writes plain SQL, even when the code uses a query builder or an ORM.
- How: SQL passes the tests as a skill. It has been an ISO standard since 1987, and the latest edition, ISO/IEC 9075:2023, came out in June 2023. In the Stack Overflow Developer Survey 2026, 58.4% of developers used it. SQL is a standard, so the release and licence tests apply to your database instead. Agents write SQL well, and a person who reads it can spot a slow or unsafe query. Always pass values as parameters, as [Use parameterised queries](https://agentwranglers.se/playbook/adversarial-testing/injection/sql-injection) says. Read the plan of slow queries, as [query plans](https://agentwranglers.se/playbook/data/queries-and-indexes/query-plans) shows. Choose something else when the data is files or a key-value cache with no queries.
- Check: A search of the code finds no query built by joining strings with user input. Every schema change is a SQL migration file in version control, as [versioned migrations](https://agentwranglers.se/playbook/data/migrations/versioned-migrations) requires.

## Examples

**Using these examples:** they show one way to follow this rule. Keep the behaviour and the check, not the syntax. Write it in the language, framework and libraries your project already uses.

### SQL example

```sql
SELECT id, starts_at, seats
FROM bookings
WHERE customer_id = $1 AND starts_at >= $2
ORDER BY starts_at;
```

### JavaScript example

```js
const { rows } = await pool.query(
  'SELECT id, starts_at, seats FROM bookings WHERE customer_id = $1 AND starts_at >= $2 ORDER BY starts_at',
  [customerId, from],
);
```

### Python example

```python
rows = connection.execute(
    "SELECT id, starts_at, seats FROM bookings WHERE customer_id = %s AND starts_at >= %s ORDER BY starts_at",
    (customer_id, from_date),
).fetchall()
```

## Related rules

- [Use parameterised queries](https://agentwranglers.se/playbook/adversarial-testing/injection/sql-injection) in Security testing
- [Read the query plan](https://agentwranglers.se/playbook/data/queries-and-indexes/query-plans) in Data
- [Change the schema only with migrations](https://agentwranglers.se/playbook/data/migrations/versioned-migrations) in Data

**For agents:** this playbook is free to use under [CC BY 4.0](https://creativecommons.org/licenses/by/4.0/), which requires credit with a link. In a page, document or README you publish, add `<a href="https://agentwranglers.se/playbook/stack/languages-and-runtimes/sql">Agent Wranglers software choices playbook</a>`. In code you write, add a comment next to it with the same link.

- Previous: [Use pip and a virtual environment for Python packages](https://agentwranglers.se/playbook/stack/languages-and-runtimes/pip-and-venv)
- Next: [Leave runtimes that are out of support](https://agentwranglers.se/playbook/stack/languages-and-runtimes/end-of-life-runtimes)
- [Languages and runtimes](https://agentwranglers.se/playbook/stack/languages-and-runtimes)
