Skip to main content
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.
Table StructureTable Structure

Table structure view

Open a table and switch the result view to Structure, or right-click it in the sidebar and choose Show Structure. The tabs are Properties, Columns, Indexes, Foreign Keys, Constraints, Triggers, DDL, and Parts (ClickHouse only); Columns through Triggers carry item counts. A tab the engine has no concept of is hidden: ClickHouse has no Foreign Keys, Redshift no Triggers, Redis no Constraints. Every grid has a filter field, and clicking a header sorts.

Properties tab

The table’s own row in the catalog: name, schema, size on disk, row count, and the comment. What sits between them is the driver’s choice, so PostgreSQL names an owner, a tablespace and a persistence where MySQL names a row format and the next auto-increment value.
A grouped form listing name, schema, owner and tablespace above a comment field holding several lines of JSONA grouped form listing name, schema, owner and tablespace above a comment field holding several lines of JSON

Properties tab on a PostgreSQL table

Comment is the only editable field. It scrolls rather than clipping, so a long one reads and edits in place. An edit queues with the rest of the structure changes and reaches the server on Save Changes.
Comment editing is available for MySQL, MariaDB, PostgreSQL and PGlite, and on those engines for an ordinary or partitioned table. Everywhere else, and on a view, a materialized view or a foreign table, the comment is read-only.

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).

Generated columns

PostgreSQL, CockroachDB, PGlite, MySQL, MariaDB and SQLite add two more fields. Generated is a menu of Not generated, STORED and VIRTUAL; Expression holds the SQL the value is computed from. Set both on a new row and the column is created as GENERATED ALWAYS AS (expression). The keyword is always written out. PostgreSQL 17 and earlier accept STORED only, PostgreSQL 18 made VIRTUAL the default, and MySQL and MariaDB default to VIRTUAL, so leaving it implicit would mean different columns on different servers.
A column row with Generated set to VIRTUAL and an Expression beside itA column row with Generated set to VIRTUAL and an Expression beside it

Generated column fields on the Columns tab

Two limits apply to a column that already exists. Switching Generated on it is refused by every engine: drop the column and add it back to make it generated, which discards its data. On SQLite, a column added to a populated table is VIRTUAL; ALTER TABLE refuses cannot add a STORED column there, so STORED is reachable only when the table is created.
Type picker popoverType picker popover

Type picker popover

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

Foreign keys tab

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.

Constraints tab

Check constraints are table-level, so a rule spanning two columns is one row here rather than something hidden on a column.
Two check constraints, one of them spanning two columnsTwo check constraints, one of them spanning two columns

Constraints tab

Columns is filled from the catalog on PostgreSQL and SQL Server. MySQL, MariaDB and SQLite publish no such catalog, so the cell stays empty there. Renaming a constraint runs a single RENAME CONSTRAINT where the engine has one. Changing the expression drops and re-adds it, because no engine can alter a check in place. Both the re-add and a brand-new constraint scan every existing row and fail if any row violates the rule, so a failed save means the data disagrees with the constraint. The tab is hidden on engines with no check constraints. SQL Server lists and edits them, but has computed columns rather than generated ones, so it gets this tab and not the two column fields. SQLite is the one engine where listing and editing part company. The tab appears on every version, but + and - need SQLite 3.53.0 or later, the release that added ADD CONSTRAINT and DROP CONSTRAINT to ALTER TABLE. The driver links the system SQLite, so the version is the one macOS ships. On an older one the constraints still list, read-only.

Saving changes

Nothing here reaches the server on its own. 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 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.
Schema change preview with ALTER TABLE statementsSchema change preview with ALTER TABLE statements

Generated DDL preview

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

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.
Visual table creation is supported for MySQL, MariaDB, PostgreSQL, PGlite, SQLite, SQL Server, ClickHouse, DuckDB, Oracle, Snowflake, libSQL, Cloudflare D1, Trino, Teradata, and Dameng.

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.
  • A view, a materialized view or a foreign table keeps a read-only comment on the Properties tab. Each takes its own COMMENT ON keyword: run it in the editor.
  • Renaming a table is not on the Properties tab. It happens in the sidebar row: see Table Operations.
  • 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.