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