> ## Documentation Index
> Fetch the complete documentation index at: https://ngquct-fix-disconnected-workspace-navigation.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

export const what_0 = "Column, index and key changes"

This is a DDL editor with a grid in front of it. Rename a column, add an index, change a key, and what you get is a pending `ALTER TABLE` you can read before it runs; the table on the server is untouched until you apply it.

<Frame caption="Table structure view">
  <img className="block dark:hidden" src="https://mintcdn.com/ngquct-fix-disconnected-workspace-navigation/03NGRqPEJYVINQ2c/images/table-structure.png?fit=max&auto=format&n=03NGRqPEJYVINQ2c&q=85&s=ab1ee0e2926927337617035be5342a3b" alt="Table Structure" width="1560" height="960" data-path="images/table-structure.png" />

  <img className="hidden dark:block" src="https://mintcdn.com/ngquct-fix-disconnected-workspace-navigation/03NGRqPEJYVINQ2c/images/table-structure-dark.png?fit=max&auto=format&n=03NGRqPEJYVINQ2c&q=85&s=35baa82a478f02b39d56f2be4bb64c7f" alt="Table Structure" width="1560" height="960" data-path="images/table-structure-dark.png" />
</Frame>

Open a table and switch the result view to **Structure**, or right-click it in the sidebar and choose **Show Structure**.

The tabs are **Columns**, **Indexes**, **Foreign Keys**, **Triggers**, **DDL**, and **Parts** (ClickHouse only); the first four carry item counts. A tab the engine has no concept of is hidden: ClickHouse has no Foreign Keys, Redshift no Triggers. Every grid has a filter field, and clicking a header sorts.

## Columns tab

Columns are edited in place. **Nullable**, **Primary Key**, and **Auto Inc** are YES/NO dropdowns; **Primary Key** set to YES forces **Nullable** to NO and holds it there until the key comes back off. **Type** opens a picker of the engine's types by category: search to filter, or type a parametric value such as `VARCHAR(255)` and press Return to use it as written.

Which remaining columns appear is the driver's choice. **Comment** is there on most engines and writes the column comment. MySQL and MariaDB add **Charset**, **Collation**, and **On Update**; **On Update** set to YES on a `TIMESTAMP` or `DATETIME` column adds `ON UPDATE CURRENT_TIMESTAMP` at that column's own precision, so `TIMESTAMP(6)` gets `ON UPDATE CURRENT_TIMESTAMP(6)`.

<Frame caption="Type picker popover">
  <img className="block dark:hidden" src="https://mintcdn.com/ngquct-fix-disconnected-workspace-navigation/03NGRqPEJYVINQ2c/images/structure-type-picker.png?fit=max&auto=format&n=03NGRqPEJYVINQ2c&q=85&s=73263bd1d29f76bb22072f79b2b2f830" 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-fix-disconnected-workspace-navigation/03NGRqPEJYVINQ2c/images/structure-type-picker-dark.png?fit=max&auto=format&n=03NGRqPEJYVINQ2c&q=85&s=544124c97b815294c0489ffe35a0fc74" alt="Type picker popover" width="1560" height="960" data-path="images/structure-type-picker-dark.png" />
</Frame>

Add a column with **+** at the right of the status bar or `Cmd+Shift+N`. Select rows and click **-** or press `Delete` to mark them for removal.

Flag **Primary Key** on one column, or several for a composite key in one `PRIMARY KEY (col1, col2)` clause. On an existing table that becomes a drop of the old constraint followed by an add.

Drag a column row to reorder it (MySQL and MariaDB only). That one runs immediately as `ALTER TABLE … MODIFY COLUMN … AFTER` and goes to query history rather than the queue. Dragging is off while unsaved 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. Right-click any row in these three grids for **Copy Name**, **Copy Definition**, **Copy As** (CSV, JSON, SQL), **Duplicate** (`Cmd+D`), and **Delete**. A row already marked for deletion offers **Undo Delete**.

## Saving changes

Nothing here reaches the server on its own. {what_0} queue on the tab, the toolbar counts them,
**Preview SQL** (`Cmd+Shift+P`) shows the statements they will produce, and `Cmd+S` runs them.

[Change Tracking](/features/change-tracking) covers the queue, undo (`Cmd+Z`) and redo (`Cmd+Shift+Z`). A save runs on the tab's own connection, database, and schema, the ones it was opened on, and never moves the sidebar or the toolbar.

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

The queue outlives everything short of an explicit discard: closing the tab, closing the window, quitting, and **Refresh** all ask first. A save that never reaches the server leaves the tab open with its queue intact.

<Frame caption="Generated DDL preview">
  <img className="block dark:hidden" src="https://mintcdn.com/ngquct-fix-disconnected-workspace-navigation/bkFRiX1X7Rpue5lP/images/schema-change-preview.png?fit=max&auto=format&n=bkFRiX1X7Rpue5lP&q=85&s=9c47d868f28d985c0fa43508750a4ec1" 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-fix-disconnected-workspace-navigation/bkFRiX1X7Rpue5lP/images/schema-change-preview-dark.png?fit=max&auto=format&n=bkFRiX1X7Rpue5lP&q=85&s=f982648193eaea129092e2c9470869e9" alt="Schema change preview with ALTER TABLE statements" width="1560" height="960" data-path="images/schema-change-preview-dark.png" />
</Frame>

### When one statement fails

A save is often several statements, run in order. Engines with transactional DDL roll the whole set back; MySQL, MariaDB, and Oracle commit each one as it runs, so everything before the failure has landed while the queue still holds all of it. An **Error Applying Changes** sheet reports what the server said: refresh before saving again, or the second save replays work the server already did.

## Triggers tab

Lists **Name**, **Timing** (BEFORE, AFTER, INSTEAD OF), **Event** (INSERT, UPDATE, DELETE), and **Enabled** where the engine reports it. Select one to read its `CREATE TRIGGER` statement from the catalog, with **Copy** and **Open in Editor**. **New Trigger**, **Edit**, and **Delete** sit in the action bar; the editor opens the trigger's real DDL, including the trigger function on PostgreSQL.

<Info>
  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 the viewer and the editor start from the trigger header alone.
</Info>

## DDL tab

Read-only `CREATE TABLE` with syntax highlighting and font size controls. **Copy**, **Export** as a `.sql` file, and **Open in Editor** send it onward. On PostgreSQL the `CREATE SEQUENCE` and `CREATE TYPE … AS ENUM` statements the table depends on are prepended, so the script runs on an empty database.

## Parts tab (ClickHouse)

Lists partitions and parts from `system.parts`. **Optimize** merges parts; **Drop Partition** and **Detach Partition** act on the selected partition. Detached data stays on disk and is unreadable until it is re-attached.

## Creating a new table

Choose **Database > New Table…**, or right-click empty space in the sidebar and choose **New Table…**. The tab holds a **Table Name** field (with Engine, Charset, and Collation pickers on MySQL and MariaDB), the same three editing grids, and a **SQL Preview** tab carrying the live `CREATE TABLE`. **Create Table** (`Cmd+Enter` or `Cmd+S`) executes it and opens the new table.

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

## MongoDB collections

MongoDB structure is read-only, and inferred from the collection's first 200 documents: top-level field names are unioned across the sample, and each field takes its most common BSON type. `_id` comes first, marked as the primary key. The DDL tab shows indexes as `createIndex()` commands for `mongosh`, plus the validator and capped-collection options where present.

## Limitations

* **Changing a primary key on an existing table** works on MySQL, MariaDB, PostgreSQL, PGlite, SQL Server, DuckDB, Snowflake, and Dameng. Elsewhere the dropdown accepts the edit and the save produces nothing for it: rebuild the table by hand.
* **Check constraints and generated columns** have no field in the grid. Both show in the DDL tab; change them by running DDL yourself.
* **SQLite**: a column can be added, dropped, and renamed. No other column change generates SQL.
* **Cassandra / ScyllaDB**: add and drop column only, no index editing, no visual table creation.
* **Redshift, CockroachDB, BigQuery, Elasticsearch, SurrealDB, Beancount**: structure is read-only.
* **Redis, etcd, DynamoDB**: no table schema to edit.

## Refreshing

**Database > Refresh** (`Cmd+R`) or the toolbar refresh button reloads structure from the server; changes made through TablePro refresh on their own. A refresh reads the tab's own database and schema, not the sidebar's current selection.
