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

> Node: Data Table (`data_table`) · Action · v1
> Category: Core Nodes · Credentials: none
> Updated: 2026-08-16

# Data Table

> Save and query structured data persistently across workflow executions

## Overview

Data Table provides persistent tabular storage within the workflow platform. It supports typed columns (string, number, boolean, date), CRUD operations on rows, table management, conditional pass-through (row exists/not exists), filtering with multiple condition types, sorting, pagination, and bulk insert optimization. System columns (id, createdAt, updatedAt) are added automatically. This is an internal storage mechanism — no external API or credentials required.

**Category:** Core Nodes  
**Tool Name:** `data_table`  
**Version:** 1

**Appearance:** Icon: `lucide-Database` | Color: `#FF6D5A`

## Node Type

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

## Input / Output

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

## Credentials

This tool does not require any credentials.

### Resources

| Resource | Value |
|----------|-------|
| Row | `row` |
| Table | `table` |

### Operations

Rows (`resource` is `row`):

| Operation | Value | Description |
|-----------|-------|-------------|
| Delete | `deleteRows` | Delete row(s) |
| Get | `get` | Get row(s) |
| If Row Exists | `rowExists` | Match input items that are in the data table |
| If Row Does Not Exist | `rowNotExists` | Match input items that are not in the data table |
| Insert | `insert` | Insert a new row |
| Update | `update` | Update row(s) matching certain fields |
| Upsert | `upsert` | Update row(s), or insert if there is no match |

Tables (`resource` is `table`):

| Operation | Value | Description |
|-----------|-------|-------------|
| Create | `create` | Create a new data table |
| Delete | `delete` | Delete a data table |
| List | `list` | List all data tables |
| Update | `update` | Update a data table name |

### Parameters

#### Row: Insert

| Parameter | Type | Required | Default | Description |
|-----------|------|----------|---------|-------------|
| Data Table | `string` | Yes | — | The ID or name of the data table. You can find table IDs in the data tables management page. |
| Column Mapping Mode | `options` | No | `defineBelow` | Whether to map input item fields automatically or define column values explicitly. Auto-map copies input JSON and strips system columns (id, createdAt, updatedAt). |
| | | | | Options: `autoMapInputData`, `defineBelow` |
| Column Values | `json` | No | `{}` | JSON object with column names as keys and values to set. Example: {"name": "John", "age": 30, "active": true}. _(shown when Column Mapping Mode is `defineBelow`)_ |
| Optimize Bulk | `boolean` | No | `false` | Whether to improve bulk insert performance by not returning inserted data (returns count only). |

#### Row: Get

| Parameter | Type | Required | Default | Description |
|-----------|------|----------|---------|-------------|
| Data Table | `string` | Yes | — | The ID or name of the data table. You can find table IDs in the data tables management page. |
| Must Match | `options` | No | `anyCondition` | Whether rows must match any condition (OR) or all conditions (AND). |
| | | | | Options: `anyCondition`, `allConditions` |
| Filter Conditions | `json` | No | `[]` | Array of filter conditions. Each condition: { "keyName": "columnName", "condition": "eq\|neq\|gt\|gte\|lt\|lte\|like\|ilike\|isEmpty\|isNotEmpty\|isTrue\|isFalse", "keyValue": "value" }. The keyValue field is not needed for isEmpty, isNotEmpty, isTrue, and isFalse conditions. |
| Return All | `boolean` | No | `false` | Whether to return all results or only up to a given limit. |
| Limit | `number` | No | `50` | Max number of results to return. _(shown when Return All is `false`)_ |
| Order By | `boolean` | No | `false` | Whether to sort the results by a column. |
| Order By Column | `string` | No | `createdAt` | The column name to sort by. Must match an existing column in the data table. _(shown when Order By is `true`)_ |
| Order By Direction | `options` | No | `DESC` | Sort direction for the column. _(shown when Order By is `true`)_ |
| | | | | Options: `ASC`, `DESC` |

#### Row: Update

| Parameter | Type | Required | Default | Description |
|-----------|------|----------|---------|-------------|
| Data Table | `string` | Yes | — | The ID or name of the data table. You can find table IDs in the data tables management page. |
| Must Match | `options` | No | `anyCondition` | Whether rows must match any condition (OR) or all conditions (AND). |
| | | | | Options: `anyCondition`, `allConditions` |
| Filter Conditions | `json` | No | `[]` | Array of filter conditions selecting the rows to update. At least one condition is required. |
| Column Mapping Mode | `options` | No | `defineBelow` | Whether to map input item fields automatically or define column values explicitly. Auto-map copies input JSON and strips system columns (id, createdAt, updatedAt). |
| | | | | Options: `autoMapInputData`, `defineBelow` |
| Column Values | `json` | No | `{}` | JSON object with column names as keys and values to set. Example: {"name": "John", "age": 30, "active": true}. _(shown when Column Mapping Mode is `defineBelow`)_ |
| Dry Run | `boolean` | No | `false` | Whether to simulate the operation and return affected rows without committing changes. |

#### Row: Upsert

| Parameter | Type | Required | Default | Description |
|-----------|------|----------|---------|-------------|
| Data Table | `string` | Yes | — | The ID or name of the data table. You can find table IDs in the data tables management page. |
| Must Match | `options` | No | `anyCondition` | Whether rows must match any condition (OR) or all conditions (AND). |
| | | | | Options: `anyCondition`, `allConditions` |
| Filter Conditions | `json` | No | `[]` | Array of filter conditions deciding whether a matching row already exists. At least one condition is required. |
| Column Mapping Mode | `options` | No | `defineBelow` | Whether to map input item fields automatically or define column values explicitly. Auto-map copies input JSON and strips system columns (id, createdAt, updatedAt). |
| | | | | Options: `autoMapInputData`, `defineBelow` |
| Column Values | `json` | No | `{}` | JSON object with column names as keys and values to set. Example: {"name": "John", "age": 30, "active": true}. _(shown when Column Mapping Mode is `defineBelow`)_ |
| Dry Run | `boolean` | No | `false` | Whether to simulate the operation and return affected rows without committing changes. |

#### Row: Delete

| Parameter | Type | Required | Default | Description |
|-----------|------|----------|---------|-------------|
| Data Table | `string` | Yes | — | The ID or name of the data table. You can find table IDs in the data tables management page. |
| Must Match | `options` | No | `anyCondition` | Whether rows must match any condition (OR) or all conditions (AND). |
| | | | | Options: `anyCondition`, `allConditions` |
| Filter Conditions | `json` | No | `[]` | Array of filter conditions selecting the rows to delete. At least one condition is required. |
| Dry Run | `boolean` | No | `false` | Whether to simulate the operation and return affected rows without committing changes. |

#### Row: If Row Exists

| Parameter | Type | Required | Default | Description |
|-----------|------|----------|---------|-------------|
| Data Table | `string` | Yes | — | The ID or name of the data table. You can find table IDs in the data tables management page. |
| Must Match | `options` | No | `anyCondition` | Whether rows must match any condition (OR) or all conditions (AND). |
| | | | | Options: `anyCondition`, `allConditions` |
| Filter Conditions | `json` | No | `[]` | Array of filter conditions the item is tested against. |

#### Row: If Row Does Not Exist

| Parameter | Type | Required | Default | Description |
|-----------|------|----------|---------|-------------|
| Data Table | `string` | Yes | — | The ID or name of the data table. You can find table IDs in the data tables management page. |
| Must Match | `options` | No | `anyCondition` | Whether rows must match any condition (OR) or all conditions (AND). |
| | | | | Options: `anyCondition`, `allConditions` |
| Filter Conditions | `json` | No | `[]` | Array of filter conditions the item is tested against. |

#### Table: Create

| Parameter | Type | Required | Default | Description |
|-----------|------|----------|---------|-------------|
| Table Name | `string` | Yes | — | The name of the data table to create. |
| Columns | `json` | No | `[]` | Array of column definitions for the new table. Each column: {"name": "columnName", "type": "string\|number\|boolean\|date"}. System columns (id, createdAt, updatedAt) are added automatically. |
| Reuse Existing Tables | `boolean` | No | `true` | Whether to return an existing table with the same name instead of throwing an error. |

#### Table: List

| Parameter | Type | Required | Default | Description |
|-----------|------|----------|---------|-------------|
| Return All | `boolean` | No | `true` | Whether to return all tables or only up to a given limit. |
| Limit | `number` | No | `50` | Max number of tables to return. _(shown when Return All is `false`)_ |
| Filter by Name | `string` | No | — | Filter data tables by name (case-insensitive). |
| Sort Field | `options` | No | `name` | Field to sort the table list by. |
| | | | | Options: `createdAt`, `name`, `updatedAt` |
| Sort Direction | `options` | No | `asc` | Sort direction for the table list. |
| | | | | Options: `asc`, `desc` |

#### Table: Update

| Parameter | Type | Required | Default | Description |
|-----------|------|----------|---------|-------------|
| Data Table | `string` | Yes | — | The ID or name of the data table to operate on. |
| New Name | `string` | Yes | — | The new name for the data table. |

#### Table: Delete

| Parameter | Type | Required | Default | Description |
|-----------|------|----------|---------|-------------|
| Data Table | `string` | Yes | — | The ID or name of the data table to operate on. |

#### All Operations

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

## Output Data

Except for the two conditional operations, this node **replaces** the item JSON with the operation's result and does not forward binary data. Read anything you still need from the item before this node, or send it down a parallel branch.

| Resource and operation | Items out and what is on them |
|------------------------|-------------------------------|
| Row: `insert` | One item holding the inserted row, including the system columns `id`, `createdAt` and `updatedAt`. With **Optimize Bulk** on, a count result is returned instead of the row data. |
| Row: `get` | One item per matching row. A query that matches nothing produces no output items at all. |
| Row: `update` | One item per updated row. |
| Row: `upsert` | One item per row that was updated or inserted. |
| Row: `deleteRows` | One item per deleted row. |
| Row: `rowExists` | The original input item, unchanged, when at least one row matches. When nothing matches the item is dropped and produces no output. |
| Row: `rowNotExists` | The original input item, unchanged, when no row matches. When something matches the item is dropped. |
| Table: `create` | One item holding the data table record, including its `id` and `name`. With **Reuse Existing Tables** on and a name that already exists, the existing table's record is returned instead. |
| Table: `list` | One item per data table. |
| Table: `update` | One item: `{ "success": true, "name": "<the new name>" }`. |
| Table: `delete` | One item: `{ "success": true, "deletedTableId": "<the table id>" }`. |

A row comes back with your own columns plus the three system columns:

```json
{
  "id": 17,
  "name": "John Doe",
  "email": "john@example.com",
  "age": 30,
  "active": true,
  "createdAt": "2026-01-15T10:00:00.000Z",
  "updatedAt": "2026-01-15T10:00:00.000Z"
}
```

Date values always come back as ISO 8601 strings, so they are safe to compare and to pass to other nodes.

**Dry Run** changes nothing in storage but still emits the rows the operation *would* have touched, which makes it a safe way to preview a destructive filter before running it for real.

`deleteRows`, `update` and `upsert` require at least one filter condition — an empty **Filter Conditions** array fails the item rather than matching every row.

Because `rowExists` and `rowNotExists` drop non-matching items, they act as filters in the middle of a branch rather than as data sources.

## Usage Examples

- Insert a row into a data table from workflow data
- Query rows from a data table with filters and sorting
- Delete rows matching specific conditions
- Update rows that match a filter
- Upsert: update if exists, insert if not
- Check if a row exists before proceeding
- Create a new data table with typed columns
- List all available data tables
- Rename or delete a data table

## Example Configuration

Insert a row straight from the incoming item's fields:

```json
{
  "type": "data_table",
  "parameters": {
    "resource": "row",
    "operation": "insert",
    "dataTableId": "users_table",
    "columnsMappingMode": "autoMapInputData"
  }
}
```

Insert a row with values you set explicitly:

```json
{
  "type": "data_table",
  "parameters": {
    "resource": "row",
    "operation": "insert",
    "dataTableId": "users_table",
    "columnsMappingMode": "defineBelow",
    "columnsValue": {
      "name": "John Doe",
      "email": "john@example.com",
      "age": 30,
      "active": true
    }
  }
}
```

Query rows with two conditions, a limit and a sort:

```json
{
  "type": "data_table",
  "parameters": {
    "resource": "row",
    "operation": "get",
    "dataTableId": "users_table",
    "matchType": "allConditions",
    "filterConditions": [
      {
        "keyName": "active",
        "condition": "isTrue"
      },
      {
        "keyName": "age",
        "condition": "gte",
        "keyValue": "18"
      }
    ],
    "returnAll": false,
    "limit": 50,
    "orderBy": true,
    "orderByColumn": "name",
    "orderByDirection": "ASC"
  }
}
```

Preview an update without committing it:

```json
{
  "type": "data_table",
  "parameters": {
    "resource": "row",
    "operation": "update",
    "dataTableId": "users_table",
    "matchType": "anyCondition",
    "filterConditions": [
      {
        "keyName": "email",
        "condition": "like",
        "keyValue": "@example.com"
      }
    ],
    "columnsMappingMode": "defineBelow",
    "columnsValue": {
      "status": "verified"
    },
    "dryRun": true
  }
}
```

Delete inactive rows that have never logged in:

```json
{
  "type": "data_table",
  "parameters": {
    "resource": "row",
    "operation": "deleteRows",
    "dataTableId": "users_table",
    "matchType": "allConditions",
    "filterConditions": [
      {
        "keyName": "active",
        "condition": "isFalse"
      },
      {
        "keyName": "last_login",
        "condition": "isEmpty"
      }
    ]
  }
}
```

Let only items that already exist in the table continue:

```json
{
  "type": "data_table",
  "parameters": {
    "resource": "row",
    "operation": "rowExists",
    "dataTableId": "users_table",
    "matchType": "allConditions",
    "filterConditions": [
      {
        "keyName": "email",
        "condition": "eq",
        "keyValue": "{{ $json.email }}"
      }
    ]
  }
}
```

Create a typed table, reusing it if it already exists:

```json
{
  "type": "data_table",
  "parameters": {
    "resource": "table",
    "operation": "create",
    "tableName": "products",
    "tableColumns": [
      {
        "name": "name",
        "type": "string"
      },
      {
        "name": "price",
        "type": "number"
      },
      {
        "name": "in_stock",
        "type": "boolean"
      },
      {
        "name": "launch_date",
        "type": "date"
      }
    ],
    "createIfNotExists": true
  }
}
```

List tables whose name contains "user":

```json
{
  "type": "data_table",
  "parameters": {
    "resource": "table",
    "operation": "list",
    "returnAll": false,
    "limit": 20,
    "filterName": "user",
    "sortField": "name",
    "sortDirection": "asc"
  }
}
```

Rename a table:

```json
{
  "type": "data_table",
  "parameters": {
    "resource": "table",
    "operation": "update",
    "dataTableId": "old_table_name",
    "newName": "new_table_name"
  }
}
```

Delete a table:

```json
{
  "type": "data_table",
  "parameters": {
    "resource": "table",
    "operation": "delete",
    "dataTableId": "table_to_delete"
  }
}
```

### 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

Persistent tabular storage for saving, querying, updating, and deleting structured data across workflow executions without external databases.

### Common Patterns

- **CRUD workflow** — create the table (`table` / `create`), insert data (`row` / `insert`), then query it (`row` / `get`).
- **Conditional processing** — use `rowExists` or `rowNotExists` to branch workflow logic based on data presence.
- **Bulk operations** — turn **Optimize Bulk** on when inserting many rows, and **Dry Run** on when testing an update or delete filter.
- **Advanced filtering** — combine several conditions and set **Must Match** to `allConditions` for AND logic or `anyCondition` for OR logic.

### Parameter Dependencies

- **Resource** determines which **Operation** options are available.
- Most row operations need a **Data Table** and support filtering via **Must Match** and **Filter Conditions**.
- Insert, update and upsert use **Column Mapping Mode** to decide how data reaches the columns.
- Get supports pagination (**Return All**, **Limit**) and sorting (**Order By**, **Order By Column**, **Order By Direction**).
- Table operations have their own parameters — **Table Name** when creating, **New Name** when renaming.

### Filter conditions

- Comparison: `eq`, `neq`, `gt`, `gte`, `lt`, `lte`.
- Text: `like` and `ilike` (case-insensitive).
- Presence and boolean: `isEmpty`, `isNotEmpty`, `isTrue`, `isFalse` — these take no `keyValue`.