基础用法
本指南将带您了解 Sleet ORM 的基本用法,从定义表结构到执行数据库操作。
快速开始
定义 Schema
首先创建一个 schema 文件来定义您的表结构:
lua
-- server/schema.lua
local sl = Sleet
local players = sl.table('players', {
id = sl.serial().primaryKey().comment('玩家自增ID'),
identifier = sl.varchar(64).notNull().unique().comment('Steam / Discord 标识符'),
name = sl.varchar(255).notNull().comment('玩家名称'),
money = sl.int().default(500).comment('现金'),
bank = sl.int().default(2500).comment('银行余额'),
is_admin = sl.boolean().default(false).comment('管理员标志'),
metadata = sl.json().comment('扩展数据'),
last_seen = sl.timestamp().defaultNow().comment('最后在线时间'),
})
-- 导出 schema 供其他脚本使用
return { players = players }基本查询操作
在您的业务逻辑脚本中使用 schema:
lua
-- server/main.lua
local sl = Sleet
local s = require 'server.schema'
local db = sl.connect()
-- SELECT 查询
local rows = db.select()
.from(s.players)
.where(sl.eq(s.players.identifier, identifier))
.limit(1)
.execute()
local player = rows[1] -- 获取第一个结果数据库操作
SELECT 查询
查询所有记录
lua
-- 查询所有玩家
local allPlayers = db.select().from(s.players).execute()条件查询
lua
-- 根据 ID 查询单个玩家
local player = db.select()
.from(s.players)
.where(sl.eq(s.players.id, 123))
.execute()[1]
-- 查询管理员
local admins = db.select()
.from(s.players)
.where(sl.eq(s.players.is_admin, true))
.execute()
-- 复杂条件查询
local richPlayers = db.select()
.from(s.players)
.where(sl.and_(
sl.gte(s.players.money, 10000),
sl.gte(s.players.bank, 50000)
))
.execute()指定查询列
lua
-- 只查询特定字段
local playerNames = db.select({ s.players.id, s.players.name })
.from(s.players)
.execute()排序和分页
lua
-- 按名称排序
local sortedPlayers = db.select()
.from(s.players)
.orderBy(s.players.name, 'asc')
.execute()
-- 分页查询
local page2Players = db.select()
.from(s.players)
.limit(20)
.offset(40)
.execute()INSERT 操作
插入单条记录
lua
-- 新建玩家
local newPlayerId = db.insert(s.players)
.values({
identifier = 'steam:110000103fa6cc0',
name = GetPlayerName(source)
})
.execute()
print("新玩家 ID:", newPlayerId)批量插入(如果支持)
lua
-- 批量插入多个玩家
local playerIds = 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, bank = 10000 })
.where(sl.eq(s.players.identifier, identifier))
.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()更新 JSON 字段
lua
-- 更新玩家元数据
db.update(s.players)
.set({
metadata = {
last_position = { x = 100, y = 200, z = 30 },
playtime = 3600,
achievements = { 'first_login', 'tutorial_complete' }
}
})
.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()常用操作符
比较操作符
lua
-- 等于
sl.eq(s.players.name, '张三')
-- 不等于
sl.ne(s.players.status, 'banned')
-- 大于/小于
sl.gt(s.players.money, 1000)
sl.gte(s.players.level, 5)
sl.lt(s.players.age, 60)
sl.lte(s.players.warnings, 3)字符串操作符
lua
-- 模糊匹配
sl.like(s.players.name, '%张%')
-- 不匹配
sl.notLike(s.players.identifier, 'discord:%')NULL 检查
lua
-- 检查 NULL
sl.isNull(s.players.banned_until)
-- 检查非 NULL
sl.isNotNull(s.players.last_seen)范围操作符
lua
-- IN 查询
sl.inArray(s.players.role, { 'admin', 'moderator', 'vip' })
-- NOT IN
sl.notInArray(s.players.status, { 'banned', 'suspended' })
-- BETWEEN
sl.between(s.players.money, 1000, 10000)逻辑操作符
lua
-- AND 条件
sl.and_(
sl.eq(s.players.is_active, true),
sl.gte(s.players.level, 10)
)
-- OR 条件
sl.or_(
sl.eq(s.players.is_admin, true),
sl.eq(s.players.is_moderator, true)
)
-- NOT 条件
sl.not_(sl.eq(s.players.is_banned, true))高级功能
JOIN 查询
lua
-- 假设有订单表
local orders = sl.table('orders', {
id = sl.serial().primaryKey(),
player_id = sl.int().references(s.players.id),
item_name = sl.varchar(255),
price = sl.decimal(10, 2)
})
-- 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()聚合查询
lua
-- 统计查询(需要手动类型注解)
---@type { total: integer, avg_money: number }[]
local stats = db.select({
sl.sql('COUNT(*) AS total'),
sl.sql('AVG(`money`) AS avg_money')
}).from(s.players).execute()
local playerCount = stats[1].total
local averageMoney = stats[1].avg_money调试查询
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
-- 获取或创建玩家
function GetOrCreatePlayer(identifier, name)
-- 先尝试查找现有玩家
local existing = db.select()
.from(s.players)
.where(sl.eq(s.players.identifier, identifier))
.limit(1)
.execute()[1]
if existing then
-- 更新最后登录时间
db.update(s.players)
.set({ last_seen = sl.sql('NOW()') })
.where(sl.eq(s.players.id, existing.id))
.execute()
return existing
else
-- 创建新玩家
local newId = db.insert(s.players)
.values({
identifier = identifier,
name = name,
last_seen = sl.sql('NOW()')
})
.execute()
-- 返回新创建的玩家
return db.select()
.from(s.players)
.where(sl.eq(s.players.id, newId))
.execute()[1]
end
end金钱转账
lua
function TransferMoney(fromId, toId, amount)
-- 开始事务(需要 oxmysql 支持)
MySQL.transaction({
-- 扣除发送方金钱
{
query = db.update(s.players)
.set({ money = sl.sql('`money` - ?', { amount }) })
.where(sl.and_(
sl.eq(s.players.id, fromId),
sl.gte(s.players.money, amount)
))
.toSQL()
},
-- 增加接收方金钱
{
query = db.update(s.players)
.set({ money = sl.sql('`money` + ?', { amount }) })
.where(sl.eq(s.players.id, toId))
.toSQL()
}
}, function(success)
if success then
print("转账成功")
else
print("转账失败")
end
end)
end下一步
现在您已经掌握了基础用法:
