> ## Documentation Index
> Fetch the complete documentation index at: https://ngquct-feat-cloudflare-r2-sql.mintlify.site/llms.txt
> Use this file to discover all available pages before exploring further.

# Table Structure

> Browse and edit columns, indexes, foreign keys, triggers, and DDL with a visual structure editor

Browse and edit columns, indexes, foreign keys, triggers, and DDL for any table.

<Frame caption="Table structure view">
  <img className="block dark:hidden" src="https://mintcdn.com/ngquct-feat-cloudflare-r2-sql/wtMckuN2hfshdEnb/images/table-structure.png?fit=max&auto=format&n=wtMckuN2hfshdEnb&q=85&s=668375d66673af8dd7603e19d8a57ce3" alt="Table Structure" width="1560" height="960" data-path="images/table-structure.png" />

  <img className="hidden dark:block" src="https://mintcdn.com/ngquct-feat-cloudflare-r2-sql/wtMckuN2hfshdEnb/images/table-structure-dark.png?fit=max&auto=format&n=wtMckuN2hfshdEnb&q=85&s=69549260dea14273691ea92c00356cf2" alt="Table Structure" width="1560" height="960" data-path="images/table-structure-dark.png" />
</Frame>

Open a table, then pick **Structure** in the Data / Structure / JSON control at the bottom of the tab. Or right-click a table in the sidebar and choose **Show Structure**.

Tabs: **Columns**, **Indexes**, **Foreign Keys**, **Triggers**, **DDL**, and **Parts** (ClickHouse only). The Columns, Indexes, Foreign Keys, and Triggers labels show item counts. Tabs the database cannot support are hidden, such as Foreign Keys on ClickHouse or Triggers on Redshift. A filter field above the grid narrows rows by name; click a column header to sort.

## Columns Tab

Columns are edited inline in the grid:

* **Nullable**, **Primary Key**, and **Auto Inc** are YES/NO dropdowns.
* Setting **Primary Key** to YES sets **Nullable** to NO. A primary key column cannot hold NULL, so Nullable stays NO until you turn the primary key off.
* **Type** opens a picker with the database's types grouped by category. Search to filter, or type a parametric value such as `VARCHAR(255)` or `DECIMAL(10,2)` and press Return to use it as written.
* **Charset** and **Collation** columns appear for MySQL and MariaDB.
* **On Update** appears for MySQL and MariaDB, next to **Default**. Set it to YES on a `TIMESTAMP` or `DATETIME` column to add `ON UPDATE CURRENT_TIMESTAMP`, so the column re-stamps itself on every write. TablePro matches the fractional-second precision to the column's own type, so a `TIMESTAMP(6)` column gets `ON UPDATE CURRENT_TIMESTAMP(6)`.

<Frame caption="Type picker popover">
  <img className="block dark:hidden" src="https://mintcdn.com/ngquct-feat-cloudflare-r2-sql/wtMckuN2hfshdEnb/images/structure-type-picker.png?fit=max&auto=format&n=wtMckuN2hfshdEnb&q=85&s=23f2370b5db2a7531d2c9e31909b8f40" alt="Type picker popover" width="1560" height="960" data-path="images/structure-type-picker.png" />

  <img className="hidden dark:block" src="https://mintcdn.com/ngquct-feat-cloudflare-r2-sql/wtMckuN2hfshdEnb/images/structure-type-picker-dark.png?fit=max&auto=format&n=wtMckuN2hfshdEnb&q=85&s=b158b53328733bf434c65d7e4772574c" alt="Type picker popover" width="1560" height="960" data-path="images/structure-type-picker-dark.png" />
</Frame>

Add a column with the **Add Column** button in the status bar or `Cmd+Shift+N`. Select rows and click **Remove Column** or press `Delete` to mark them for removal.

### Primary Keys

Toggle the **Primary Key** flag on one or more columns; multiple flagged columns produce a composite key in a single `PRIMARY KEY (col1, col2)` clause. Changing the key on an existing table runs a drop-and-add sequence on MySQL, MariaDB, PostgreSQL, PGlite, SQL Server, DuckDB, and Snowflake. Other engines, SQLite, ClickHouse, Cassandra, ScyllaDB, and Oracle among them, cannot alter a primary key in place: the dropdown stays editable but the change generates no SQL.

### Reordering Columns

Drag a column row to a new position (MySQL and MariaDB only). The reorder executes immediately as `ALTER TABLE ... MODIFY COLUMN ... AFTER` and is recorded in query history. Dragging is disabled while unsaved structure changes exist.

## Indexes Tab

| Field         | Description                                                                                                            |
| ------------- | ---------------------------------------------------------------------------------------------------------------------- |
| **Columns**   | Indexed columns. Multi-column indexes list several columns in one row. MySQL prefix lengths are written as `email(20)` |
| **Type**      | BTREE, HASH, FULLTEXT, SPATIAL (MySQL), GIN, GIST, BRIN (PostgreSQL)                                                   |
| **Unique**    | Whether the index enforces uniqueness                                                                                  |
| **Condition** | `WHERE` predicate for partial indexes (PostgreSQL)                                                                     |

## Foreign Keys Tab

| Field                       | Description                                                    |
| --------------------------- | -------------------------------------------------------------- |
| **Columns**                 | Local column(s)                                                |
| **Ref Table / Ref Columns** | Referenced table and column(s)                                 |
| **Ref Schema**              | Referenced schema, for cross-schema references                 |
| **On Delete / On Update**   | Dropdowns: NO ACTION, RESTRICT, CASCADE, SET NULL, SET DEFAULT |

Right-click a foreign key and choose **Open \[table]** to jump to the referenced table.

## Saving Changes

Structure edits queue locally; nothing runs until you save. See [Change Tracking](/features/change-tracking) for how the queue, undo (`Cmd+Z`), and redo (`Cmd+Shift+Z`) work. Saving runs on the tab's own connection, database, and schema, the ones it was opened on. It never moves the sidebar's selected database or the toolbar.

* **Save Changes** (`Cmd+S` or the toolbar checkmark) applies the queued changes. Changes that can lose data (dropping a column, changing a type, adding NOT NULL, changing the primary key) first show a confirmation that lists each risky change.
* **Preview SQL** (`Cmd+Shift+P`) shows the generated DDL statements without executing them.

<Frame caption="Generated DDL preview">
  <img className="block dark:hidden" src="https://mintcdn.com/ngquct-feat-cloudflare-r2-sql/wtMckuN2hfshdEnb/images/schema-change-preview.png?fit=max&auto=format&n=wtMckuN2hfshdEnb&q=85&s=17cc328dabaa9c864f56924d58b41768" alt="Schema change preview with ALTER TABLE statements" width="1560" height="960" data-path="images/schema-change-preview.png" />

  <img className="hidden dark:block" src="https://mintcdn.com/ngquct-feat-cloudflare-r2-sql/wtMckuN2hfshdEnb/images/schema-change-preview-dark.png?fit=max&auto=format&n=wtMckuN2hfshdEnb&q=85&s=dce413f54169b42fef4bf3fc1bb1c2d6" alt="Schema change preview with ALTER TABLE statements" width="1560" height="960" data-path="images/schema-change-preview-dark.png" />
</Frame>

### Row Context Menu

Right-click rows in the Columns, Indexes, or Foreign Keys tabs for **Copy Name**, **Copy Definition**, **Copy As** (CSV, JSON, SQL), **Duplicate** (`Cmd+D`), and **Delete**. Rows already marked for deletion offer **Undo Delete** instead. Multi-select to act on several rows at once.

## Triggers Tab

Lists the table's triggers with **Name**, **Timing** (BEFORE, AFTER, INSTEAD OF), **Event** (INSERT, UPDATE, DELETE), and **Enabled** where the database reports it. Select a trigger to see its full `CREATE TRIGGER` statement, fetched from the engine's catalog, in a syntax-highlighted viewer with **Copy** and **Open in Editor**.

**New Trigger**, **Edit**, and **Delete** in the tab's toolbar manage triggers. The editor opens the trigger's actual DDL so the whole definition round-trips; for PostgreSQL it includes the trigger function so you can edit the logic. Saving runs the right statements for the engine, wrapped in a transaction where the engine supports transactional DDL. Deleting asks for confirmation.

<Note>
  Triggers are available for MySQL, MariaDB, PostgreSQL, SQLite, SQL Server, Oracle, libSQL, and Cloudflare D1; the tab is hidden elsewhere. Oracle does not return the trigger body, so editing starts from the trigger header.
</Note>

## DDL Tab

Read-only `CREATE TABLE` statement with syntax highlighting and font size controls. Toolbar buttons: **Copy**, **Export** as a `.sql` file, and **Open in Editor** to send the DDL to a new query tab.

## Parts Tab (ClickHouse)

Lists the table's partitions and parts from `system.parts`. Toolbar actions: **Optimize** (merge parts), **Drop Partition**, and **Detach Partition** for the selected partition.

## Creating a New Table

Click the **+** button at the bottom of the sidebar and choose **New Table**. The editor opens as a tab with:

* **Table Name** field, plus Engine, Charset, and Collation pickers for MySQL and MariaDB
* **Columns**, **Indexes**, and **Foreign Keys** tabs using the same grid editing as the structure view
* **SQL Preview** tab with the live-generated `CREATE TABLE` DDL

Click **Create Table** (`Cmd+Return` or `Cmd+S`) to execute. TablePro opens the new table and refreshes the sidebar.

<Note>
  Visual table creation is supported for MySQL, MariaDB, PostgreSQL, PGlite, SQLite, SQL Server, ClickHouse, DuckDB, Oracle, Snowflake, libSQL, Cloudflare D1, Trino, and Teradata.
</Note>

## Limitations

TablePro disables operations the database cannot perform:

* **SQLite**: columns can be renamed but not otherwise modified.
* **Cassandra / ScyllaDB**: add and drop column only; no index editing.
* **Redshift, CockroachDB, Cloudflare D1, Beancount**: structure is read-only.
* **Redis, etcd, DynamoDB**: no table schema to edit.

## MongoDB Collections

MongoDB structure is read-only. TablePro infers the schema from the first 50 documents of the collection: it unions the top-level field names across the sample and picks each field's most common BSON type. `_id` is listed first and marked as the primary key. The DDL tab shows indexes as `createIndex()` commands you can run in `mongosh`, plus the collection's validator and capped-collection options when present. Edit documents in the data grid instead.

## Refreshing

Use **Query > Refresh** (`Cmd+R`) or the toolbar refresh button to reload structure from the database. Changes made through TablePro refresh automatically. Refresh always reads from the tab's own database and schema, not the sidebar's current selection.
