列类型
Sleet ORM 提供了丰富的列类型定义,支持 MySQL 的所有常用数据类型,并提供了类型安全的 Lua 接口。
整数类型
自增整数
lua
-- 自增主键(常用于 ID 字段)
local users = sl.table('users', {
id = sl.serial().primaryKey(), -- INT AUTO_INCREMENT PRIMARY KEY
big_id = sl.bigserial().primaryKey() -- BIGINT AUTO_INCREMENT PRIMARY KEY
})普通整数
lua
local products = sl.table('products', {
id = sl.serial().primaryKey(),
price = sl.int().notNull(), -- INT NOT NULL
stock = sl.bigint().default(0), -- BIGINT DEFAULT 0
category_id = sl.smallint(), -- SMALLINT
is_featured = sl.tinyint().default(0) -- TINYINT DEFAULT 0
})| 类型 | MySQL 类型 | 范围 | 用途 |
|---|---|---|---|
serial() | INT AUTO_INCREMENT | -2,147,483,648 到 2,147,483,647 | 主键 ID |
bigserial() | BIGINT AUTO_INCREMENT | -9,223,372,036,854,775,808 到 9,223,372,036,854,775,807 | 大表主键 |
int() | INT | -2,147,483,648 到 2,147,483,647 | 常规整数 |
bigint() | BIGINT | -9,223,372,036,854,775,808 到 9,223,372,036,854,775,807 | 大整数 |
smallint() | SMALLINT | -32,768 到 32,767 | 小整数 |
tinyint() | TINYINT | -128 到 127 | 微整数 |
浮点类型
lua
local measurements = sl.table('measurements', {
id = sl.serial().primaryKey(),
temperature = sl.float(), -- FLOAT
precision_value = sl.double(), -- DOUBLE
price = sl.decimal(10, 2).notNull(), -- DECIMAL(10,2) NOT NULL
percentage = sl.decimal(5, 4).default(0.0) -- DECIMAL(5,4) DEFAULT 0.0
})| 类型 | MySQL 类型 | 精度 | 用途 |
|---|---|---|---|
float() | FLOAT | 单精度 | 一般浮点数 |
double() | DOUBLE | 双精度 | 高精度浮点数 |
decimal(p, s) | DECIMAL(p,s) | 精确 | 金钱、精确计算 |
decimal() 参数说明
lua
-- decimal(precision, scale)
-- precision: 总位数(包括小数点前后)
-- scale: 小数点后位数
sl.decimal(10, 2) -- 最大 99999999.99
sl.decimal(5, 4) -- 最大 9.9999
sl.decimal() -- 默认 DECIMAL(10,2)字符串类型
lua
local users = sl.table('users', {
id = sl.serial().primaryKey(),
username = sl.varchar(50).notNull().unique(), -- VARCHAR(50) NOT NULL UNIQUE
password_hash = sl.varchar(255).notNull(), -- VARCHAR(255) NOT NULL
status = sl.char(1).default('A'), -- CHAR(1) DEFAULT 'A'
bio = sl.text(), -- TEXT
description = sl.mediumtext(), -- MEDIUMTEXT
content = sl.longtext() -- LONGTEXT
})| 类型 | MySQL 类型 | 最大长度 | 用途 |
|---|---|---|---|
varchar(len) | VARCHAR(len) | 65,535 字节 | 变长字符串 |
char(len) | CHAR(len) | 255 字符 | 定长字符串 |
text() | TEXT | 65,535 字符 | 短文本 |
mediumtext() | MEDIUMTEXT | 16,777,215 字符 | 中等文本 |
longtext() | LONGTEXT | 4,294,967,295 字符 | 长文本 |
字符串类型选择建议
lua
-- 短字符串,长度固定或变化不大
sl.varchar(50) -- 用户名、邮箱等
sl.char(2) -- 国家代码、状态码等
-- 长文本内容
sl.text() -- 评论、简短描述
sl.mediumtext() -- 文章内容
sl.longtext() -- 大型文档、JSON 数据布尔类型
lua
local players = sl.table('players', {
id = sl.serial().primaryKey(),
is_admin = sl.boolean().default(false), -- TINYINT(1) DEFAULT 0
is_active = sl.boolean().notNull(), -- TINYINT(1) NOT NULL
is_banned = sl.boolean().default(false) -- TINYINT(1) DEFAULT 0
})注意:MySQL 没有原生的 BOOLEAN 类型,
sl.boolean()会转换为TINYINT(1),其中 0 表示 false,1 表示 true。
时间类型
lua
local events = sl.table('events', {
id = sl.serial().primaryKey(),
created_at = sl.timestamp().defaultNow(), -- TIMESTAMP DEFAULT CURRENT_TIMESTAMP
updated_at = sl.timestamp().onUpdate(sl.sql('NOW()')), -- TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
scheduled_at = sl.datetime().notNull(), -- DATETIME NOT NULL
event_date = sl.date(), -- DATE
deleted_at = sl.timestamp().softDelete() -- 软删除时间戳
})| 类型 | MySQL 类型 | 格式 | 用途 |
|---|---|---|---|
timestamp() | TIMESTAMP | YYYY-MM-DD HH:MM:SS | 时间戳,自动时区转换 |
datetime() | DATETIME | YYYY-MM-DD HH:MM:SS | 日期时间,不转换时区 |
date() | DATE | YYYY-MM-DD | 仅日期 |
时间类型使用示例
lua
-- 自动时间戳
local posts = sl.table('posts', {
id = sl.serial().primaryKey(),
title = sl.varchar(255).notNull(),
created_at = sl.timestamp().defaultNow(),
updated_at = sl.timestamp()
.defaultNow()
.onUpdate(sl.sql('CURRENT_TIMESTAMP'))
})
-- 软删除支持
local users = sl.table('users', {
id = sl.serial().primaryKey(),
name = sl.varchar(255).notNull(),
deleted_at = sl.timestamp().softDelete()
})JSON 类型
lua
local players = sl.table('players', {
id = sl.serial().primaryKey(),
metadata = sl.json(), -- JSON 或 LONGTEXT(根据 MySQL 版本)
settings = sl.json().default('{}'), -- JSON DEFAULT '{}'
inventory = sl.json().notNull() -- JSON NOT NULL
})JSON 数据操作
lua
-- 插入 JSON 数据
db.insert(s.players)
.values({
name = 'Player1',
metadata = {
level = 10,
achievements = { 'first_login', 'tutorial_complete' },
position = { x = 100, y = 200, z = 30 }
}
})
.execute()
-- 更新 JSON 数据
db.update(s.players)
.set({
metadata = {
level = 15,
last_position = { x = 150, y = 250, z = 35 }
}
})
.where(sl.eq(s.players.id, playerId))
.execute()注意:如果 MySQL 版本不支持 JSON 类型,会自动降级为 LONGTEXT 类型。
列修饰符
所有列类型都支持以下修饰符方法:
基本约束
lua
local users = sl.table('users', {
id = sl.serial().primaryKey(), -- 主键
email = sl.varchar(255)
.notNull() -- 非空
.unique(), -- 唯一
name = sl.varchar(255)
.notNull()
.comment('用户姓名'), -- 注释
status = sl.varchar(20)
.default('active') -- 默认值
})外键关系
lua
local orders = sl.table('orders', {
id = sl.serial().primaryKey(),
user_id = sl.int()
.notNull()
.references(s.users.id), -- 外键引用
total = sl.decimal(10, 2).notNull()
})时间相关
lua
local posts = sl.table('posts', {
id = sl.serial().primaryKey(),
created_at = sl.timestamp().defaultNow(), -- 默认当前时间
updated_at = sl.timestamp()
.defaultNow()
.onUpdate(sl.sql('NOW()')) -- 更新时自动设置
})软删除
lua
local users = sl.table('users', {
id = sl.serial().primaryKey(),
name = sl.varchar(255).notNull(),
deleted_at = sl.timestamp().softDelete() -- 软删除标记
})修饰符方法参考
| 方法 | 参数 | 描述 |
|---|---|---|
primaryKey() | 无 | 设置为主键(自动添加 NOT NULL) |
notNull() | 无 | 非空约束 |
unique() | 无 | 唯一约束 |
default(value) | value: any | 设置默认值 |
defaultNow() | 无 | 默认当前时间(仅时间类型) |
autoIncrement() | 无 | 自动递增 |
references(column) | column: 列定义 | 外键引用 |
onUpdate(value) | value: any | 更新时的值 |
softDelete() | 无 | 标记为软删除字段 |
comment(text) | text: string | 添加列注释 |
完整示例
lua
local sl = Sleet
-- 用户表
local users = sl.table('users', {
id = sl.serial().primaryKey().comment('用户ID'),
identifier = sl.varchar(64).notNull().unique().comment('Steam/Discord标识符'),
name = sl.varchar(255).notNull().comment('用户名'),
email = sl.varchar(255).unique().comment('邮箱地址'),
password_hash = sl.varchar(255).comment('密码哈希'),
is_admin = sl.boolean().default(false).comment('管理员标志'),
is_active = sl.boolean().default(true).comment('激活状态'),
level = sl.int().default(1).comment('用户等级'),
experience = sl.bigint().default(0).comment('经验值'),
balance = sl.decimal(15, 2).default(0.00).comment('账户余额'),
metadata = sl.json().comment('扩展数据'),
last_login = sl.timestamp().comment('最后登录时间'),
created_at = sl.timestamp().defaultNow().comment('创建时间'),
updated_at = sl.timestamp().defaultNow().onUpdate(sl.sql('NOW()')).comment('更新时间'),
deleted_at = sl.timestamp().softDelete().comment('软删除时间')
})
-- 订单表(展示外键关系)
local orders = sl.table('orders', {
id = sl.serial().primaryKey(),
user_id = sl.int().notNull().references(users.id),
order_number = sl.varchar(50).notNull().unique(),
total_amount = sl.decimal(10, 2).notNull(),
status = sl.varchar(20).default('pending'),
items = sl.json(),
created_at = sl.timestamp().defaultNow(),
updated_at = sl.timestamp().defaultNow().onUpdate(sl.sql('NOW()'))
})
return { users = users, orders = orders }最佳实践
1. 选择合适的数据类型
lua
-- 好的实践
local users = sl.table('users', {
id = sl.serial().primaryKey(), -- 自增主键
status = sl.varchar(20), -- 状态用短字符串
age = sl.tinyint(), -- 年龄用小整数
balance = sl.decimal(15, 2), -- 金钱用精确小数
settings = sl.json() -- 配置用 JSON
})
-- 避免的做法
local bad_users = sl.table('bad_users', {
id = sl.varchar(255).primaryKey(), -- 避免:字符串主键性能差
status = sl.text(), -- 避免:短字符串用TEXT浪费空间
age = sl.bigint(), -- 避免:小数值用大整数浪费空间
balance = sl.float(), -- 避免:金钱计算用浮点数不精确
})2. 合理使用索引
lua
local users = sl.table('users', {
id = sl.serial().primaryKey(), -- 自动创建主键索引
identifier = sl.varchar(64).unique(), -- 自动创建唯一索引
email = sl.varchar(255).unique(), -- 经常查询的字段创建唯一索引
name = sl.varchar(255), -- 如果经常按名称搜索,考虑添加索引
created_at = sl.timestamp().defaultNow() -- 如果按时间排序,考虑添加索引
})3. 使用适当的默认值
lua
local users = sl.table('users', {
id = sl.serial().primaryKey(),
is_active = sl.boolean().default(true), -- 新用户默认激活
level = sl.int().default(1), -- 新用户从等级1开始
balance = sl.decimal(15, 2).default(0.00), -- 初始余额为0
created_at = sl.timestamp().defaultNow(), -- 自动设置创建时间
metadata = sl.json().default('{}') -- 空JSON对象
})