# Ejecutar SQL
`nexus.sql()` ejecuta una sentencia de Spark SQL en Nexus y espera la respuesta. En la app, las mismas consultas se ejecutan en . Para scripts largos o procesamiento pesado, vea [Sesiones de Spark](/docs/es/developers/spark) y [Trabajos](/docs/es/developers/jobs).
## Antes de empezar [#antes-de-empezar]
- El SDK está instalado y usted puede conectarse ([Inicio rápido del SDK](/docs/es/developers)).
- El **Acceso** de su clave permite lo que hace la sentencia. Una clave de solo lectura solo puede leer.
- El espacio de trabajo tiene créditos.
## Ejecute una consulta [#ejecute-una-consulta]
```python title="top_customers.py"
from klarety import Nexus, RefusedError, ServiceError
with Nexus.connect() as nexus:
try:
result = nexus.sql(
"SELECT customer, SUM(amount) AS total "
"FROM orders GROUP BY customer ORDER BY total DESC",
max_rows=10,
)
except RefusedError as refused:
raise SystemExit(f"Query refused: {refused}")
except ServiceError as failed:
raise SystemExit(f"Nexus could not answer, try again: {failed}")
for row in result.rows:
print(row["customer"], row["total"])
print(f"Read {result.bytes_scanned} bytes")
```
Las tablas sin nombre de esquema se leen de `default`. Nombre otro esquema como `esquema.tabla`.
### Qué se devuelve [#qué-se-devuelve]
`sql()` devuelve un `ResultSet`:
| Campo | Significado |
| --- | --- |
| `rows` | Las filas, cada una un diccionario por nombre de columna. `len(result)` es el número de filas. |
| `bytes_scanned` | Cuántos datos leyó la sentencia. |
| `truncated` | `True` cuando la sentencia produjo más filas de las devueltas. |
| `result_id` | Se define cuando el resto del resultado se guardó aparte para leerlo página por página. |
| `pages` | Cuántas páginas se guardaron aparte. |
| `result_truncated` | `True` cuando incluso el resultado guardado superó el tamaño de su plan, así que solo se guarda la primera parte. |
Dos tipos de valor requieren cuidado:
- Un número entero mayor que 253 llega como texto, para que ningún lector JSON lo redondee. Conviértalo con `int()`.
- Un valor `timestamptz` llega en UTC sin desplazamiento escrito. Agregue `Z` antes de que lo lea un analizador estricto.
## Pase valores con parámetros [#pase-valores-con-parámetros]
Nunca una la entrada del usuario al SQL. Use `params`: cada `:nombre` se llena como **literal de texto**, nunca se lee como SQL.
```python
result = nexus.sql(
"SELECT * FROM orders WHERE customer = :customer AND amount > CAST(:minimum AS DOUBLE)",
params={"customer": "Acme", "minimum": "100"},
)
```
Cada valor es texto; use `CAST` para números y fechas en el SQL, como arriba. Un nombre de parámetro empieza con una letra o guion bajo y tiene hasta 64 letras, dígitos o guiones bajos; una sentencia acepta hasta 256 parámetros.
## Controle cuántas filas se devuelven [#controle-cuántas-filas-se-devuelven]
`max_rows` limita las filas devueltas: de 1 a 10.000, 1.000 por defecto, nunca más que la página de filas de su plan. Si hay más, `truncated` es `True`.
## Lea un resultado grande [#lea-un-resultado-grande]
Cuando un resultado no cabe en una respuesta, Nexus guarda el resto un día y define `result_id`. `nexus.result_rows(result)` lee todas las filas página por página, sin cargarlo todo en memoria:
```python
result = nexus.sql("SELECT * FROM events WHERE day = '2026-11-01'")
if result.truncated:
count = 0
for row in nexus.result_rows(result):
count += 1
print(f"{count} rows in total")
```
Si `result_id` es `None`, `result_rows()` devuelve las filas que tiene, así que siempre es seguro llamarlo.
## Estime antes de ejecutar [#estime-antes-de-ejecutar]
`nexus.estimate()` indica cuánto leería una sentencia, sin ejecutarla ni cobrarla:
```python
estimate = nexus.estimate("SELECT * FROM events")
print(estimate["bytes_scanned"], estimate["allowed_bytes"], estimate["within_budget"])
```
Si `within_budget` es `False`, sería rechazada con `OverBudgetError`. Agregue un `WHERE` sobre una columna por la que esté organizada la tabla, seleccione menos columnas o agregue primero.
## Inicie Nexus con anticipación [#inicie-nexus-con-anticipación]
Tras un periodo sin actividad, la primera sentencia puede esperar mientras Nexus arranca. Antes de una ráfaga conocida (por ejemplo, al iniciar su app), llame a `nexus.warm()`; responde de inmediato y arranca Nexus en segundo plano. `nexus.spark_status()` le dice si está apagado, arrancando, listo u ocupado.
## Reintentos y tiempos de espera [#reintentos-y-tiempos-de-espera]
No necesita escribir ciclos de reintento alrededor de `sql()`:
- Cada sentencia lleva un ID elegido por el SDK. Si la conexión se cae, el SDK la reenvía con el mismo ID, y Nexus la ejecuta una sola vez.
- Cuando todos los espacios que permite su plan están ocupados, o Nexus está arrancando, el SDK espera y reintenta hasta por cinco minutos.
- Una sentencia que no terminó en ese tiempo lanza `AnswerNotReadyError`. Ejecútela de nuevo: nada se ejecutó dos veces.
## Qué puede salir mal [#qué-puede-salir-mal]
| Excepción | Causa | Qué hacer |
| --- | --- | --- |
| `RefusedError` | La sentencia no está permitida para esta clave, o el SQL no es válido. El mensaje dice cuál. | Corrija la sentencia o use una clave con más acceso. |
| `OverBudgetError` | La sentencia leería más de lo que permite su plan. | Acótela y verifique con `estimate()`. |
| `RateLimitedError` | Demasiadas llamadas por minuto. | El SDK ya esperó; haga su ciclo más lento. |
| `OverBudgetError` (ocupado) | Todos los espacios están tomados y la cola está llena. | Envíela de nuevo en un momento. |
| `InsufficientCreditsError` | El espacio de trabajo no tiene créditos. | Agregue créditos. |
| `AnswerNotReadyError` | No hubo respuesta dentro del tiempo de espera. | Pregunte de nuevo. |
## Próximos pasos [#próximos-pasos]
- [Tablas y esquemas](/docs/es/developers/tables) para crear y cambiar las tablas que consulta.
- [Trabajos y trabajos por lotes](/docs/es/developers/jobs) para cambiar filas con SQL.
- [Errores](/docs/es/developers/errors) para la lista completa de excepciones.