我有以下Oracle表:
GAMES
id_game int
id_user int
dt_game DATE
在创建新记录之前,我必须检查同一个用户是否每天都没有插入N次游戏。
我实际上是以这种方式选择今天玩的游戏数量:
select count(1) as num from GAMES
where id_user=ID_USER and
to_char(dt_game,'DD/MM/YYYY')=to_char(sysdate,'DD/MM/YYYY')
我不太喜欢它:有更好的方法吗?
提前致谢 角
答案 0 :(得分:6)
日期转换有点无意义并且阻止使用该列的任何索引;您可以使用dt_game > trunc(sysdate)
简化该位。
答案 1 :(得分:4)
在插入新行之前检查表并计算行数存在问题(与并发性有关)。
让我们说用户目前玩了9场比赛,你想把行限制在10 ..
如果你打开两个不同的会话,那么他们两个将看到9个游戏的当前未提交的值,因此两个游戏都被允许,到交易完成时,用户将玩11个游戏......违反了你试图强制执行的规则。
答案 2 :(得分:2)
您可以使用唯一约束来确保在特定日期可以插入固定的最大记录数。例如,如果N = 5:
CREATE TABLE GAMES (
id_game NUMBER NOT NULL,
id_user NUMBER NOT NULL,
dt_game DATE NOT NULL,
user_game_count NUMBER NOT NULL,
CONSTRAINT max_games_per_day
CHECK (user_game_count BETWEEN 1 AND 5),
CONSTRAINT dt_game_notime
CHECK (dt_game = TRUNC(dt_game)),
CONSTRAINT games_unique
UNIQUE (id_user, dt_game, user_game_count),
);
max_games_per_day
约束意味着它只能采用5个不同值中的一个。 dt_game_notime
约束意味着我们不会获得各种时间值。最后,唯一约束确保对于任何特定日期和用户,它们最多只能插入5行。
答案 3 :(得分:1)
在Oracle中,您可以在id_user,to_char(dt_game,'DD / MM / YYYY')上创建function based index以提高查找性能。