<!-- BusyBot node reference — https://busybot.net/tools/snowflake/ -->

> Node: Snowflake (`snowflake`) · Action · v1
> Category: Data & Storage · Credentials: Snowflake (`snowflakeApi`)
> Updated: 2026-08-16

# Snowflake

> Execute SQL operations against Snowflake cloud data warehouse with parameterized queries for safe data retrieval and manipulation.

## Overview

Snowflake cloud data warehouse tool for performing SQL operations. Supports three operations: Execute Query (run arbitrary SQL), Insert (write rows into a table using parameterized bind variables), and Update (change rows matched by a key column using parameterized bind variables). Both password and key-pair (JWT) authentication are supported. All data values are sent as parameterized bind variables to prevent SQL injection.

**Category:** Data & Storage  
**Tool Name:** `snowflake`  
**Version:** 1

**Appearance:** Icon: `si-snowflake` | Color: `#29B5E8`

## Node Type

**Action** — processes input items and produces output

## Input / Output

| Direction | Port(s) |
|-----------|--------|
| Input | `Input` |
| Output | `Output`, `Error` |

## Credentials

This tool requires **Snowflake** credentials.
See the [Credentials Guide](https://busybot.net/credentials/snowflake-api/) for setup instructions.

### Operations

| Operation | Value | Description |
|-----------|-------|-------------|
| Execute Query | `executeQuery` | Execute an SQL query |
| Insert | `insert` | Insert rows in database |
| Update | `update` | Update rows in database |

### Parameters

#### Execute Query (`executeQuery`)

| Parameter | Type | Required | Default | Description |
|-----------|------|----------|---------|-------------|
| Query | `string` | Yes | — | The SQL query to execute. Use ? positional placeholders for any user-supplied values and pass them via additionalFields.bindParams. {{ expressions }} are NOT permitted in the SQL string itself (SQL injection risk). |
| Additional Fields | `collection` | No | `{}` | Optional settings for the query. |
| — Bind Parameters | `json` | No | `[]` | Array of values bound to ? placeholders in the query (in order). String entries may use {{ }} expressions; each value becomes a separate positional bind so it is safe from SQL injection. |

#### Insert (`insert`)

| Parameter | Type | Required | Default | Description |
|-----------|------|----------|---------|-------------|
| Table | `string` | Yes | — | Name of the table to insert data into. |
| Columns | `string` | No | — | Comma-separated list of the properties which should be used as columns for the new rows. Values are taken from the input item JSON fields with matching names. |

#### Update (`update`)

| Parameter | Type | Required | Default | Description |
|-----------|------|----------|---------|-------------|
| Table | `string` | Yes | — | Name of the table to update data in. |
| Update Key | `string` | Yes | `id` | Name of the column which decides which rows in the database should be updated. Normally that would be "id". |
| Columns | `string` | No | — | Comma-separated list of the properties which should be used as columns for rows to update. Values are taken from the input item JSON fields with matching names. |

#### All Operations

| Parameter | Type | Required | Default | Description |
|-----------|------|----------|---------|-------------|
| Max Concurrency | `number` | No | `10` | Maximum number of items to process concurrently. |

## Output Data

For Execute Query, returned rows replace the item: each row becomes its own output item and the row's columns *are* that item's JSON, so a query returning 200 rows turns one input item into 200 output items. For Insert and Update, each input item produces exactly one output item. In every case the input item's other JSON fields do not pass through, and binary data on the input item is forwarded onto the output items.

| Operation | Output items |
|-----------|--------------|
| `executeQuery` | One item per returned row, holding that row's columns. A statement that returns no rows produces one item: `{ "success": true, "rowsAffected": 0 }` |
| `insert` | One item per input item, containing only the columns named in Columns, with the values that were written |
| `update` | One item per input item, containing only the columns named in Columns, with the values that were written |

Reference the values downstream by column name, e.g. `{{ $json.customer_id }}` for Insert and Update, or the column names your query selected for Execute Query.

## Usage Examples

- Execute a SELECT query against a Snowflake table
- Insert rows into a Snowflake table from input items
- Update rows in a Snowflake table matched by an ID column
- Run aggregate analytics queries on Snowflake data warehouse
- Query Snowflake views or materialized views

## Example Configuration

Run a query whose two placeholders are filled from the input item:

```json
{
  "type": "snowflake",
  "parameters": {
    "operation": "executeQuery",
    "query": "SELECT * FROM users WHERE created_date >= ? AND status = ?",
    "additionalFields": {
      "bindParams": ["{{ $json.startDate }}", "{{ $json.status }}"]
    },
    "maxConcurrency": 5
  }
}
```

Insert one row per input item, taking the values from matching JSON fields:

```json
{
  "type": "snowflake",
  "parameters": {
    "operation": "insert",
    "table": "customers",
    "columns": "customer_id,name,email,phone,created_at",
    "maxConcurrency": 10
  }
}
```

Update rows matched by a key column:

```json
{
  "type": "snowflake",
  "parameters": {
    "operation": "update",
    "table": "user_profiles",
    "updateKey": "user_id",
    "columns": "name,email,last_login,status",
    "maxConcurrency": 8
  }
}
```

Execute an analytical query with a dynamic date range:

```json
{
  "type": "snowflake",
  "parameters": {
    "operation": "executeQuery",
    "query": "SELECT product_id, SUM(quantity) as total_sold, AVG(price) as avg_price FROM sales WHERE sale_date BETWEEN ? AND ? GROUP BY product_id ORDER BY total_sold DESC",
    "additionalFields": {
      "bindParams": ["{{ $json.start_date }}", "{{ $json.end_date }}"]
    },
    "maxConcurrency": 3
  }
}
```

Load records from an upstream API response into a table:

```json
{
  "type": "snowflake",
  "parameters": {
    "operation": "insert",
    "table": "customer_master",
    "columns": "external_id,company_name,contact_email,phone_number,industry,created_timestamp",
    "maxConcurrency": 15
  }
}
```

Update account records from activity data:

```json
{
  "type": "snowflake",
  "parameters": {
    "operation": "update",
    "table": "user_accounts",
    "updateKey": "account_id",
    "columns": "last_active_date,login_count,account_status,updated_by",
    "maxConcurrency": 12
  }
}
```

Generate a report with one dynamic filter:

```json
{
  "type": "snowflake",
  "parameters": {
    "operation": "executeQuery",
    "query": "SELECT r.region_name, COUNT(o.order_id) as order_count, SUM(o.total_amount) as revenue FROM orders o JOIN regions r ON o.region_id = r.region_id WHERE o.order_date >= ? GROUP BY r.region_name",
    "additionalFields": {
      "bindParams": ["{{ $json.report_start }}"]
    },
    "maxConcurrency": 5
  }
}
```

### Error Handling

| Mode | Behavior |
|------|----------|
| **stop** | Halts workflow on first error |
| **continue** | Skips failed items, passes successful ones through |
| **errorPort** | Routes failed items to Error output port |

## Tips

Execute SQL queries, insert rows, or update rows in a Snowflake cloud data warehouse using parameterized bind variables.

### Important Notes

1. **Dynamic Values in Queries**: When using `executeQuery`, dynamic values MUST be passed via `additionalFields.bindParams` using `?` placeholders in the SQL. Embedding `{{ }}` expressions directly in the query string is rejected (SQL injection risk). Each bindParams entry may itself be a `{{ }}` expression — it is evaluated per item and bound as a separate positional parameter.

2. **Column Mapping**: For `insert` and `update` operations, the `columns` parameter should list field names that exist in your input data. The tool will automatically map JSON fields to database columns.

3. **Update Key**: The `updateKey` parameter in update operations determines which database records to modify. Ensure this column exists and contains unique identifiers.

4. **Concurrency**: Use `maxConcurrency` to control database load. Lower values for heavy queries, higher values for simple operations.

### Behavior notes

- **Columns is effectively required for Insert and Update.** Leave it empty and the item fails with a message asking for a comma-separated column list — the node never guesses the column set from the item.
- **The update key belongs in the WHERE clause, not the SET list.** If you name it in Columns it is dropped from the assignment list and only used to match rows, so an update whose Columns contains nothing but the key fails. Its value is always read from the input item.
- **A field the item does not have is written as null.** Columns names the shape of the statement; each item supplies the values, and any name it lacks binds as null rather than being skipped.
- **Values are bound; names are not.** Every value travels as a `?` bind. Table, column and update-key names are written into the statement as quoted identifiers, so keep untrusted input out of those three fields.
- **Query is passed through untouched.** The statement you type is sent as written, which is why `{{ }}` inside it is rejected outright — put the moving parts in Bind Parameters instead.