Run SQL with dh#

These examples use the table from Getting Started. Replace OWNER with your username.

Read a branch, tag, or commit#

dh sql --db OWNER/people --branch main "SELECT * FROM people ORDER BY id"

Every read requires --branch or --ref. Use --branch for a branch, or --ref for a branch, tag, or commit SHA. The two flags are mutually exclusive. --limit caps returned rows; --timeout sets the server-side read timeout, from 1ms through 60s in whole milliseconds.

dh sql --db OWNER/people --branch main --limit 10 --timeout 5s \
  "SELECT * FROM people ORDER BY id"

Read SQL from a file or pipe#

Save this as query.sql:

SELECT id, name, city FROM people ORDER BY id;

Run it with:

dh sql --db OWNER/people --branch main --file query.sql

Or pipe SQL into the command:

printf 'SELECT COUNT(*) FROM people;\n' | dh sql --db OWNER/people --branch main

--file - explicitly reads stdin. A query argument and --file are mutually exclusive. Without either, dh reads piped stdin; an empty query is rejected.

Write to a branch#

dh sql --write --db OWNER/people --branch feature/people --from-branch main \
  "UPDATE people SET city = 'Paris' WHERE id = 1"

--write selects asynchronous write mode. --branch is the target, and --from-branch supplies the source branch when creating or updating a feature branch. If omitted, the source defaults to the target branch. Use --file update.sql for a query stored in a file.

The command waits for the write job and prints its result. To submit and return immediately after acceptance, add --no-wait; then use dh job watch with the returned ID.

Read and write options#

ModeRequiredAdditional options
Read--branch or --ref--limit, --timeout
Write--write, --branch--from-branch, --no-wait

--branch works in both modes. --ref, --limit, and --timeout are read-only; --from-branch and --no-wait require write mode. The branch/reference selection is explicit even when you have configured a default database.

Structured results and failures#

dh sql --db OWNER/people --branch main "SELECT id, name FROM people ORDER BY id" \
  --json columns,rows,status

Read output can include columns, rows, status, message, and warnings. Rows are arrays aligned with the column metadata. Writes return job fields instead. For acceptance without waiting, use --no-wait --json id,href; for completed writes, use fields such as id,status,result.

A failed query or failed write job returns a nonzero exit code, even when output was printed. Read warnings go to stderr in human-readable mode. Scripts should check the exit code as well as any JSON they consume. See Automate with dh and the complete dh sql reference.