# Table view

Source: https://laraport.app/docs/table-view/

> Browse database tables and query results as a grid, sort, filter with WHERE, export to CSV or JSON, and edit rows with the SQL shown before it runs.

Browsed tables and the results of your `SELECT` queries are shown as a table.

*Screen: The orders table of the app’s PostgreSQL database*

## Moving around

| Key | Action |
|---|---|
| arrows or `h` `j` `k` `l` | Move the cell cursor |
| `0` / `$` | First / last column |
| `g` / `G` | First / last row |
| `enter` | The whole row as column and value pairs |
| `y` | Copy the cell |
| `n` / `p` | Next / previous page of 100 rows |
| `s` | Sort by the current column: ascending, descending, none |
| `/` | Set a `WHERE` filter |
| `i` | The table's structure: columns, types, defaults, keys and foreign keys |
| `x` / `X` | Export the loaded rows as CSV / JSON |
| `r` | Reload |

Sorting and filtering run in the database. Wide results scroll sideways. `y` copies through the terminal; if nothing is copied, see [Troubleshooting](https://laraport.app/docs/troubleshooting/#copying-does-nothing).

## Values

- Numbers are right-aligned, and `NULL` looks different from an empty string.
- Newlines show as `↵`.
- Emoji and other characters whose width differs between terminals show as `◇`, so the columns stay aligned.
- Values are read in a structured format (`psql --csv`, `mysql --xml`, `sqlite3 -csv`), so commas, quotes, newlines and Unicode come through intact.

## Queries

A single `SELECT`, `WITH` or `VALUES` statement is wrapped in a `LIMIT`, so a huge result is never transferred: the first 500 rows are shown. Other statements show their text output.

## Editing

Tables with a primary key can be edited.

| Key | Action |
|---|---|
| `e` | Edit the cell. Multi-line values work; `ctrl+n` sets NULL, `ctrl+s` saves |
| `a` | Add a row: a form with every column, its type and default |
| `D` | Delete the row |

- Every change shows its SQL, for example `UPDATE "users" SET "name" = 'Bob' WHERE "id" = '2'`, and runs only after you confirm. **Cancel** is focused.
- Rows are addressed by their whole primary key. "0 rows" means the row was gone or its key had changed.
- No value can break the statement, whatever it contains: the statement that runs uses PostgreSQL dollar quoting with a random tag, a MySQL hex literal or an escaped SQLite string.
- Tables without a primary key, query results and views are read-only.

When the app runs with `APP_ENV=production`, the table view says **PRODUCTION**, and editing has to be switched on once per table, after a warning.
