SQL Server 2008中如何将Smallint类型字段最大值限制为指定值(如3500)
SQL Server 2008 限制Smallint角色属性上限的实现方案
首选:CHECK约束(性能最优,无额外开销)
这是SQL Server原生的存储层强制校验规则,写入/更新时由数据库引擎自动触发,对高并发的游戏服务器几乎没有性能损耗,是这类需求的标准实现方式。
前置处理(如果表中已有超上限的旧数据)
直接加约束会因为存量数据不符合规则失败,先按业务逻辑修正存量数据,示例为直接截断到上限:
-- 按实际需要限制的字段逐个执行修正 UPDATE CharacterAttributes SET Strength = 3500 WHERE Strength > 3500; UPDATE CharacterAttributes SET Dexterity = 3500 WHERE Dexterity > 3500;
添加约束的实现
ALTER TABLE CharacterAttributes ADD CONSTRAINT CHK_CharacterAttributes_Stats_Max CHECK ( Strength BETWEEN 0 AND 3500 AND Dexterity BETWEEN 0 AND 3500 AND Intelligence BETWEEN 0 AND 3500 -- 追加所有需要限制上限的属性字段 );
约束生效后,任何尝试把属性改到3500以上的INSERT/UPDATE操作都会被直接拦截,抛出数据库错误并回滚,不会写入数据。后续要调整上限只需删除旧约束,重新添加新规则即可,不需要改动字段类型。
可选:INSTEAD OF触发器(需要自定义错误信息时使用)
如果CHECK约束的默认错误信息无法满足业务需求(比如需要返回自定义错误码给服务端做分支处理),可以用触发器实现,注意SQL Server 2008没有THROW语法,要使用RAISERROR:
CREATE TRIGGER TRG_CharacterAttributes_StatsCheck ON CharacterAttributes INSTEAD OF INSERT, UPDATE AS BEGIN SET NOCOUNT ON; -- 校验本次操作的所有行是否超上限 IF EXISTS ( SELECT 1 FROM inserted WHERE Strength > 3500 OR Dexterity > 3500 OR Intelligence > 3500 ) BEGIN RAISERROR(N'属性提升失败:已达到3500的允许上限', 16, 1); ROLLBACK TRANSACTION; RETURN; END -- 校验通过则正常写入所有字段 INSERT INTO CharacterAttributes (PlayerId, Strength, Dexterity, Intelligence, /* 表的其他全量字段 */) SELECT PlayerId, Strength, Dexterity, Intelligence, /* 对应取inserted的全量字段 */ FROM inserted; END
注意:INSTEAD OF触发器的性能开销远高于CHECK约束,仅在确实需要自定义逻辑时使用,优先选CHECK约束。
配套优化:应用层前置校验
不管用哪种数据库层的校验,都建议在服务端加一层前置判断:玩家提交属性提升请求时,先计算当前属性+本次新增点数是否超过3500,超过就直接返回前端提示,无需走数据库流程,既减少数据库压力,也能给玩家更及时的反馈。
额外说明:3500远低于Smallint类型32767的原生上限,完全不需要修改字段的数据类型,不会带来额外的存储成本。
内容的提问来源于stack exchange,提问作者Nacho Sanchez
相关产品推荐
相关产品推荐

