如何在PostgreSQL中正确设计VS匹配表?
我已经考虑过这个问题了,我还没有想出更好的东西.那么让我来描述我的问题,我目前的解决方案,以及我想要改进的地方.我也有一些顾虑,比如我的设计是否实际正常化.
我正在创建一个数据库,我希望为比赛存储VS比赛信息.为简单起见,我们假装他们是国际象棋比赛. 1V1.我目前的设计如下: CREATE TABLE matches( match_id bigserial PRIMARY KEY,tournament_id int NOT NULL,step int NOT NULL,winner match_winner,(etc. etc.) UNIQUE(match_id,tournament_id,step),-- Actual primary key FOREIGN KEY (tournament_id) references tournaments(tournament_id) ON DELETE RESTRICT ON UPDATE CASCADE ); CREATE TABLE match_players( match_id bigint NOT NULL,player_id int NOT NULL,first boolean NOT NULL,PRIMARY KEY (match_id,step,player_id),UNIQUE (tournament_id,foreign key (match_id,step) -- keep em together references matches(match_id,step) ON DELETE RESTRICT ON UPDATE CASCADE,foreign key (player_id) references accounts(player_id) ON DELETE RESTRICT ON UPDATE CASCADE ); -- Partial index,ensure no more than one "first" player exists per match CREATE UNIQUE INDEX idx_match_players_primary ON match_players USING btree (match_id,step) WHERE first=true; -- Also ensure that no more than one "not-first" player exists per match CREATE UNIQUE INDEX idx_match_players_not_primary ON match_players USING btree (match_id,step) WHERE first=false; 为了得到实际的vs匹配,我可以简单地将match_players连接到它自己(在mp1.match_id = mp2.match_id,mp1.first = true和mp2.first = false,其中mp1和mp2是匹配的两个实例).部分唯一索引确保最多可添加两个玩家. 数据库已经通过这种方式进行了规范化,因为玩家是无序的.如同,A vs B与B vs A相同.我已将“first”布尔值添加到匹配中,以便可以始终显示A vs B. (我想我可以简化它,以便mp1.player_id< mp2.player_id ......但是“第一个”布尔值似乎有用). tournament_id和step在第二个表中重复,因为在该表的Unique索引上需要它们…以确保玩家每个步骤只有一个匹配. 这是我的主要问题: 这是我的一个担忧: >由于孤立行仍然存在,是否存在任何其他数据异常 感谢任何可以帮助我的人.这是迄今为止我能做的最好的事情.我想如果我解决孤立的行问题,那么这个设计将是完美的.我想我可以设置一个cron工作来清除孤立的行,但是我想知道在解决这个问题之前是否存在更清洁的设计. 我确实认为检查约束中的子查询可以解决问题,但是,我不认为PostgreSQL实际上支持该功能. 解决方法
这就是我所说的“前瞻性问题”,即您可能遇到有关依赖尚未插入的行的数据约束的问题.整个事务具有各行不需要的要求.大多数数据库提供的解决此问题的工具很少.幸运的是,PostgreSQL为您提供了一些选择.
使用TOAST的非规范化“输入缓冲区” 第一种方法是向match_player []类型匹配的匹配添加一列.然后你会在比赛中存储一系列球员.这将使用触发器实现到match_player表.尽管在发展和预见??角落案件方面存在严重的处罚.我确实认为这是一个可行的选择,但它不是一个理想的选择.这通过压平表来避免前瞻性约束.但是它只能存储第0步记录.一旦人们正在进行移动……必须通过仅插入match_players来完成. 约束触发器 第二种方法是创建一个触发器函数,该函数在每个语句中运行一次,作为在事务结束时执行的初始延迟可延迟约束触发器.这将从表中提取系统列以查找插入的行,然后检查以确保匹配发生在另一个表中.这可能是解决前瞻性约束问题的最佳通用方法. (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |