# Work with tables
Every table in Nexus has a page showing its rows, its columns and every change made to it.
## Before you start [#before-you-start]
- You see the tables you have access to. Owners and admins see them all.
- Editing rows needs access to change the table's data. If an action is refused, ask an owner or admin. See [Data access](/docs/data/data-access).
- Some tables are kept by Klarety itself. Their page says **Klarety keeps this table itself, so it cannot be changed**.
## Find a table [#find-a-table]
Go to and open **Nexus Lakehouse**. The list shows each table's **Name**, **Schema** and number of **Columns**; type in **Find a table** to narrow it. A table's page has three tabs: **Data**, **Columns** and **History**.
The menu beside a table also offers **Query in SQL editor** or copying its name.
```python title="find_tables.py"
from klarety import Nexus
with Nexus.connect() as nx:
for table in nx.tables.list("default", search="order"):
print(table)
about = nx.tables.describe("orders", schema="default")
print(about)
```
`tables.list()` reads every page of results. `made_by="org"` keeps the tables made outside any project, and `made_by="system"` the ones Klarety keeps.
## Browse and filter rows [#browse-and-filter-rows]
The **Data** tab shows the rows. A large table shows only its first rows, and says so.
Select **Filter rows**, pick a **Column**, a **Condition** and a **Value**, then **Apply**. The conditions are **is**, **is not**, **contains**, **more than**, **less than**, **is empty** and **is not empty**. Each filter is a removable chip; **Clear** removes them all.
`tables.rows()` reads every row, a page at a time. Each filter is written `column:op:value`:
```python title="read_rows.py"
from klarety import Nexus
with Nexus.connect() as nx:
for row in nx.tables.rows(
"orders",
where=["country:eq:CO"],
order_by="ordered_at",
descending=True,
):
print(row)
```
To fetch many rows by key in one read, use `in`: `where=["order_id:in:1,2,3"]`.
## Edit rows by hand [#edit-rows-by-hand]
For many rows, load a file with **Update rows by key** instead (see [Add data](/docs/data/add-data)).
### Change what you need [#change-what-you-need]
On the **Data** tab, edit a cell, select **Add a row**, or select rows and choose **Delete**.
### Review the changes [#review-the-changes]
The bar at the bottom counts your pending changes. Select **Discard** to drop them.
### Save [#save]
Select **Save**. All changes are saved together as one new version.
```python title="edit_rows.py"
from klarety import Nexus
from klarety.errors import ConflictError
with Nexus.connect() as nx:
try:
nx.tables.edit_rows(
"orders",
updated=[{"row": {"order_id": 3}, "values": {"amount": "75.00"}}],
added=[{"order_id": 9, "customer": "LucĂa", "country": "CO", "amount": "40.00"}],
deleted=[{"order_id": 7}],
)
except ConflictError as changed:
print("Someone changed these rows first:", changed)
```
Values are given as text. One call takes at most 500 changes, all saved together. Each value in `row` must still match what is stored, or nothing is saved and `ConflictError` names each changed row: read again, then retry. After a timeout, resend with the same `write_id`; it is never applied twice.
## Describe columns [#describe-columns]
The **Columns** tab lists every column with its type. A column that identifies a row is marked **key**, and **Linked tables** shows which columns match columns in other tables. **Add description** writes one line about a column, shown to everyone who reads the table.
```python
nx.tables.set_column_doc("orders", "amount", "Order total in Colombian pesos, tax included")
```
An empty description clears it.
## Add data checks [#add-data-checks]
A data check is a rule each loaded row must meet. Failing rows are set aside and the rest load, so a bad export cannot fill a table with broken rows.
| Rule in the app | `rule` in code | Example |
| --- | --- | --- |
| **is never empty** | `not_null` | `customer` is never empty |
| **is between** | `range` | `amount` is between 0 and 10000000 |
| **matches the pattern** | `pattern` | `country` matches the pattern `^[A-Z]{2}$` |
| **is one of** | `one_of` | `status` is one of `paid, refunded` |
### Open the checks [#open-the-checks]
On the table's page, open **More** and choose **Data checks**.
### Add a check [#add-a-check]
Choose a **Column** and a **Rule**, fill in the values, and select **Add check**.
### Read the results [#read-the-results]
The panel shows how many rows recent loads wrote and set aside. **Remove** drops a check.
`tables.expect()` replaces the table's checks with the list you send. An empty list removes them all.
```python title="data_checks.py"
from klarety import Nexus
with Nexus.connect() as nx:
nx.tables.expect(
"orders",
[
{"column": "customer", "rule": "not_null"},
{"column": "amount", "rule": "range", "minimum": 0},
{"column": "status", "rule": "one_of", "values": ["paid", "refunded"]},
],
)
print(nx.tables.quality("orders"))
```
A write that breaks a rule raises `TableRuleError`, naming the rule. Fix the data rather than resending it unchanged.
## See the history [#see-the-history]
The **History** tab lists every version, newest first: how many rows were added or that rows were updated, the total row count, who made the change (**You**, **A teammate**, **Studio** or **An API key**) and how it came in (**via SDK**, **via agent**, **from a Studio** or **auto import**). Select **Show older** to go further back.
To undo, select **Go back to this** on a version.
Every change after that version is undone, including other people's. To undo only one source's changes, use **Put back** in [Undo and restore](/docs/data/undo-and-restore).
```python
history = nx.tables.snapshots("orders")
authors = nx.tables.authors("orders", days=7)
```
`snapshots()` lists the table's versions; `authors()` shows who added and changed rows, day by day.
## Delete a table [#delete-a-table]
Open **More** and choose **Delete table**. You can restore it for a while after.
```python
nx.tables.delete("orders_old")
print(nx.tables.deleted())
nx.tables.restore("orders_old")
```
A deleted table can be restored for as long as your plan keeps deleted items.
## Where to go next [#where-to-go-next]
- [Query with SQL](/docs/data/sql-editor): question a table with Spark SQL.
- [Undo and restore](/docs/data/undo-and-restore): go back to an earlier version.
- [Knowledge graph](/docs/data/knowledge-graph): see how your tables link.