Skip to content

查询构建器

查询构建器是 Sleet ORM 的核心功能,提供了类型安全的 SQL 查询构建方法。

SELECT 查询

基础查询

lua
local sl = Sleet
local db = sl.connect()

-- 查询所有记录
local allPlayers = db.select().from(s.players).execute()

-- 查询指定列
local names = db.select({ s.players.id, s.players.name })
    .from(s.players)
    .execute()

条件查询

lua
-- WHERE 条件
local player = db.select()
    .from(s.players)
    .where(sl.eq(s.players.id, 123))
    .execute()

-- 复杂条件
local activePlayers = db.select()
    .from(s.players)
    .where(sl.and_(
        sl.eq(s.players.is_active, true),
        sl.gte(s.players.level, 10)
    ))
    .execute()

排序和分页

lua
-- 排序查询
local sortedPlayers = db.select()
    .from(s.players)
    .orderBy(s.players.name, 'asc')  -- 'asc' 或 'desc'
    .execute()

-- 分页查询
local page2 = db.select()
    .from(s.players)
    .limit(20)
    .offset(40)
    .execute()

JOIN 查询

lua
-- LEFT JOIN
local playerOrders = db.select()
    .from(s.orders)
    .leftJoin(s.players, sl.eq(s.orders.player_id, s.players.id))
    .where(sl.eq(s.players.identifier, identifier))
    .execute()

-- INNER JOIN
local activeOrders = db.select()
    .from(s.orders)
    .innerJoin(s.players, sl.eq(s.orders.player_id, s.players.id))
    .where(sl.eq(s.players.is_active, true))
    .execute()

-- RIGHT JOIN
local allPlayersWithOrders = db.select()
    .from(s.orders)
    .rightJoin(s.players, sl.eq(s.orders.player_id, s.players.id))
    .execute()

分组查询

lua
-- GROUP BY
local groupedStats = db.select({
    s.players.level,
    sl.sql('COUNT(*) as player_count')
})
    .from(s.players)
    .groupBy(s.players.level)
    .execute()

软删除支持

lua
-- 包含已软删除的记录
local allPlayers = db.select()
    .from(s.players)
    .withDeleted()
    .execute()

INSERT 操作

插入单条记录

lua
-- 插入新记录
local newId = db.insert(s.players)
    .values({
        identifier = 'steam:110000103fa6cc0',
        name = 'NewPlayer',
        money = 1000
    })
    .execute()

print("新插入的 ID:", newId)

批量插入

lua
-- 批量插入多条记录
local ids = db.insert(s.players)
    .values({
        { identifier = 'steam:001', name = '玩家1' },
        { identifier = 'steam:002', name = '玩家2' },
        { identifier = 'steam:003', name = '玩家3' }
    })
    .execute()

UPDATE 操作

基础更新

lua
-- 更新记录
local affected = db.update(s.players)
    .set({
        money = 5000,
        last_seen = sl.sql('NOW()')
    })
    .where(sl.eq(s.players.id, playerId))
    .execute()

print("更新了", affected, "行记录")

原子操作

lua
-- 安全的数值增减(防止并发问题)
db.update(s.players)
    .set({
        money = sl.sql('`money` + ?', { 1000 }),
        bank = sl.sql('`bank` - ?', { 500 })
    })
    .where(sl.eq(s.players.id, playerId))
    .execute()

DELETE 操作

基础删除

lua
-- 删除记录
local deleted = db.delete(s.players)
    .where(sl.eq(s.players.id, playerId))
    .execute()

print("删除了", deleted, "行记录")

批量删除

lua
-- 删除多条记录
db.delete(s.players)
    .where(sl.lt(s.players.last_seen, '2024-01-01'))
    .execute()

方法参考

SELECT 方法

方法参数描述
from(table)table: 表定义指定查询的表
where(condition)condition: 条件表达式添加 WHERE 条件
limit(n)n: number限制返回结果数量
offset(n)n: number跳过指定数量的记录
orderBy(column, direction)column: 列定义, direction: 'asc'|'desc'排序
groupBy(column)column: 列定义分组
leftJoin(table, on)table: 表定义, on: 条件表达式LEFT JOIN
innerJoin(table, on)table: 表定义, on: 条件表达式INNER JOIN
rightJoin(table, on)table: 表定义, on: 条件表达式RIGHT JOIN
withDeleted()包含软删除的记录
execute()执行查询并返回结果
toSQL()返回 SQL 字符串和参数

INSERT 方法

方法参数描述
values(data)data: table|table[]要插入的数据
execute()执行插入并返回新记录的 ID
toSQL()返回 SQL 字符串和参数

UPDATE 方法

方法参数描述
set(data)data: table要更新的数据
where(condition)condition: 条件表达式添加 WHERE 条件
execute()执行更新并返回受影响的行数
toSQL()返回 SQL 字符串和参数

DELETE 方法

方法参数描述
where(condition)condition: 条件表达式添加 WHERE 条件
execute()执行删除并返回受影响的行数
toSQL()返回 SQL 字符串和参数

调试查询

查看生成的 SQL

lua
-- 获取 SQL 和参数而不执行
local sql, params = db.select()
    .from(s.players)
    .where(sl.eq(s.players.id, 123))
    .toSQL()

print("SQL:", sql)
print("参数:", json.encode(params))
-- 输出: SQL: SELECT * FROM `players` WHERE `players`.`id` = ?
--       参数: [123]

调试复杂查询

lua
local sql, params = db.select()
    .from(s.orders)
    .leftJoin(s.players, sl.eq(s.orders.player_id, s.players.id))
    .where(sl.and_(
        sl.gte(s.orders.total, 100),
        sl.eq(s.players.is_active, true)
    ))
    .orderBy(s.orders.created_at, 'desc')
    .limit(10)
    .toSQL()

print("复杂查询 SQL:", sql)

最佳实践

1. 使用链式调用

lua
-- 推荐:链式调用
local result = db.select()
    .from(s.players)
    .where(sl.eq(s.players.is_active, true))
    .orderBy(s.players.name)
    .limit(100)
    .execute()

2. 条件构建

lua
-- 动态构建查询条件
local query = db.select().from(s.players)

if isAdmin then
    query = query.where(sl.eq(s.players.is_admin, true))
end

if minLevel then
    query = query.where(sl.gte(s.players.level, minLevel))
end

local results = query.execute()

3. 安全的参数传递

lua
-- 正确:使用参数绑定
db.select()
    .from(s.players)
    .where(sl.eq(s.players.name, playerName))  -- 自动转义
    .execute()

-- 错误:直接拼接字符串(SQL 注入风险)
-- db.select().from(s.players).where(sl.sql("name = '" .. playerName .. "'"))

4. 性能优化

lua
-- 只查询需要的列
local playerIds = db.select({ s.players.id })
    .from(s.players)
    .where(sl.eq(s.players.is_active, true))
    .execute()

-- 使用索引友好的查询
db.select()
    .from(s.players)
    .where(sl.eq(s.players.identifier, identifier))  -- identifier 应该有索引
    .limit(1)
    .execute()

下一步

Released under the MIT License.