我正在制作一个基于Web的小游戏,需要确定在哪里放置逻辑来检查sql数据库中某些底层数据的完整性。
每个用户都会跟踪分配给他的积分,并通过各种任务奖励积分。我保留每个任务交易的记录,以确保它们不会重复,并在完成时跟踪任务的价值,因为个人奖励级别随着时间的推移而波动。
到目前为止,我的架构看起来像这样:
create table player (
player_ID serial primary key,
player_Points int not null default 0
);
create table task (
task_ID serial primary key,
task_PointsAwarded int not null
);
create table task_list (
player_ID int references player(player_ID),
task_ID int references task(task_ID),
when_completed timestamp default current_timestamp,
point_value int not null, --not fk because task value may change later
constraint pk_player_task_id primary key (player_ID, task_ID)
);
因此,player.player_Points
应该是task_list
中所有累积任务点的总和。
现在我在哪里用逻辑来强制执行这个?
我是否应该完全取消player.player_Points
并在每次想知道总分时进行查询?这似乎很浪费,因为我会在游戏过程中经常进行这样的查询。
或者,在task_list
中添加一个自动更新player.player_Points
的触发器?在数据库中有太多的逻辑,应该只在应用程序中维护这种关系吗?
感谢。
答案 0 :(得分:0)
实际上,触发建议是最好的。这正是那种理想适合的任务触发器(您也可以使用触发器或约束来检查应用程序计算的总数,但它的工作量相同,所以为什么还要将计算工作添加到应用程序?)。 / p>
答案 1 :(得分:0)
从关系角度来看,你想要完全取消player.player_Points,这样你就不必担心数据的完整性。如果这是一个太大的性能负担,那么你可以像你一样对它进行非规范化,但我会对应用程序进行一些压力测试,以确保是这种情况,不需要过早优化,并且它是一个非常简单的查询来获取值(不仅仅是逻辑上的,而且来自数据库工作负载的角度)。
就个人而言,即使你使用非规范化路线,我也不会使用触发器,但这只是个人偏见,你当然可以走那条路。我可能只是设置了一些集成测试,以确保每次执行插入/更新/删除时一切都正确更新,并且如果您怀疑存在问题,可能会保存一个可以定期运行的查询。
我还考虑在任务上添加日期范围,这样您就不必将points_value存储在task_list中。