Skip to main content

Overview

Prepared statements allow you to define a query once and execute it multiple times with different parameters. This approach provides:
  • Performance: Query planning happens once, not on every execution
  • Security: Protection against SQL injection through parameterization
  • Reusability: Define complex queries once, reuse with different values
  • Type Safety: Full TypeScript inference for parameters and results

Basic Usage

Creating a Prepared Statement

Use the .prepare() method to create a reusable query:

Named Statements

Provide a unique name to your prepared statements:
The statement name is used by the database driver for caching. Use descriptive names that identify the query’s purpose.

Using Placeholders

SQL Placeholder Function

The sql.placeholder() function creates named parameters:

Placeholders in WHERE Clauses

Use placeholders for dynamic filtering:

Multiple Placeholders

Combine multiple placeholders in complex queries:

Advanced Patterns

Placeholders in LIMIT and OFFSET

Create reusable pagination queries:

Complex Prepared Statements

Combine with joins and multiple conditions:

Update with Placeholders

Prepare dynamic update statements:

Delete with Placeholders

Create reusable delete operations:

Database-Specific Features

PostgreSQL

PostgreSQL prepared statements use positional parameters internally:

MySQL

MySQL prepared statements use ? placeholders:

SQLite

SQLite supports both named and positional parameters:

Performance Benefits

Execution Time Comparison

For queries executed more than once, prepared statements can reduce execution time by 30-60% by avoiding repeated query planning.

When to Use Prepared Statements

1

Repeated queries with different parameters

Bulk operations, pagination, or search functionality.
2

Performance-critical paths

Hot code paths where every millisecond counts.
3

User input handling

Any query that includes user-provided values for security.
4

Batch operations

Processing large datasets with similar query patterns.

Type Safety

Prepared statements maintain full type inference:

Security Considerations

SQL Injection Prevention

Prepared statements automatically escape parameters:
Never concatenate user input directly into SQL strings, even when using prepared statements. Always use placeholders for dynamic values.

Safe vs Unsafe Patterns

Common Pitfalls

Statement Caching

Prepared statement names must be unique across your application. Reusing names can cause unexpected behavior.

Optional Parameters

Handle optional placeholders carefully:

Best Practices

1

Use descriptive statement names

Name your statements clearly: get_user_by_email not stmt1.
2

Prepare statements outside loops

Create prepared statements once, then execute multiple times.
3

Use placeholders for all dynamic values

Never interpolate user input directly into SQL.
4

Consider transaction context

Prepared statements work within transactions for consistent performance.
5

Profile before optimizing

Measure query performance before converting all queries to prepared statements.

Real-World Example

Here’s a complete example of using prepared statements in an API endpoint:
Organize your prepared statements in a dedicated module and export them for reuse across your application.