# Tablas y esquemas
Nexus guarda sus datos en tablas, en el formato abierto Apache Iceberg, agrupadas en esquemas. El esquema `default` siempre existe y se usa salvo que pase `schema=`. Esta página cubre `nexus.tables` y `nexus.schemas`.
## Antes de empezar [#antes-de-empezar]
- Leer tablas requiere acceso de lectura. Crear tablas y cambiar columnas requiere una clave cuyo **Acceso** incluya cambios de esquema.
- Todos los ejemplos suponen `nexus = Nexus.connect()`.
## Esquemas [#esquemas]
```python
for schema in nexus.schemas.list(): # the default schema first
print(schema)
nexus.schemas.create("finance")
print(nexus.schemas.describe("finance"))
nexus.schemas.delete("finance") # only when it holds no tables and no files
```
## Encuentre y describa tablas [#encuentre-y-describa-tablas]
```python
for table in nexus.tables.list(search="order"):
print(table["name"], table["column_count"], table["doc"])
details = nexus.tables.describe("orders")
```
`list()` recorre todas las páginas por usted. Cada entrada tiene `name`, `schema`, `owner`, `doc`, `column_count`, `about`, `made_by` y `mine`. Pase el ID de un proyecto en `made_by=` para filtrar.
## Cree una tabla [#cree-una-tabla]
```python title="create_orders.py"
from klarety import Nexus, RefusedError
with Nexus.connect() as nexus:
try:
created = nexus.tables.create(
"orders",
[
{"name": "order_id", "type": "string", "doc": "Order number."},
{"name": "customer", "type": "string", "doc": "Customer name."},
{"name": "amount", "type": "double", "doc": "Order total in US dollars."},
{"name": "ordered_at", "type": "timestamp", "doc": "When the order was placed."},
],
doc="One row per customer order.",
identifier_columns=["order_id"],
expectations=[{"column": "amount", "rule": "range", "minimum": 0}],
)
except RefusedError as refused:
raise SystemExit(f"Could not create the table: {refused}")
print(created)
```
- `doc` es obligatorio, en la tabla y en cada columna: una línea que diga qué contiene. Una columna también puede definir `"required": True`.
- `identifier_columns` nombra las columnas que identifican una fila (su clave).
- `expectations` son reglas que revisa cada carga; las filas que las incumplen se apartan bajo el nombre de la regla.
- `relationships` (por ejemplo `{"columns": ["customer"], "references": "customers", "referenced_columns": ["id"]}`) ayudan a Nexus a organizar ambas tablas. No se exigen al escribir.
- Nexus elige la organización física y la informa. `cluster_by` sugiere las columnas por las que más filtra; `pin_layout()` evita que cambie a medida que crece la tabla.
Normalmente no necesita `create()`: [cargar un archivo](/docs/es/developers/ingest) crea su tabla.
## Describa qué significa una tabla [#describa-qué-significa-una-tabla]
```python
nexus.tables.describe_meaning(
"orders", grain="one order", time_column="ordered_at", status="ready"
)
nexus.tables.set_column_doc("orders", "amount", "Order total in US dollars, tax included.")
```
`status` es `draft`, `ready` o `deprecated`. Solo cambian los valores que pase. Las personas y la IA leen estas descripciones para entender sus datos.
## Lea filas [#lea-filas]
```python
for row in nexus.tables.rows("orders", where=["customer:eq:Acme"], order_by="ordered_at"):
print(row)
```
`rows()` pagina a medida que recorre. Un filtro `where` es `columna:op:valor`, donde `op` es `eq`, `ne`, `gt`, `ge`, `lt`, `le`, `in`, `contains`, `is_null` o `not_null`. Para traer muchas filas por clave en una lectura, use `in`: `"order_id:in:A1,A2,A3"`. Para algo más, use [SQL](/docs/es/developers/sql).
## Edite unas pocas filas [#edite-unas-pocas-filas]
`edit_rows()` agrega, actualiza y borra hasta 500 filas en un solo commit:
```python
from klarety import ConflictError
try:
nexus.tables.edit_rows(
"orders",
added=[{"order_id": "A9", "customer": "Acme", "amount": "120.00"}],
updated=[{"row": {"order_id": "A1", "amount": "80.00"}, "values": {"amount": "85.00"}}],
write_id="fix-a1-2026-11-10",
)
except ConflictError as changed:
print("A row changed since you read it:", changed)
```
- En `updated`, `row` es la fila como usted la leyó y `values` los valores nuevos, escritos como texto. Si algún valor de `row` ya no coincide con lo guardado, no se guarda nada y `ConflictError` nombra cada fila que cambió.
- `write_id` nombra la escritura (de 8 a 64 letras, dígitos, `-` o `_`). Tras un tiempo de espera agotado, reenvíe con el mismo `write_id`: una escritura que ya llegó se responde como guardada, nunca se hace dos veces.
- Para más de 500 filas, cargue un archivo con `mode="upsert"`.
## Cambie columnas [#cambie-columnas]
```python
nexus.tables.add_column("orders", {"name": "channel", "type": "string", "doc": "Where the order came from."})
nexus.tables.change_columns("orders", rename={"channel": "sales_channel"}, retype={"amount": "decimal(12,2)"})
nexus.tables.change_columns("orders", remove=["sales_channel"])
nexus.tables.restore_column("orders", "sales_channel")
```
Todos los cambios de una llamada a `change_columns()` ocurren juntos. Una columna eliminada se conserva hasta que se purga, así que `restore_column()` puede traerla de vuelta.
## Historial, reversión y restauración [#historial-reversión-y-restauración]
Cada cambio crea una instantánea de la tabla.
```python
history = nexus.tables.snapshots("orders")
nexus.tables.rollback("orders", snapshot_id=1234567890)
new_rows = nexus.tables.changes("orders", since=0) # pass back "through" next time
```
`delete()` elimina una tabla, que sigue restaurable durante el periodo de recuperación de su plan:
```python
nexus.tables.delete("orders")
print(nexus.tables.deleted())
nexus.tables.restore("orders")
```
`nexus.tables.erase("orders", "customer = 'Acme'")` elimina los bytes de las filas que coinciden, no solo las filas, y devuelve un comprobante. No se puede deshacer: una reversión a antes del borrado se rechaza, así que las filas borradas nunca vuelven.
## Revise calidad y actividad [#revise-calidad-y-actividad]
```python
print(nexus.tables.quality("orders"))
print(nexus.tables.authors("orders", days=7)) # who added and changed rows, day by day
print(nexus.tables.lineage("orders"))
```
## Qué puede salir mal [#qué-puede-salir-mal]
| Excepción | Causa | Qué hacer |
| --- | --- | --- |
| `NotFoundError` | No existe esa tabla en este esquema, o no puede llegar a ella. | Revise el nombre y `schema=`. |
| `RefusedError` | Su clave no puede hacer este cambio. | Use una clave con acceso a cambios de esquema. |
| `ConflictError` | Una fila cambió desde que la leyó, o la tabla está cambiando. | Lea de nuevo y reintente. |
| `TableRuleError` | El cambio incumple una regla de la tabla; el mensaje la nombra. | Corrija el cambio; nunca lo reenvíe igual. |
## Próximos pasos [#próximos-pasos]
- [Cargar datos](/docs/es/developers/ingest) para llenar tablas desde archivos.
- [Ejecutar SQL](/docs/es/developers/sql) para consultarlas.
- [Trabajos y trabajos por lotes](/docs/es/developers/jobs) para cambiar muchas filas con SQL.