Pular para o conteúdo

Banco de Dados SQL

Execute queries SQL em bancos de dados PostgreSQL, MySQL e SQLite. Recursos incluem queries parametrizadas, transacoes, prepared statements e um query builder fluente.

Para configuração de banco de dados, veja Database.

local sql = require("sql")

Obter uma conexão de banco de dados do registry 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âmetroTipoDescrição
idstringID do recurso (ex: “app.db:main”)

Retorna: DB, error

Conexoes sao automaticamente retornadas ao pool quando a função termina, mas chamar `db:release()` explicitamente e recomendado para operações de longa duração. Os marcadores de posição são passados ao driver do banco de dados sem alteração; o runtime não os reescreve. SQLite e MySQL usam `?`, PostgreSQL usa `$1, $2` — escreva-os no formato que seu driver espera. Os exemplos a seguir usam `?` (SQLite/MySQL). Para consultas que visam mais de um mecanismo, construa-as com o [Query Builder](#query-builder) e defina o `placeholder_format` do dialeto.
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)

Retorna: userdata

Coerce valor para tipo SQL float.

local value = sql.as.float(19.99)

Retorna: userdata

Coerce valor para tipo SQL text.

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

Retorna: userdata

Coerce valor para tipo SQL binary.

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

Retorna: userdata

Retorna marcador SQL NULL.

local value = sql.as.null()

Retorna: userdata

local query = sql.builder.select("id", "name")
:from("users")
:where({active = 1})
ParâmetroTipoDescrição
columns…stringNomes das colunas (opcional)

Retorna: SelectBuilder

Cria query builder de INSERT.

local query = sql.builder.insert("users")
:columns("name", "email")
:values("alice", "alice@example.com")
ParâmetroTipoDescrição
tablestringNome da tabela (opcional)

Retorna: InsertBuilder

Cria query builder de UPDATE.

local query = sql.builder.update("users")
:set("status", "active")
:where({id = 123})
ParâmetroTipoDescrição
tablestringNome da tabela (opcional)

Retorna: UpdateBuilder

Cria query builder de DELETE.

local query = sql.builder.delete("users")
:where({active = 0})
:limit(100)
ParâmetroTipoDescrição
tablestringNome da tabela (opcional)

Retorna: DeleteBuilder

Cria expressao SQL raw para uso em clausulas where/having.

local expr = sql.builder.expr("score BETWEEN ? AND ?", 80, 90)
ParâmetroTipoDescrição
sqlstringExpressao SQL com placeholders ?
args…anyArgumentos de bind (opcional)

Retorna: Sqlizer

Cria condição de igualdade de tabela.

local cond = sql.builder.eq({active = 1, status = "open"})
ParâmetroTipoDescrição
maptablePares {coluna = valor}

Retorna: Sqlizer

Cria condição de desigualdade de tabela.

local cond = sql.builder.not_eq({status = "closed"})
ParâmetroTipoDescrição
maptablePares {coluna = valor}

Retorna: Sqlizer

Cria condição menor-que de tabela.

local cond = sql.builder.lt({age = 18})
ParâmetroTipoDescrição
maptablePares {coluna = valor}

Retorna: Sqlizer

Cria condição menor-ou-igual de tabela.

local cond = sql.builder.lte({price = 100})
ParâmetroTipoDescrição
maptablePares {coluna = valor}

Retorna: Sqlizer

Cria condição maior-que de tabela.

local cond = sql.builder.gt({score = 80})
ParâmetroTipoDescrição
maptablePares {coluna = valor}

Retorna: Sqlizer

Cria condição maior-ou-igual de tabela.

local cond = sql.builder.gte({age = 21})
ParâmetroTipoDescrição
maptablePares {coluna = valor}

Retorna: Sqlizer

Cria condição LIKE de tabela.

local cond = sql.builder.like({name = "john%"})
ParâmetroTipoDescrição
maptablePares {coluna = valor}

Retorna: Sqlizer

Cria condição NOT LIKE de tabela.

local cond = sql.builder.not_like({email = "%@spam.com"})
ParâmetroTipoDescrição
maptablePares {coluna = valor}

Retorna: Sqlizer

Combina multiplas condicoes com AND.

local cond = sql.builder.and_({
sql.builder.eq({active = 1}),
sql.builder.gt({score = 80})
})
ParâmetroTipoDescrição
conditionstableArray de condicoes Sqlizer ou table

Retorna: Sqlizer

Combina multiplas condicoes com OR.

local cond = sql.builder.or_({
sql.builder.eq({status = "pending"}),
sql.builder.eq({status = "active"})
})
ParâmetroTipoDescrição
conditionstableArray de condicoes Sqlizer ou table

Retorna: Sqlizer

Formato de placeholder para placeholders ? (padrão). Disponível como alias sql.builder.default_placeholder.

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

Formato de placeholder para placeholders $1, $2, …

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

Formato de placeholder para placeholders @p1, @p2, ... (estilo SQL Server). Passado para placeholder_format como os formatos acima.

Formato de placeholder para placeholders :1, :2, .... Passado para placeholder_format como os formatos acima.

Handle de conexão de banco de dados retornado por sql.get().

Retorna constante de tipo de banco de dados.

local dbtype, err = db:type()

Retorna: string, error

Executa query SELECT e retorna linhas.

local rows, err = db:query("SELECT id, name FROM users WHERE active = ?", {1})
ParâmetroTipoDescrição
sqlstringQuery SQL com placeholders ?
paramstableArray de parametros de bind (opcional)

Retorna: table[], error

Executa query INSERT/UPDATE/DELETE.

local result, err = db:execute("INSERT INTO users (name) VALUES (?)", {"alice"})
ParâmetroTipoDescrição
sqlstringStatement SQL com placeholders ?
paramstableArray de parametros de bind (opcional)

Retorna: table, error

Retorna tabela com campos:

  • last_insert_id - Ultimo ID inserido
  • rows_affected - Numero de linhas afetadas

Cria prepared statement para execução repetida.

local stmt, err = db:prepare("SELECT * FROM users WHERE id = ?")
ParâmetroTipoDescrição
sqlstringSQL com placeholders ?

Retorna: Statement, error

Inicia transação de banco de dados.

local tx, err = db:begin({
isolation = sql.isolation.SERIALIZABLE,
read_only = false
})
ParâmetroTipoDescrição
optionstableOpções de transação (opcional)

Campos da tabela de opções:

  • isolation - Nivel de isolamento de sql.isolation.* (padrão: DEFAULT)
  • read_only - Flag de transação somente leitura (padrão: false)

Retorna: Transaction, error

Libera recurso de banco de dados de volta ao pool.

local ok, err = db:release()

Retorna: boolean, error

Retorna estatisticas do pool de conexoes.

local stats, err = db:stats()

Retorna: table, error

Retorna tabela com campos:

  • max_open_connections - Max conexoes abertas permitidas
  • open_connections - Conexoes abertas atuais
  • in_use - Conexoes em uso atualmente
  • idle - Conexoes ociosas no pool
  • wait_count - Contagem total de espera por conexão
  • wait_duration - Duração total de espera
  • max_idle_closed - Conexoes fechadas por max idle
  • max_idle_time_closed - Conexoes fechadas por timeout de idle
  • max_lifetime_closed - Conexoes fechadas por max lifetime

Prepared statement retornado por db:prepare().

Executa prepared statement como SELECT.

local rows, err = stmt:query({123})
ParâmetroTipoDescrição
paramstableArray de parametros de bind (opcional)

Retorna: table[], error

Executa prepared statement como INSERT/UPDATE/DELETE.

local result, err = stmt:execute({"alice"})
ParâmetroTipoDescrição
paramstableArray de parametros de bind (opcional)

Retorna: table, error

Retorna tabela com campos:

  • last_insert_id - Ultimo ID inserido
  • rows_affected - Numero de linhas afetadas

Fecha prepared statement.

local ok, err = stmt:close()

Retorna: boolean, error

Transação de banco de dados retornada por db:begin().

Retorna constante de tipo de banco de dados.

local dbtype, err = tx:db_type()

Retorna: string, error

Executa query SELECT dentro da transação.

local rows, err = tx:query("SELECT id, name FROM users WHERE active = ?", {1})
ParâmetroTipoDescrição
sqlstringQuery SQL com placeholders ?
paramstableArray de parametros de bind (opcional)

Retorna: table[], error

Executa INSERT/UPDATE/DELETE dentro da transação.

local result, err = tx:execute("INSERT INTO users (name) VALUES (?)", {"alice"})
ParâmetroTipoDescrição
sqlstringStatement SQL com placeholders ?
paramstableArray de parametros de bind (opcional)

Retorna: table, error

Retorna tabela com campos:

  • last_insert_id - Ultimo ID inserido
  • rows_affected - Numero de linhas afetadas

Cria prepared statement dentro da transação.

local stmt, err = tx:prepare("SELECT * FROM users WHERE id = ?")
ParâmetroTipoDescrição
sqlstringSQL com placeholders ?

Retorna: Statement, error

Commita transação.

local ok, err = tx:commit()

Retorna: boolean, error

Faz rollback da transação.

local ok, err = tx:rollback()

Retorna: boolean, error

Cria savepoint nomeado dentro da transação.

local ok, err = tx:savepoint("sp1")
ParâmetroTipoDescrição
namestringNome do savepoint (apenas alfanumerico e underscore)

Retorna: boolean, error

Faz rollback para savepoint nomeado.

local ok, err = tx:rollback_to("sp1")
ParâmetroTipoDescrição
namestringNome do savepoint

Retorna: boolean, error

Libera savepoint.

local ok, err = tx:release("sp1")
ParâmetroTipoDescrição
namestringNome do savepoint

Retorna: boolean, error

Interface fluente para construir queries SELECT.

Define clausula FROM.

local query = sql.builder.select("id", "name"):from("users")
ParâmetroTipoDescrição
tablestringNome da tabela

Retorna: SelectBuilder

Adiciona clausula JOIN.

local query = sql.builder.select("*")
:from("users")
:join("orders ON orders.user_id = users.id")
ParâmetroTipoDescrição
joinstringClausula JOIN com placeholders ?
args…anyArgumentos de bind (opcional)

Retorna: SelectBuilder

Adiciona clausula LEFT JOIN.

local query = sql.builder.select("*")
:from("users")
:left_join("orders ON orders.user_id = users.id")
ParâmetroTipoDescrição
joinstringClausula JOIN com placeholders ?
args…anyArgumentos de bind (opcional)

Retorna: SelectBuilder

Adiciona clausula RIGHT JOIN.

local query = sql.builder.select("*")
:from("users")
:right_join("orders ON orders.user_id = users.id")
ParâmetroTipoDescrição
joinstringClausula JOIN com placeholders ?
args…anyArgumentos de bind (opcional)

Retorna: SelectBuilder

Adiciona clausula INNER JOIN.

local query = sql.builder.select("*")
:from("users")
:inner_join("orders ON orders.user_id = users.id")
ParâmetroTipoDescrição
joinstringClausula JOIN com placeholders ?
args…anyArgumentos de bind (opcional)

Retorna: SelectBuilder

Adiciona condição WHERE.

local query = sql.builder.select("*")
:from("users")
:where({active = 1})
ParâmetroTipoDescrição
conditionstring|table|SqlizerCondição WHERE
args…anyArgumentos de bind (opcional, quando usando string)

Suporta tres formatos:

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

Retorna: SelectBuilder

Adiciona clausula ORDER BY.

local query = sql.builder.select("*")
:from("users")
:order_by("name ASC", "created_at DESC")
ParâmetroTipoDescrição
columns…stringNomes de colunas com ASC/DESC opcional

Retorna: SelectBuilder

Adiciona clausula GROUP BY.

local query = sql.builder.select("status", "COUNT(*)")
:from("users")
:group_by("status")
ParâmetroTipoDescrição
columns…stringNomes das colunas

Retorna: SelectBuilder

Adiciona condição HAVING.

local query = sql.builder.select("status", "COUNT(*) as cnt")
:from("users")
:group_by("status")
:having(sql.builder.gt({cnt = 10}))
ParâmetroTipoDescrição
conditionstring|table|SqlizerCondição HAVING
args…anyArgumentos de bind (opcional, quando usando string)

Retorna: SelectBuilder

Define LIMIT.

local query = sql.builder.select("*")
:from("users")
:limit(10)
ParâmetroTipoDescrição
nintegerValor de limit

Retorna: SelectBuilder

Define OFFSET.

local query = sql.builder.select("*")
:from("users")
:offset(20)
ParâmetroTipoDescrição
nintegerValor de offset

Retorna: SelectBuilder

Adiciona colunas ao SELECT.

local query = sql.builder.select():columns("id", "name", "email")
ParâmetroTipoDescrição
columns…stringNomes das colunas

Retorna: SelectBuilder

Adiciona modificador DISTINCT.

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

Retorna: SelectBuilder

Adiciona sufixo SQL.

local query = sql.builder.select("*")
:from("users")
:suffix("FOR UPDATE")
ParâmetroTipoDescrição
sqlstringSufixo SQL com placeholders ?
args…anyArgumentos de bind (opcional)

Retorna: SelectBuilder

Define formato de placeholder.

local query = sql.builder.select("*")
:from("users")
:placeholder_format(sql.builder.dollar)
ParâmetroTipoDescrição
formatuserdataFormato de placeholder (sql.builder.*)

Retorna: SelectBuilder

Gera string SQL e argumentos de bind.

local sql_str, args = query:to_sql()

Retorna: string, table

Cria executor para query.

local executor = query:run_with(db)
local rows, err = executor:query()
ParâmetroTipoDescrição
dbDB|TransactionHandle de banco de dados ou transação

Retorna: QueryExecutor

Interface fluente para construir queries INSERT.

Define nome da tabela.

local query = sql.builder.insert():into("users")
ParâmetroTipoDescrição
tablestringNome da tabela

Retorna: InsertBuilder

Define nomes das colunas.

local query = sql.builder.insert("users"):columns("name", "email")
ParâmetroTipoDescrição
columns…stringNomes das colunas

Retorna: InsertBuilder

Adiciona valores de linha.

local query = sql.builder.insert("users")
:columns("name", "email")
:values("alice", "alice@example.com")
ParâmetroTipoDescrição
values…anyValores da linha

Retorna: InsertBuilder

Define colunas e valores de tabela.

local query = sql.builder.insert("users")
:set_map({name = "alice", email = "alice@example.com"})
ParâmetroTipoDescrição
maptablePares {coluna = valor}

Retorna: InsertBuilder

Insere de query 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âmetroTipoDescrição
querySelectBuilderQuery SELECT

Retorna: InsertBuilder

Adiciona prefixo SQL.

local query = sql.builder.insert("users")
:prefix("INSERT IGNORE INTO")
ParâmetroTipoDescrição
sqlstringPrefixo SQL com placeholders ?
args…anyArgumentos de bind (opcional)

Retorna: InsertBuilder

Adiciona sufixo SQL.

local query = sql.builder.insert("users")
:columns("name")
:values("alice")
:suffix("RETURNING id")
ParâmetroTipoDescrição
sqlstringSufixo SQL com placeholders ?
args…anyArgumentos de bind (opcional)

Retorna: InsertBuilder

Adiciona opções de INSERT.

local query = sql.builder.insert("users")
:options("DELAYED", "IGNORE")
ParâmetroTipoDescrição
options…stringOpções de INSERT

Retorna: InsertBuilder

Define formato de placeholder.

local query = sql.builder.insert("users")
:placeholder_format(sql.builder.dollar)
ParâmetroTipoDescrição
formatuserdataFormato de placeholder (sql.builder.*)

Retorna: InsertBuilder

Gera string SQL e argumentos de bind.

local sql_str, args = query:to_sql()

Retorna: string, table

Cria executor para query.

local executor = query:run_with(db)
local result, err = executor:exec()
ParâmetroTipoDescrição
dbDB|TransactionHandle de banco de dados ou transação

Retorna: QueryExecutor

Interface fluente para construir queries UPDATE.

Define nome da tabela.

local query = sql.builder.update():table("users")
ParâmetroTipoDescrição
tablestringNome da tabela

Retorna: UpdateBuilder

Define valor de coluna.

local query = sql.builder.update("users")
:set("status", "active")
:set("updated_at", sql.builder.expr("NOW()"))
ParâmetroTipoDescrição
columnstringNome da coluna
valueanyValor da coluna

Retorna: UpdateBuilder

Define multiplas colunas de tabela.

local query = sql.builder.update("users")
:set_map({status = "active", updated_at = sql.builder.expr("NOW()")})
ParâmetroTipoDescrição
maptablePares {coluna = valor}

Retorna: UpdateBuilder

Adiciona condição WHERE.

local query = sql.builder.update("users")
:set("status", "active")
:where({id = 123})
ParâmetroTipoDescrição
conditionstring|table|SqlizerCondição WHERE
args…anyArgumentos de bind (opcional, quando usando string)

Retorna: UpdateBuilder

Adiciona clausula ORDER BY.

local query = sql.builder.update("users")
:set("rank", 1)
:order_by("score DESC")
ParâmetroTipoDescrição
columns…stringNomes de colunas com ASC/DESC opcional

Retorna: UpdateBuilder

Define LIMIT.

local query = sql.builder.update("users")
:set("status", "active")
:limit(10)
ParâmetroTipoDescrição
nintegerValor de limit

Retorna: UpdateBuilder

Define OFFSET.

local query = sql.builder.update("users")
:set("status", "active")
:offset(5)
ParâmetroTipoDescrição
nintegerValor de offset

Retorna: UpdateBuilder

Adiciona sufixo SQL.

local query = sql.builder.update("users")
:set("status", "active")
:suffix("RETURNING id")
ParâmetroTipoDescrição
sqlstringSufixo SQL com placeholders ?
args…anyArgumentos de bind (opcional)

Retorna: UpdateBuilder

Adiciona clausula FROM.

local query = sql.builder.update("users")
:set("status", "active")
:from("other_table")
ParâmetroTipoDescrição
tablestringNome da tabela

Retorna: UpdateBuilder

Update de query 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âmetroTipoDescrição
querySelectBuilderQuery SELECT
aliasstringAlias da tabela

Retorna: UpdateBuilder

Define formato de placeholder.

local query = sql.builder.update("users")
:placeholder_format(sql.builder.dollar)
ParâmetroTipoDescrição
formatuserdataFormato de placeholder (sql.builder.*)

Retorna: UpdateBuilder

Gera string SQL e argumentos de bind.

local sql_str, args = query:to_sql()

Retorna: string, table

Cria executor para query.

local executor = query:run_with(db)
local result, err = executor:exec()
ParâmetroTipoDescrição
dbDB|TransactionHandle de banco de dados ou transação

Retorna: QueryExecutor

Interface fluente para construir queries DELETE.

Define nome da tabela.

local query = sql.builder.delete():from("users")
ParâmetroTipoDescrição
tablestringNome da tabela

Retorna: DeleteBuilder

Adiciona condição WHERE.

local query = sql.builder.delete("users")
:where({active = 0})
ParâmetroTipoDescrição
conditionstring|table|SqlizerCondição WHERE
args…anyArgumentos de bind (opcional, quando usando string)

Retorna: DeleteBuilder

Adiciona clausula ORDER BY.

local query = sql.builder.delete("users")
:where({active = 0})
:order_by("created_at ASC")
ParâmetroTipoDescrição
columns…stringNomes de colunas com ASC/DESC opcional

Retorna: DeleteBuilder

Define LIMIT.

local query = sql.builder.delete("users")
:where({active = 0})
:limit(100)
ParâmetroTipoDescrição
nintegerValor de limit

Retorna: DeleteBuilder

Define OFFSET.

local query = sql.builder.delete("users")
:where({active = 0})
:offset(10)
ParâmetroTipoDescrição
nintegerValor de offset

Retorna: DeleteBuilder

Adiciona sufixo SQL.

local query = sql.builder.delete("users")
:where({active = 0})
:suffix("RETURNING id")
ParâmetroTipoDescrição
sqlstringSufixo SQL com placeholders ?
args…anyArgumentos de bind (opcional)

Retorna: DeleteBuilder

Define formato de placeholder.

local query = sql.builder.delete("users")
:placeholder_format(sql.builder.dollar)
ParâmetroTipoDescrição
formatuserdataFormato de placeholder (sql.builder.*)

Retorna: DeleteBuilder

Gera string SQL e argumentos de bind.

local sql_str, args = query:to_sql()

Retorna: string, table

Cria executor para query.

local executor = query:run_with(db)
local result, err = executor:exec()
ParâmetroTipoDescrição
dbDB|TransactionHandle de banco de dados ou transação

Retorna: QueryExecutor

O query executor executa queries geradas pelo builder.

Executa query e retorna linhas (para SELECT).

local rows, err = executor:query()

Retorna: table[], error

Executa query e retorna resultado (para INSERT/UPDATE/DELETE).

local result, err = executor:exec()

Retorna: table, error

Retorna tabela com campos:

  • last_insert_id - Ultimo ID inserido
  • rows_affected - Numero de linhas afetadas

Retorna SQL gerado e argumentos sem executar.

local sql_str, args = executor:to_sql()

Retorna: string, table

Acesso a banco de dados está sujeito a avaliação de política de segurança.

AçãoRecursoDescrição
db.getID do DatabaseObter conexão de banco de dados
CondiçãoTipoRetentável
ID de recurso vazioerrors.INVALIDnão
Permissão negadaerrors.PERMISSION_DENIEDnão
Recurso não encontradoerrors.NOT_FOUNDnão
Recurso não e databaseerrors.INVALIDnão
Parametros inválidoserrors.INVALIDnão
Erro de sintaxe SQLerrors.INVALIDnão
Statement fechadoerrors.INVALIDnão
Transação não ativaerrors.INVALIDnão
Nome de savepoint inválidoerrors.INVALIDnão
Erro de execução de queryvariavaria

Veja Error Handling para trabalhar com erros.

local sql = require("sql")
-- Obter conexão de banco de dados
local db, err = sql.get("app.db:main")
if err then error(err) end
-- Verificar tipo de banco de dados
local dbtype, _ = db:type()
print("Tipo de banco de dados:", dbtype)
-- Query direta
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
-- Padrão builder
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
-- Transação com 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
-- Prepared statements
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 e 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("ID inserido:", result.last_insert_id)
db:release()