Reference · Tools
Data Table
Permanently save, retrieve, update, and delete structured data across workflow executions in built-in tables
Data Table gives your workflows a built-in database — typed columns, automatic system fields, and full CRUD operations without connecting to any external service. Use it to track form submissions across runs, maintain a running list of processed records, or gate workflow logic on whether a row already exists.
- Node type
- Action
- Parameters
- 26
- Outputs
- Output, Error
- Credentials
- None required
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:
{
"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:
{
"type": "data_table",
"parameters": {
"resource": "row",
"operation": "insert",
"dataTableId": "users_table",
"columnsMappingMode": "autoMapInputData"
}
}
Insert a row with values you set explicitly:
{
"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:
{
"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:
{
"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:
{
"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:
{
"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:
{
"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”:
{
"type": "data_table",
"parameters": {
"resource": "table",
"operation": "list",
"returnAll": false,
"limit": 20,
"filterName": "user",
"sortField": "name",
"sortDirection": "asc"
}
}
Rename a table:
{
"type": "data_table",
"parameters": {
"resource": "table",
"operation": "update",
"dataTableId": "old_table_name",
"newName": "new_table_name"
}
}
Delete a table:
{
"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
rowExistsorrowNotExiststo 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
allConditionsfor AND logic oranyConditionfor 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:
likeandilike(case-insensitive). - Presence and boolean:
isEmpty,isNotEmpty,isTrue,isFalse— these take nokeyValue.
Frequently asked questions
Do I need to connect any credentials or external database to use Data Table?
No. Data Table is entirely internal to the platform — no credentials, API keys, or external database connections are required. Storage is managed by BusyBot itself, so you can start inserting rows immediately after creating a table with the Table → Create operation.
What order do I need to set up a table before I can insert rows?
You must create the table first using the Table resource with the Create operation, providing a Table Name. Only after the table exists can you use row operations like Insert, Get, Update, or Delete against it. Skipping this step will cause subsequent row operations to fail.
What are 'rowExists' and 'rowNotExists' operations actually for?
These operations let you branch your workflow based on whether matching rows are found. Instead of returning row data, they route execution to the Output path if the condition is met or the Error path if it isn't — so you can, for example, skip processing a record you've already stored, or trigger an alert when expected data is missing.
When should I turn on 'Optimize Bulk' for inserts, and what does 'Dry Run' do?
Enable Optimize Bulk whenever you're inserting a large number of rows at once — it batches the writes for better performance. Dry Run is useful during development for Update and Delete operations: it evaluates your filter conditions and shows you which rows would be affected without actually modifying any data.
How do I write a filter that matches rows meeting multiple conditions at the same time?
Add multiple Filter Conditions and set Must Match to 'allConditions' for AND logic (every condition must be true) or 'anyCondition' for OR logic (at least one must be true). Available comparisons include eq, neq, gt, gte, lt, lte, like, ilike, isEmpty, isNotEmpty, isTrue, and isFalse — note that the presence and boolean operators (isEmpty, isTrue, etc.) do not take a value, just a column name.
Build with the Data Table node
Drop it into a workflow, wire it to an agent, or call it on a schedule.
Open BusyBotLast updated . Spotted something wrong? Tell us.