Skip to main content
The sql template tag allows you to write raw SQL snippets and queries when Kysely’s query builder API doesn’t cover your use case. It provides a safe way to embed SQL while preventing SQL injection through parameterization.

Basic Usage

Simple Raw SQL

Create a raw SQL snippet:
Substitutions (the things inside ${}) are automatically passed to the database as parameters and are never interpolated into the SQL string. There’s no need to worry about SQL injection vulnerabilities.

Executing Raw SQL

SQL snippets can be executed by calling the execute method:

Using Raw SQL in Queries

You can use raw SQL expressions in select, where, and other clauses:
The generated SQL (PostgreSQL):

Merging SQL Expressions

You can merge other sql expressions and queries using substitutions:

Helper Methods

The sql tag provides several helper methods for common use cases:

sql.ref - Column References

Interpret a substitution as a column reference:
The generated SQL (PostgreSQL):
References can include table names:
The generated SQL (PostgreSQL):
And schemas on supported databases:
The generated SQL (PostgreSQL):
Using sql.ref with unchecked inputs WILL lead to SQL injection vulnerabilities. The input is not checked or escaped by Kysely in any way.

sql.table - Table References

Interpret a substitution as a table reference:
The generated SQL (PostgreSQL):
With schema:
The generated SQL (PostgreSQL):
Using sql.table with unchecked inputs WILL lead to SQL injection vulnerabilities.

sql.id - Arbitrary Identifiers

Add arbitrary identifiers (like index names):
The generated SQL (PostgreSQL):
Multiple identifiers get separated by dots:
The generated SQL (PostgreSQL):
Using sql.id with unchecked inputs WILL lead to SQL injection vulnerabilities.

sql.val - Value Parameters

sql.val(value) is a shortcut for:
Example:

sql.lit - Literal Values

Add literal values directly to the SQL string:
The generated SQL (PostgreSQL):
The value is added directly to the SQL string instead of as a parameter. Using sql.lit with unchecked inputs WILL lead to SQL injection vulnerabilities. Only use this when something can’t be sent as a parameter.

sql.raw - Raw SQL Strings

Add arbitrary runtime SQL:
The generated SQL (PostgreSQL):
The difference between sql.lit and sql.raw is that sql.lit assumes the input is a value and will quote it appropriately, while sql.raw assumes the input is already valid SQL and glues it in as-is.
Using sql.raw with unchecked inputs WILL lead to SQL injection vulnerabilities.

sql.join - Lists

Join arrays of values or expressions:
The generated SQL (PostgreSQL):
The second argument is the joining expression (defaults to , ):
The generated SQL (PostgreSQL):

Type Safety

When using the sql tag, you need to specify the type of the expression:

Working with Expression Builder

You can combine raw SQL with the expression builder for type-safe column references:

Common Use Cases

Database Functions

Use raw SQL for database-specific functions:

CTEs with Raw SQL

Complex WHERE Conditions

Database-Specific Features

Best Practices

  1. Always use parameters: Never concatenate user input directly into SQL strings
  2. Specify types: Always provide type parameters to the sql tag
  3. Use helpers cautiously: Only use sql.ref, sql.table, sql.id, sql.lit, and sql.raw with trusted inputs
  4. Prefer query builder: Use raw SQL only when the query builder doesn’t support your use case
  5. Keep it simple: Break complex raw SQL into smaller, reusable pieces

API Reference

Main Tag

  • sql<T> - Create a raw SQL expression

Helper Methods

  • sql.ref<R>(columnReference) - Column reference
  • sql.table<T>(tableReference) - Table reference
  • sql.id<T>(...ids) - Arbitrary identifier
  • sql.val<V>(value) - Value parameter
  • sql.lit<V>(value) - Literal value
  • sql.raw<R>(sql) - Raw SQL string
  • sql.join<T>(array, separator?) - Join array items

Deprecated

  • sql.value<V>(value) - Use sql.val instead
  • sql.literal<V>(value) - Use sql.lit instead