> ## Documentation Index
> Fetch the complete documentation index at: https://docs.tracecat.com/llms.txt
> Use this file to discover all available pages before exploring further.

# SQL

## `core.sql.execute_query`

Execute a parameterized SQL query on an external database.

### Secrets

Required secrets:

* `sql`: required values `CONNECTION_URL`.

### Inputs

<ParamField path="query" type="string" required>
  SQL query to execute. Use :param\_name syntax for bound parameters. Do NOT use Tracecat expressions in the query string.
</ParamField>

<ParamField path="bound_params" type="object | null">
  Bound query parameters as a dictionary (injected with :param\_name syntax). Supply dynamic values here, NOT within the query string. This is required for safe, parameterized SQL queries.

  Default: `null`.
</ParamField>

<ParamField path="fetch_one" type="boolean">
  Return a single row instead of a list of rows. Defaults to False, which fetches all rows.

  Default: `false`.
</ParamField>

<ParamField path="max_rows" type="integer">
  Maximum number of rows to return. Default 200. Prevents accidentally returning huge result sets.

  Default: `200`.
</ParamField>

### Examples

**Query an external database**

```yaml theme={null}
- ref: recent_logins
  action: core.sql.execute_query
  args:
    query: |
      SELECT user_email, last_login_at
      FROM user_logins
      WHERE last_login_at >= :cutoff
      ORDER BY last_login_at DESC
    bound_params:
      cutoff: ${{ TRIGGER.cutoff }}
    max_rows: 100
```

## `core.duckdb.execute_sql`

Execute SQL in an in-process DuckDB engine

### Secrets

Optional secrets:

* `amazon_s3`: optional values `AWS_ACCESS_KEY_ID`, `AWS_SECRET_ACCESS_KEY`, `AWS_SESSION_TOKEN`, `AWS_REGION`, `AWS_ROLE_ARN`, `AWS_ROLE_SESSION_NAME`.

### Inputs

<ParamField path="sql" type="string" required>
  SQL to execute in an in-process DuckDB connection.
</ParamField>

### Examples

**Run in-process SQL**

```yaml theme={null}
- ref: aggregate_results
  action: core.duckdb.execute_sql
  args:
    sql: |
      WITH findings(id, severity) AS (
        VALUES (1, 'high'), (2, 'low'), (3, 'high')
      )
      SELECT severity, count(*) AS count
      FROM findings
      GROUP BY severity
      ORDER BY count DESC
```

**Read from S3**

```yaml theme={null}
# Attach the amazon_s3 secret (static keys or AWS_ROLE_ARN for AssumeRole).
- ref: read_s3
  action: core.duckdb.execute_sql
  args:
    sql: |
      SELECT *
      FROM read_parquet('s3://my-bucket/findings/*.parquet')
```
