Ir al contenido

Base de Datos SQL

Ejecuta consultas SQL contra bases de datos PostgreSQL, MySQL y SQLite. Incluye consultas parametrizadas, transacciones, sentencias preparadas y un constructor de consultas fluido.

Para la configuración de la base de datos, consulte Base de Datos.

local sql = require("sql")

Obtener una conexión a la base de datos desde el registro de recursos:

local db, err = sql.get("app.db:main")
if err then
return nil, err
end
local rows = db:query("SELECT * FROM users WHERE active = ?", {1})
db:release()
ParámetroTipoDescripción
idstringID de recurso (p. ej., “app.db:main”)

Devuelve: DB, error

Las conexiones se devuelven automáticamente al pool cuando termina la función, pero se recomienda llamar a `db:release()` explícitamente en operaciones de larga duración. Los marcadores de posición se pasan al controlador de base de datos sin cambios; el runtime no los reescribe. SQLite y MySQL usan `?`, PostgreSQL usa `$1, $2`: escríbalos en la forma que espera su controlador. Los ejemplos siguientes usan `?` (SQLite/MySQL). Para consultas dirigidas a más de un motor, constrúyalas con el Constructor de Consultas y establezca el `placeholder_format` del dialecto.
sql.type.POSTGRES -- "postgres"
sql.type.MYSQL -- "mysql"
sql.type.SQLITE -- "sqlite"
sql.type.UNKNOWN -- "unknown"
sql.isolation.DEFAULT -- "default"
sql.isolation.READ_UNCOMMITTED -- "read_uncommitted"
sql.isolation.READ_COMMITTED -- "read_committed"
sql.isolation.WRITE_COMMITTED -- "write_committed"
sql.isolation.REPEATABLE_READ -- "repeatable_read"
sql.isolation.SERIALIZABLE -- "serializable"
local insert = sql.builder.insert("users")
:columns("name", "email")
:values("alice", sql.NULL)
local value = sql.as.int(42)

Devuelve: userdata

Convierte un valor al tipo SQL float.

local value = sql.as.float(19.99)

Devuelve: userdata

Convierte un valor al tipo SQL text.

local value = sql.as.text("hello")

Devuelve: userdata

Convierte un valor al tipo SQL binary.

local value = sql.as.binary("binary data")

Devuelve: userdata

Devuelve el marcador SQL NULL.

local value = sql.as.null()

Devuelve: userdata

local query = sql.builder.select("id", "name")
:from("users")
:where({active = 1})
ParámetroTipoDescripción
columns…stringNombres de columnas (opcional)

Devuelve: SelectBuilder

Crea un constructor de consulta INSERT.

local query = sql.builder.insert("users")
:columns("name", "email")
:values("alice", "alice@example.com")
ParámetroTipoDescripción
tablestringNombre de tabla (opcional)

Devuelve: InsertBuilder

Crea un constructor de consulta UPDATE.

local query = sql.builder.update("users")
:set("status", "active")
:where({id = 123})
ParámetroTipoDescripción
tablestringNombre de tabla (opcional)

Devuelve: UpdateBuilder

Crea un constructor de consulta DELETE.

local query = sql.builder.delete("users")
:where({active = 0})
:limit(100)
ParámetroTipoDescripción
tablestringNombre de tabla (opcional)

Devuelve: DeleteBuilder

Crea una expresión SQL cruda para usar en cláusulas where/having.

local expr = sql.builder.expr("score BETWEEN ? AND ?", 80, 90)
ParámetroTipoDescripción
sqlstringExpresión SQL con marcadores ?
args…anyArgumentos de enlace (opcional)

Devuelve: Sqlizer

Crea una condición de igualdad desde una tabla.

local cond = sql.builder.eq({active = 1, status = "open"})
ParámetroTipoDescripción
maptablePares {column = value}

Devuelve: Sqlizer

Crea una condición de desigualdad desde una tabla.

local cond = sql.builder.not_eq({status = "closed"})
ParámetroTipoDescripción
maptablePares {column = value}

Devuelve: Sqlizer

Crea una condición “menor que” desde una tabla.

local cond = sql.builder.lt({age = 18})
ParámetroTipoDescripción
maptablePares {column = value}

Devuelve: Sqlizer

Crea una condición “menor o igual que” desde una tabla.

local cond = sql.builder.lte({price = 100})
ParámetroTipoDescripción
maptablePares {column = value}

Devuelve: Sqlizer

Crea una condición “mayor que” desde una tabla.

local cond = sql.builder.gt({score = 80})
ParámetroTipoDescripción
maptablePares {column = value}

Devuelve: Sqlizer

Crea una condición “mayor o igual que” desde una tabla.

local cond = sql.builder.gte({age = 21})
ParámetroTipoDescripción
maptablePares {column = value}

Devuelve: Sqlizer

Crea una condición LIKE desde una tabla.

local cond = sql.builder.like({name = "john%"})
ParámetroTipoDescripción
maptablePares {column = value}

Devuelve: Sqlizer

Crea una condición NOT LIKE desde una tabla.

local cond = sql.builder.not_like({email = "%@spam.com"})
ParámetroTipoDescripción
maptablePares {column = value}

Devuelve: Sqlizer

Combina múltiples condiciones con AND.

local cond = sql.builder.and_({
sql.builder.eq({active = 1}),
sql.builder.gt({score = 80})
})
ParámetroTipoDescripción
conditionstableArreglo de condiciones Sqlizer o tabla

Devuelve: Sqlizer

Combina múltiples condiciones con OR.

local cond = sql.builder.or_({
sql.builder.eq({status = "pending"}),
sql.builder.eq({status = "active"})
})
ParámetroTipoDescripción
conditionstableArreglo de condiciones Sqlizer o tabla

Devuelve: Sqlizer

Formato de marcador para ? (predeterminado). Disponible como alias sql.builder.default_placeholder.

local query = sql.builder.select("*")
:from("users")
:placeholder_format(sql.builder.question)

Formato de marcador para $1, $2, …

local query = sql.builder.select("*")
:from("users")
:placeholder_format(sql.builder.dollar)

Formato de marcador para @p1, @p2, ... (estilo SQL Server). Se pasa a placeholder_format como los formatos anteriores.

Formato de marcador para :1, :2, .... Se pasa a placeholder_format como los formatos anteriores.

Handle de conexión a la base de datos devuelto por sql.get().

Devuelve la constante del tipo de base de datos.

local dbtype, err = db:type()

Devuelve: string, error

Ejecuta una consulta SELECT y devuelve filas.

local rows, err = db:query("SELECT id, name FROM users WHERE active = ?", {1})
ParámetroTipoDescripción
sqlstringConsulta SQL con marcadores ?
paramstableArreglo de parámetros de enlace (opcional)

Devuelve: table[], error

Ejecuta una consulta INSERT/UPDATE/DELETE.

local result, err = db:execute("INSERT INTO users (name) VALUES (?)", {"alice"})
ParámetroTipoDescripción
sqlstringSentencia SQL con marcadores ?
paramstableArreglo de parámetros de enlace (opcional)

Devuelve: table, error

Devuelve una tabla con los campos:

  • last_insert_id - Último ID insertado
  • rows_affected - Número de filas afectadas

Crea una sentencia preparada para ejecución repetida.

local stmt, err = db:prepare("SELECT * FROM users WHERE id = ?")
ParámetroTipoDescripción
sqlstringSQL con marcadores ?

Devuelve: Statement, error

Inicia una transacción en la base de datos.

local tx, err = db:begin({
isolation = sql.isolation.SERIALIZABLE,
read_only = false
})
ParámetroTipoDescripción
optionstableOpciones de transacción (opcional)

Campos de la tabla options:

  • isolation - Nivel de aislamiento de sql.isolation.* (predeterminado: DEFAULT)
  • read_only - Indicador de transacción de solo lectura (predeterminado: false)

Devuelve: Transaction, error

Devuelve el recurso de base de datos al pool.

local ok, err = db:release()

Devuelve: boolean, error

Devuelve estadísticas del pool de conexiones.

local stats, err = db:stats()

Devuelve: table, error

Devuelve una tabla con los campos:

  • max_open_connections - Máximo de conexiones abiertas permitidas
  • open_connections - Conexiones abiertas actualmente
  • in_use - Conexiones actualmente en uso
  • idle - Conexiones inactivas en el pool
  • wait_count - Número total de esperas de conexión
  • wait_duration - Duración total de espera
  • max_idle_closed - Conexiones cerradas por máximo de inactivas
  • max_idle_time_closed - Conexiones cerradas por timeout de inactividad
  • max_lifetime_closed - Conexiones cerradas por tiempo de vida máximo

Sentencia preparada devuelta por db:prepare().

Ejecuta la sentencia preparada como SELECT.

local rows, err = stmt:query({123})
ParámetroTipoDescripción
paramstableArreglo de parámetros de enlace (opcional)

Devuelve: table[], error

Ejecuta la sentencia preparada como INSERT/UPDATE/DELETE.

local result, err = stmt:execute({"alice"})
ParámetroTipoDescripción
paramstableArreglo de parámetros de enlace (opcional)

Devuelve: table, error

Devuelve una tabla con los campos:

  • last_insert_id - Último ID insertado
  • rows_affected - Número de filas afectadas

Cierra la sentencia preparada.

local ok, err = stmt:close()

Devuelve: boolean, error

Transacción de base de datos devuelta por db:begin().

Devuelve la constante del tipo de base de datos.

local dbtype, err = tx:db_type()

Devuelve: string, error

Ejecuta una consulta SELECT dentro de la transacción.

local rows, err = tx:query("SELECT id, name FROM users WHERE active = ?", {1})
ParámetroTipoDescripción
sqlstringConsulta SQL con marcadores ?
paramstableArreglo de parámetros de enlace (opcional)

Devuelve: table[], error

Ejecuta INSERT/UPDATE/DELETE dentro de la transacción.

local result, err = tx:execute("INSERT INTO users (name) VALUES (?)", {"alice"})
ParámetroTipoDescripción
sqlstringSentencia SQL con marcadores ?
paramstableArreglo de parámetros de enlace (opcional)

Devuelve: table, error

Devuelve una tabla con los campos:

  • last_insert_id - Último ID insertado
  • rows_affected - Número de filas afectadas

Crea una sentencia preparada dentro de la transacción.

local stmt, err = tx:prepare("SELECT * FROM users WHERE id = ?")
ParámetroTipoDescripción
sqlstringSQL con marcadores ?

Devuelve: Statement, error

Confirma la transacción.

local ok, err = tx:commit()

Devuelve: boolean, error

Revierte la transacción.

local ok, err = tx:rollback()

Devuelve: boolean, error

Crea un savepoint nombrado dentro de la transacción.

local ok, err = tx:savepoint("sp1")
ParámetroTipoDescripción
namestringNombre del savepoint (solo alfanuméricos y guion bajo)

Devuelve: boolean, error

Revierte hasta el savepoint nombrado.

local ok, err = tx:rollback_to("sp1")
ParámetroTipoDescripción
namestringNombre del savepoint

Devuelve: boolean, error

Libera el savepoint.

local ok, err = tx:release("sp1")
ParámetroTipoDescripción
namestringNombre del savepoint

Devuelve: boolean, error

Interfaz fluida para construir consultas SELECT.

Establece la cláusula FROM.

local query = sql.builder.select("id", "name"):from("users")
ParámetroTipoDescripción
tablestringNombre de tabla

Devuelve: SelectBuilder

Añade una cláusula JOIN.

local query = sql.builder.select("*")
:from("users")
:join("orders ON orders.user_id = users.id")
ParámetroTipoDescripción
joinstringCláusula JOIN con marcadores ?
args…anyArgumentos de enlace (opcional)

Devuelve: SelectBuilder

Añade una cláusula LEFT JOIN.

local query = sql.builder.select("*")
:from("users")
:left_join("orders ON orders.user_id = users.id")
ParámetroTipoDescripción
joinstringCláusula JOIN con marcadores ?
args…anyArgumentos de enlace (opcional)

Devuelve: SelectBuilder

Añade una cláusula RIGHT JOIN.

local query = sql.builder.select("*")
:from("users")
:right_join("orders ON orders.user_id = users.id")
ParámetroTipoDescripción
joinstringCláusula JOIN con marcadores ?
args…anyArgumentos de enlace (opcional)

Devuelve: SelectBuilder

Añade una cláusula INNER JOIN.

local query = sql.builder.select("*")
:from("users")
:inner_join("orders ON orders.user_id = users.id")
ParámetroTipoDescripción
joinstringCláusula JOIN con marcadores ?
args…anyArgumentos de enlace (opcional)

Devuelve: SelectBuilder

Añade una condición WHERE.

local query = sql.builder.select("*")
:from("users")
:where({active = 1})
ParámetroTipoDescripción
conditionstring|table|SqlizerCondición WHERE
args…anyArgumentos de enlace (opcional, cuando se usa string)

Admite tres formatos:

  • String: where("status = ?", "active")
  • Table: where({status = "active"})
  • Sqlizer: where(sql.builder.gt({score = 80}))

Devuelve: SelectBuilder

Añade una cláusula ORDER BY.

local query = sql.builder.select("*")
:from("users")
:order_by("name ASC", "created_at DESC")
ParámetroTipoDescripción
columns…stringNombres de columnas con ASC/DESC opcional

Devuelve: SelectBuilder

Añade una cláusula GROUP BY.

local query = sql.builder.select("status", "COUNT(*)")
:from("users")
:group_by("status")
ParámetroTipoDescripción
columns…stringNombres de columnas

Devuelve: SelectBuilder

Añade una condición HAVING.

local query = sql.builder.select("status", "COUNT(*) as cnt")
:from("users")
:group_by("status")
:having(sql.builder.gt({cnt = 10}))
ParámetroTipoDescripción
conditionstring|table|SqlizerCondición HAVING
args…anyArgumentos de enlace (opcional, cuando se usa string)

Devuelve: SelectBuilder

Establece el LIMIT.

local query = sql.builder.select("*")
:from("users")
:limit(10)
ParámetroTipoDescripción
nintegerValor del límite

Devuelve: SelectBuilder

Establece el OFFSET.

local query = sql.builder.select("*")
:from("users")
:offset(20)
ParámetroTipoDescripción
nintegerValor del offset

Devuelve: SelectBuilder

Añade columnas al SELECT.

local query = sql.builder.select():columns("id", "name", "email")
ParámetroTipoDescripción
columns…stringNombres de columnas

Devuelve: SelectBuilder

Añade el modificador DISTINCT.

local query = sql.builder.select("status")
:from("users")
:distinct()

Devuelve: SelectBuilder

Añade un sufijo SQL.

local query = sql.builder.select("*")
:from("users")
:suffix("FOR UPDATE")
ParámetroTipoDescripción
sqlstringSufijo SQL con marcadores ?
args…anyArgumentos de enlace (opcional)

Devuelve: SelectBuilder

Establece el formato de marcadores.

local query = sql.builder.select("*")
:from("users")
:placeholder_format(sql.builder.dollar)
ParámetroTipoDescripción
formatuserdataFormato de marcadores (sql.builder.*)

Devuelve: SelectBuilder

Genera la cadena SQL y los argumentos de enlace.

local sql_str, args = query:to_sql()

Devuelve: string, table

Crea un ejecutor para la consulta.

local executor = query:run_with(db)
local rows, err = executor:query()
ParámetroTipoDescripción
dbDB|TransactionHandle de base de datos o transacción

Devuelve: QueryExecutor

Interfaz fluida para construir consultas INSERT.

Establece el nombre de la tabla.

local query = sql.builder.insert():into("users")
ParámetroTipoDescripción
tablestringNombre de tabla

Devuelve: InsertBuilder

Establece los nombres de las columnas.

local query = sql.builder.insert("users"):columns("name", "email")
ParámetroTipoDescripción
columns…stringNombres de columnas

Devuelve: InsertBuilder

Añade valores de fila.

local query = sql.builder.insert("users")
:columns("name", "email")
:values("alice", "alice@example.com")
ParámetroTipoDescripción
values…anyValores de fila

Devuelve: InsertBuilder

Establece columnas y valores desde una tabla.

local query = sql.builder.insert("users")
:set_map({name = "alice", email = "alice@example.com"})
ParámetroTipoDescripción
maptablePares {column = value}

Devuelve: InsertBuilder

Inserta desde una consulta SELECT.

local select_query = sql.builder.select("name", "email"):from("temp_users")
local query = sql.builder.insert("users")
:columns("name", "email")
:select(select_query)
ParámetroTipoDescripción
querySelectBuilderConsulta SELECT

Devuelve: InsertBuilder

Añade un prefijo SQL.

local query = sql.builder.insert("users")
:prefix("INSERT IGNORE INTO")
ParámetroTipoDescripción
sqlstringPrefijo SQL con marcadores ?
args…anyArgumentos de enlace (opcional)

Devuelve: InsertBuilder

Añade un sufijo SQL.

local query = sql.builder.insert("users")
:columns("name")
:values("alice")
:suffix("RETURNING id")
ParámetroTipoDescripción
sqlstringSufijo SQL con marcadores ?
args…anyArgumentos de enlace (opcional)

Devuelve: InsertBuilder

Añade opciones de INSERT.

local query = sql.builder.insert("users")
:options("DELAYED", "IGNORE")
ParámetroTipoDescripción
options…stringOpciones de INSERT

Devuelve: InsertBuilder

Establece el formato de marcadores.

local query = sql.builder.insert("users")
:placeholder_format(sql.builder.dollar)
ParámetroTipoDescripción
formatuserdataFormato de marcadores (sql.builder.*)

Devuelve: InsertBuilder

Genera la cadena SQL y los argumentos de enlace.

local sql_str, args = query:to_sql()

Devuelve: string, table

Crea un ejecutor para la consulta.

local executor = query:run_with(db)
local result, err = executor:exec()
ParámetroTipoDescripción
dbDB|TransactionHandle de base de datos o transacción

Devuelve: QueryExecutor

Interfaz fluida para construir consultas UPDATE.

Establece el nombre de la tabla.

local query = sql.builder.update():table("users")
ParámetroTipoDescripción
tablestringNombre de tabla

Devuelve: UpdateBuilder

Establece el valor de una columna.

local query = sql.builder.update("users")
:set("status", "active")
:set("updated_at", sql.builder.expr("NOW()"))
ParámetroTipoDescripción
columnstringNombre de la columna
valueanyValor de la columna

Devuelve: UpdateBuilder

Establece múltiples columnas desde una tabla.

local query = sql.builder.update("users")
:set_map({status = "active", updated_at = sql.builder.expr("NOW()")})
ParámetroTipoDescripción
maptablePares {column = value}

Devuelve: UpdateBuilder

Añade una condición WHERE.

local query = sql.builder.update("users")
:set("status", "active")
:where({id = 123})
ParámetroTipoDescripción
conditionstring|table|SqlizerCondición WHERE
args…anyArgumentos de enlace (opcional, cuando se usa string)

Devuelve: UpdateBuilder

Añade una cláusula ORDER BY.

local query = sql.builder.update("users")
:set("rank", 1)
:order_by("score DESC")
ParámetroTipoDescripción
columns…stringNombres de columnas con ASC/DESC opcional

Devuelve: UpdateBuilder

Establece el LIMIT.

local query = sql.builder.update("users")
:set("status", "active")
:limit(10)
ParámetroTipoDescripción
nintegerValor del límite

Devuelve: UpdateBuilder

Establece el OFFSET.

local query = sql.builder.update("users")
:set("status", "active")
:offset(5)
ParámetroTipoDescripción
nintegerValor del offset

Devuelve: UpdateBuilder

Añade un sufijo SQL.

local query = sql.builder.update("users")
:set("status", "active")
:suffix("RETURNING id")
ParámetroTipoDescripción
sqlstringSufijo SQL con marcadores ?
args…anyArgumentos de enlace (opcional)

Devuelve: UpdateBuilder

Añade una cláusula FROM.

local query = sql.builder.update("users")
:set("status", "active")
:from("other_table")
ParámetroTipoDescripción
tablestringNombre de tabla

Devuelve: UpdateBuilder

Actualiza desde una consulta SELECT.

local select_query = sql.builder.select("*"):from("temp_users")
local query = sql.builder.update("users")
:set("status", "active")
:from_select(select_query, "t")
ParámetroTipoDescripción
querySelectBuilderConsulta SELECT
aliasstringAlias de tabla

Devuelve: UpdateBuilder

Establece el formato de marcadores.

local query = sql.builder.update("users")
:placeholder_format(sql.builder.dollar)
ParámetroTipoDescripción
formatuserdataFormato de marcadores (sql.builder.*)

Devuelve: UpdateBuilder

Genera la cadena SQL y los argumentos de enlace.

local sql_str, args = query:to_sql()

Devuelve: string, table

Crea un ejecutor para la consulta.

local executor = query:run_with(db)
local result, err = executor:exec()
ParámetroTipoDescripción
dbDB|TransactionHandle de base de datos o transacción

Devuelve: QueryExecutor

Interfaz fluida para construir consultas DELETE.

Establece el nombre de la tabla.

local query = sql.builder.delete():from("users")
ParámetroTipoDescripción
tablestringNombre de tabla

Devuelve: DeleteBuilder

Añade una condición WHERE.

local query = sql.builder.delete("users")
:where({active = 0})
ParámetroTipoDescripción
conditionstring|table|SqlizerCondición WHERE
args…anyArgumentos de enlace (opcional, cuando se usa string)

Devuelve: DeleteBuilder

Añade una cláusula ORDER BY.

local query = sql.builder.delete("users")
:where({active = 0})
:order_by("created_at ASC")
ParámetroTipoDescripción
columns…stringNombres de columnas con ASC/DESC opcional

Devuelve: DeleteBuilder

Establece el LIMIT.

local query = sql.builder.delete("users")
:where({active = 0})
:limit(100)
ParámetroTipoDescripción
nintegerValor del límite

Devuelve: DeleteBuilder

Establece el OFFSET.

local query = sql.builder.delete("users")
:where({active = 0})
:offset(10)
ParámetroTipoDescripción
nintegerValor del offset

Devuelve: DeleteBuilder

Añade un sufijo SQL.

local query = sql.builder.delete("users")
:where({active = 0})
:suffix("RETURNING id")
ParámetroTipoDescripción
sqlstringSufijo SQL con marcadores ?
args…anyArgumentos de enlace (opcional)

Devuelve: DeleteBuilder

Establece el formato de marcadores.

local query = sql.builder.delete("users")
:placeholder_format(sql.builder.dollar)
ParámetroTipoDescripción
formatuserdataFormato de marcadores (sql.builder.*)

Devuelve: DeleteBuilder

Genera la cadena SQL y los argumentos de enlace.

local sql_str, args = query:to_sql()

Devuelve: string, table

Crea un ejecutor para la consulta.

local executor = query:run_with(db)
local result, err = executor:exec()
ParámetroTipoDescripción
dbDB|TransactionHandle de base de datos o transacción

Devuelve: QueryExecutor

El ejecutor de consultas ejecuta las consultas generadas por el constructor.

Ejecuta la consulta y devuelve filas (para SELECT).

local rows, err = executor:query()

Devuelve: table[], error

Ejecuta la consulta y devuelve el resultado (para INSERT/UPDATE/DELETE).

local result, err = executor:exec()

Devuelve: table, error

Devuelve una tabla con los campos:

  • last_insert_id - Último ID insertado
  • rows_affected - Número de filas afectadas

Devuelve el SQL generado y los argumentos sin ejecutar.

local sql_str, args = executor:to_sql()

Devuelve: string, table

El acceso a la base de datos está sujeto a la evaluación de políticas de seguridad.

AcciónRecursoDescripción
db.getID de base de datosAdquirir conexión a la base de datos
CondiciónTipoReintentable
ID de recurso vacíoerrors.INVALIDno
Permiso denegadoerrors.PERMISSION_DENIEDno
Recurso no encontradoerrors.NOT_FOUNDno
El recurso no es base de datoserrors.INVALIDno
Parámetros inválidoserrors.INVALIDno
Error de sintaxis SQLerrors.INVALIDno
Sentencia cerradaerrors.INVALIDno
Transacción no activaerrors.INVALIDno
Nombre de savepoint inválidoerrors.INVALIDno
Error de ejecución de consultavaríavaría

Consulte Manejo de Errores para trabajar con errores.

local sql = require("sql")
-- Obtener conexión a la base de datos
local db, err = sql.get("app.db:main")
if err then error(err) end
-- Verificar tipo de base de datos
local dbtype, _ = db:type()
print("Database type:", dbtype)
-- Consulta directa
local users, err = db:query("SELECT id, name FROM users WHERE active = ?", {1})
if err then error(err) end
for _, user in ipairs(users) do
print(user.id, user.name)
end
-- Patrón constructor
local query = sql.builder.select("u.id", "u.name", "COUNT(o.id) as order_count")
:from("users u")
:left_join("orders o ON o.user_id = u.id")
:where(sql.builder.and_({
sql.builder.eq({["u.active"] = 1}),
sql.builder.gte({["u.score"] = 80})
}))
:group_by("u.id", "u.name")
:having(sql.builder.gt({["COUNT(o.id)"] = 0}))
:order_by("order_count DESC")
:limit(10)
local executor = query:run_with(db)
local results, err = executor:query()
if err then error(err) end
-- Transacción con savepoints
local tx, err = db:begin({isolation = sql.isolation.SERIALIZABLE})
if err then error(err) end
local _, err = tx:execute("INSERT INTO users (name) VALUES (?)", {"alice"})
if err then
tx:rollback()
error(err)
end
tx:savepoint("sp1")
local _, err = tx:execute("UPDATE users SET status = ? WHERE id = ?", {"active", 1})
if err then
tx:rollback_to("sp1")
else
tx:release("sp1")
end
local ok, err = tx:commit()
if err then error(err) end
-- Sentencias preparadas
local stmt, err = db:prepare("INSERT INTO logs (message, level) VALUES (?, ?)")
if err then error(err) end
for i = 1, 100 do
local _, err = stmt:execute({"log message " .. i, "info"})
if err then
stmt:close()
error(err)
end
end
stmt:close()
-- NULL y valores tipados
local insert = sql.builder.insert("products")
:columns("name", "price", "description")
:values("Widget", sql.as.float(19.99), sql.NULL)
local executor = insert:run_with(db)
local result, err = executor:exec()
if err then error(err) end
print("Inserted ID:", result.last_insert_id)
db:release()