---
title: "Run SQL against a SQL database"
method: POST
path: "/storage/sqldbs/{id}/actions/query"
tags: ["sql databases"]
---

# Run SQL against a SQL database

`POST /storage/sqldbs/{id}/actions/query`

Runs SQL against the database and returns the resulting rows — empty for statements that return none, such as DDL. Bind positional `?` placeholders with `params` rather than interpolating values into the SQL string.

## Path parameters

- `id` string, uuid, required

## Request body

- SqlDatabaseQueryRequest
  - `params` union[] — Positional bind parameters, in placeholder order. Each value is a string, a number, a boolean, or null; booleans are cast to `1`/`0`. The count must match the number of `?` placeholders exactly — a mismatch is rejected with 422 rather than binding null for the ones you left out. (Not enforced for multi-statement scripts or named parameters, where the placeholder count is not the number bound.)
    - union
      - string
      - number
      - boolean
  - `sql` string, required — The SQL to run. Use positional `?` placeholders and supply the values in `params` rather than interpolating them into this string.

## Response `200`

The SQL result

- SqlDatabaseQueryResponseWrapper
  - `data` SqlDatabaseQueryResult
    - `count` integer — Number of rows returned.
    - `duration` number — Wall-clock duration of the request, in milliseconds.
    - `meta` SqlDatabaseQueryResultMeta
      - `changes` integer — Number of rows added, changed, or removed by the statement.
      - `duration` number — Wall-clock duration of the statement, in milliseconds.
      - `last_row_id` integer — Rowid of the last inserted row, when applicable.
      - `rows_read` integer
      - `rows_written` integer
    - `results` object[] — The result rows, each a map of column name to value. Empty for statements that return no rows.
    - `success` boolean

## Other responses

- `400` — Bad request — the request body is malformed
- `401` — Unauthorized
- `404` — SQL database not found
- `409` — Conflict — the database is not ready yet. This is transient; retry once it reaches `provision_ok`.
- `413` — The SQL body exceeds the maximum size (8 MiB)
- `422` — Validation error — an invalid `id`, empty `sql`, an unsupported bind parameter, the wrong number of bind parameters for the placeholders in `sql`, or a SQL error raised by the database. Also returned for a script over roughly 4 MiB, whose detail ends in `stream too large`: that transport ceiling is reached before the 8 MiB `413`, so ~4 MiB is the size to plan against
- `500` — Internal server error

---

[API](https://skmtc.net/team-telnyx/apis/telnyx-api-2.md) · [All operations](https://skmtc.net/team-telnyx/apis/telnyx-api-2/llms.txt) · [OpenAPI document](https://skmtc-service-staging.skmtc.workers.dev/v1/apis/team-telnyx/telnyx-api-2/revisions/ec31f78cf002/schema)
