操作符
Sleet ORM 提供了完整的操作符集合,用于构建类型安全的查询条件。所有操作符都会自动处理参数绑定,防止 SQL 注入攻击。
比较操作符
基本比较
lua
local sl = Sleet
local db = sl.connect()
-- 等于
local player = db.select()
.from(s.players)
.where(sl.eq(s.players.id, 123))
.execute()[1]
-- 不等于
local activePlayers = db.select()
.from(s.players)
.where(sl.ne(s.players.status, 'banned'))
.execute()
-- 大于
local highLevelPlayers = db.select()
.from(s.players)
.where(sl.gt(s.players.level, 50))
.execute()
-- 大于等于
local eligiblePlayers = db.select()
.from(s.players)
.where(sl.gte(s.players.age, 18))
.execute()
-- 小于
local newPlayers = db.select()
.from(s.players)
.where(sl.lt(s.players.level, 10))
.execute()
-- 小于等于
local moderateWarnings = db.select()
.from(s.players)
.where(sl.lte(s.players.warnings, 3))
.execute()操作符对照表
| 操作符 | SQL | 描述 | 示例 |
|---|---|---|---|
sl.eq(col, val) | = | 等于 | sl.eq(s.players.name, 'John') |
sl.ne(col, val) | != | 不等于 | sl.ne(s.players.status, 'banned') |
sl.gt(col, val) | > | 大于 | sl.gt(s.players.level, 10) |
sl.gte(col, val) | >= | 大于等于 | sl.gte(s.players.money, 1000) |
sl.lt(col, val) | < | 小于 | sl.lt(s.players.age, 60) |
sl.lte(col, val) | <= | 小于等于 | sl.lte(s.players.warnings, 5) |
字符串操作符
模糊匹配
lua
-- LIKE 模糊匹配
local playersWithJohn = db.select()
.from(s.players)
.where(sl.like(s.players.name, '%John%'))
.execute()
-- 以特定字符串开头
local steamPlayers = db.select()
.from(s.players)
.where(sl.like(s.players.identifier, 'steam:%'))
.execute()
-- 以特定字符串结尾
local gmailUsers = db.select()
.from(s.players)
.where(sl.like(s.players.email, '%@gmail.com'))
.execute()
-- NOT LIKE 不匹配
local nonDiscordPlayers = db.select()
.from(s.players)
.where(sl.notLike(s.players.identifier, 'discord:%'))
.execute()
-- ILIKE 大小写不敏感匹配(MySQL 默认不区分大小写)
local caseInsensitive = db.select()
.from(s.players)
.where(sl.ilike(s.players.name, '%JOHN%'))
.execute()字符串操作符对照表
| 操作符 | SQL | 描述 | 示例 |
|---|---|---|---|
sl.like(col, pattern) | LIKE | 模糊匹配 | sl.like(s.players.name, '%John%') |
sl.notLike(col, pattern) | NOT LIKE | 不匹配 | sl.notLike(s.players.email, '%spam%') |
sl.ilike(col, pattern) | LIKE | 大小写不敏感匹配 | sl.ilike(s.players.name, '%ADMIN%') |
通配符说明
lua
-- % 匹配零个或多个字符
sl.like(s.players.name, 'John%') -- 以 'John' 开头
sl.like(s.players.name, '%Smith') -- 以 'Smith' 结尾
sl.like(s.players.name, '%John%') -- 包含 'John'
-- _ 匹配单个字符
sl.like(s.players.code, 'A_B') -- A 和 B 之间有一个字符
sl.like(s.players.phone, '138____1234') -- 特定格式的手机号NULL 检查操作符
lua
-- 检查 NULL 值
local playersWithoutEmail = db.select()
.from(s.players)
.where(sl.isNull(s.players.email))
.execute()
-- 检查非 NULL 值
local playersWithEmail = db.select()
.from(s.players)
.where(sl.isNotNull(s.players.email))
.execute()
-- 查找未被封禁的玩家(banned_until 为 NULL)
local activePlayers = db.select()
.from(s.players)
.where(sl.isNull(s.players.banned_until))
.execute()
-- 查找当前被封禁的玩家
local bannedPlayers = db.select()
.from(s.players)
.where(sl.isNotNull(s.players.banned_until))
.execute()NULL 操作符对照表
| 操作符 | SQL | 描述 | 示例 |
|---|---|---|---|
sl.isNull(col) | IS NULL | 值为空 | sl.isNull(s.players.deleted_at) |
sl.isNotNull(col) | IS NOT NULL | 值不为空 | sl.isNotNull(s.players.email) |
范围操作符
IN 和 NOT IN
lua
-- IN 查询 - 值在指定列表中
local vipPlayers = db.select()
.from(s.players)
.where(sl.inArray(s.players.role, { 'admin', 'moderator', 'vip' }))
.execute()
-- 查找特定等级的玩家
local specificLevels = db.select()
.from(s.players)
.where(sl.inArray(s.players.level, { 10, 20, 30, 40, 50 }))
.execute()
-- NOT IN 查询 - 值不在指定列表中
local normalPlayers = db.select()
.from(s.players)
.where(sl.notInArray(s.players.status, { 'banned', 'suspended', 'deleted' }))
.execute()
-- 排除特定 ID
local otherPlayers = db.select()
.from(s.players)
.where(sl.notInArray(s.players.id, { 1, 2, 3 }))
.execute()BETWEEN
lua
-- BETWEEN 范围查询
local middleAged = db.select()
.from(s.players)
.where(sl.between(s.players.age, 25, 65))
.execute()
-- 特定时间范围
local recentPlayers = db.select()
.from(s.players)
.where(sl.between(s.players.created_at, '2024-01-01', '2024-12-31'))
.execute()
-- 金钱范围
local middleClass = db.select()
.from(s.players)
.where(sl.between(s.players.money, 10000, 100000))
.execute()范围操作符对照表
| 操作符 | SQL | 描述 | 示例 |
|---|---|---|---|
sl.inArray(col, values) | IN (...) | 值在列表中 | sl.inArray(s.players.role, {'admin', 'user'}) |
sl.notInArray(col, values) | NOT IN (...) | 值不在列表中 | sl.notInArray(s.players.status, {'banned'}) |
sl.between(col, min, max) | BETWEEN ... AND ... | 值在范围内 | sl.between(s.players.level, 10, 50) |
逻辑操作符
AND 逻辑
lua
-- AND - 所有条件都必须满足
local activeVipPlayers = db.select()
.from(s.players)
.where(sl.and_(
sl.eq(s.players.is_active, true),
sl.eq(s.players.is_vip, true),
sl.gte(s.players.level, 10)
))
.execute()
-- 复杂 AND 条件
local specificPlayers = db.select()
.from(s.players)
.where(sl.and_(
sl.like(s.players.name, 'John%'),
sl.gte(s.players.money, 5000),
sl.lte(s.players.warnings, 2),
sl.isNotNull(s.players.email)
))
.execute()OR 逻辑
lua
-- OR - 任一条件满足即可
local privilegedPlayers = db.select()
.from(s.players)
.where(sl.or_(
sl.eq(s.players.is_admin, true),
sl.eq(s.players.is_moderator, true),
sl.gte(s.players.level, 100)
))
.execute()
-- 多种状态查询
local availablePlayers = db.select()
.from(s.players)
.where(sl.or_(
sl.eq(s.players.status, 'online'),
sl.eq(s.players.status, 'idle'),
sl.eq(s.players.status, 'away')
))
.execute()NOT 逻辑
lua
-- NOT - 条件取反
local notBannedPlayers = db.select()
.from(s.players)
.where(sl.not_(sl.eq(s.players.is_banned, true)))
.execute()
-- 等价于
local notBannedPlayers2 = db.select()
.from(s.players)
.where(sl.eq(s.players.is_banned, false))
.execute()
-- 复杂 NOT 条件
local exceptionalPlayers = db.select()
.from(s.players)
.where(sl.not_(sl.and_(
sl.lt(s.players.level, 10),
sl.eq(s.players.is_premium, false)
)))
.execute()逻辑操作符对照表
| 操作符 | SQL | 描述 | 示例 |
|---|---|---|---|
sl.and_(cond1, cond2, ...) | AND | 所有条件都成立 | sl.and_(sl.eq(...), sl.gt(...)) |
sl.or_(cond1, cond2, ...) | OR | 任一条件成立 | sl.or_(sl.eq(...), sl.eq(...)) |
sl.not_(condition) | NOT | 条件取反 | sl.not_(sl.eq(s.players.active, false)) |
复杂条件组合
嵌套逻辑
lua
-- 复杂的条件组合
local targetPlayers = db.select()
.from(s.players)
.where(sl.and_(
-- 基本活跃条件
sl.eq(s.players.is_active, true),
sl.isNull(s.players.deleted_at),
-- 复杂的权限或等级条件
sl.or_(
-- 管理员或版主
sl.or_(
sl.eq(s.players.is_admin, true),
sl.eq(s.players.is_moderator, true)
),
-- 或者高等级VIP
sl.and_(
sl.eq(s.players.is_vip, true),
sl.gte(s.players.level, 50)
),
-- 或者富有的普通玩家
sl.and_(
sl.gte(s.players.money, 100000),
sl.gte(s.players.bank, 500000)
)
)
))
.execute()动态条件构建
lua
-- 根据参数动态构建查询条件
function FindPlayers(filters)
local conditions = {}
-- 基础条件:非删除用户
table.insert(conditions, sl.isNull(s.players.deleted_at))
-- 可选条件
if filters.name then
table.insert(conditions, sl.like(s.players.name, '%' .. filters.name .. '%'))
end
if filters.minLevel then
table.insert(conditions, sl.gte(s.players.level, filters.minLevel))
end
if filters.maxLevel then
table.insert(conditions, sl.lte(s.players.level, filters.maxLevel))
end
if filters.roles and #filters.roles > 0 then
table.insert(conditions, sl.inArray(s.players.role, filters.roles))
end
if filters.isActive ~= nil then
table.insert(conditions, sl.eq(s.players.is_active, filters.isActive))
end
-- 组合所有条件
local whereClause = (#conditions == 1) and conditions[1] or sl.and_(table.unpack(conditions))
return db.select()
.from(s.players)
.where(whereClause)
.execute()
end
-- 使用示例
local results = FindPlayers({
name = 'John',
minLevel = 10,
roles = { 'admin', 'moderator' },
isActive = true
})实用示例
用户筛选系统
lua
-- 查找活跃的高等级用户
local elitePlayers = db.select()
.from(s.players)
.where(sl.and_(
sl.eq(s.players.is_active, true),
sl.gte(s.players.level, 80),
sl.gte(s.players.playtime, 100), -- 游戏时间超过100小时
sl.lte(s.players.warnings, 1) -- 警告少于等于1次
))
.execute()
-- 查找需要关注的用户
local concernUsers = db.select()
.from(s.players)
.where(sl.or_(
sl.gte(s.players.warnings, 3), -- 警告过多
sl.like(s.players.last_action, '%suspicious%'), -- 可疑行为
sl.and_(
sl.lt(s.players.playtime, 5), -- 游戏时间短
sl.gte(s.players.money, 50000) -- 但金钱很多
)
))
.execute()商品查询系统
lua
-- 查找热门商品
local popularItems = db.select()
.from(s.items)
.where(sl.and_(
sl.eq(s.items.is_available, true),
sl.gte(s.items.sales_count, 100),
sl.between(s.items.price, 10, 1000),
sl.inArray(s.items.category, { 'weapons', 'vehicles', 'clothing' })
))
.execute()
-- 查找促销商品
local saleItems = db.select()
.from(s.items)
.where(sl.and_(
sl.eq(s.items.is_available, true),
sl.or_(
sl.isNotNull(s.items.discount_price),
sl.like(s.items.name, '%Sale%'),
sl.like(s.items.description, '%限时%')
)
))
.execute()时间范围查询
lua
-- 查找最近登录的用户
local recentUsers = db.select()
.from(s.players)
.where(sl.and_(
sl.gte(s.players.last_login, '2024-01-01'),
sl.isNotNull(s.players.last_login)
))
.execute()
-- 查找长期未登录用户
local inactiveUsers = db.select()
.from(s.players)
.where(sl.or_(
sl.lt(s.players.last_login, '2023-01-01'),
sl.isNull(s.players.last_login)
))
.execute()最佳实践
1. 合理使用索引
lua
-- 好的做法:在有索引的字段上使用精确匹配
db.select()
.from(s.players)
.where(sl.eq(s.players.identifier, identifier)) -- identifier 通常有唯一索引
.execute()
-- 避免:在大表上使用 LIKE 开头通配符
-- db.select().from(s.players).where(sl.like(s.players.name, '%John%'))
-- 更好的做法是使用全文搜索或专门的搜索字段2. 条件顺序优化
lua
-- 将最具选择性的条件放在前面
db.select()
.from(s.players)
.where(sl.and_(
sl.eq(s.players.identifier, identifier), -- 最具选择性(唯一)
sl.eq(s.players.is_active, true), -- 中等选择性
sl.isNotNull(s.players.name) -- 选择性最低
))
.execute()3. 避免复杂嵌套
lua
-- 复杂条件可以分解为多个查询或使用临时变量
local roleCondition = sl.inArray(s.players.role, { 'admin', 'moderator' })
local levelCondition = sl.gte(s.players.level, 50)
local moneyCondition = sl.gte(s.players.money, 100000)
local finalCondition = sl.and_(
sl.eq(s.players.is_active, true),
sl.or_(roleCondition, levelCondition, moneyCondition)
)
local results = db.select()
.from(s.players)
.where(finalCondition)
.execute()4. 参数安全
lua
-- 正确:使用参数绑定(自动防护)
local userInput = "John'; DROP TABLE users; --"
db.select()
.from(s.players)
.where(sl.eq(s.players.name, userInput)) -- 安全,自动转义
.execute()
-- 错误:直接拼接 SQL
-- local sql = "SELECT * FROM players WHERE name = '" .. userInput .. "'"
-- 这样会导致 SQL 注入漏洞