SQL新手求助:如何约束Games表Winner为同记录Player_1/Player_2?是否为外键?
问题解答
一、确保Winner字段值为Player_1或Player_2的方法
你之前的CHECK约束写法存在语法错误,收到的错误提示翻译为:CHECK约束中禁止使用子查询(实际你的写法并非子查询,而是误用了IN的语法——IN后需跟括号包裹的字段列表,而非单个字段)。
方法1:修正CHECK约束写法
大多数现代数据库(如PostgreSQL、SQL Server、MySQL 8.0+)支持直接通过CHECK约束实现:
CREATE TABLE Games( Player_1 VARCHAR NOT NULL, Player_2 VARCHAR NOT NULL, Winner VARCHAR NOT NULL CHECK(Winner IN (Player_1, Player_2)), PRIMARY KEY(Player_1, Player_2) );
方法2:用触发器兼容低版本数据库
如果你的数据库对CHECK约束支持有限(如MySQL 8.0之前的版本),可以通过触发器强制校验:
-- MySQL插入前校验触发器 DELIMITER // CREATE TRIGGER check_winner_insert BEFORE INSERT ON Games FOR EACH ROW BEGIN IF NEW.Winner NOT IN (NEW.Player_1, NEW.Player_2) THEN SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT = 'Winner必须是本场比赛的Player_1或Player_2'; END IF; END // DELIMITER ; -- MySQL更新前校验触发器(防止修改后违反规则) DELIMITER // CREATE TRIGGER check_winner_update BEFORE UPDATE ON Games FOR EACH ROW BEGIN IF NEW.Winner NOT IN (NEW.Player_1, NEW.Player_2) THEN SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT = 'Winner必须是本场比赛的Player_1或Player_2'; END IF; END // DELIMITER ;
二、Winner是否属于外键?
Winner本身不是外键——外键的作用是关联到另一张表的主键,确保字段值是关联表中存在的合法数据。
如果你的系统有单独存储玩家信息的Players表,此时Player_1、Player_2和Winner都应该设为外键,关联到Players表的主键,既保证玩家是系统内的合法用户,又进一步约束Winner的合法性:
-- 先创建玩家表 CREATE TABLE Players( Player_ID VARCHAR PRIMARY KEY, Nickname VARCHAR NOT NULL, -- 其他玩家信息字段,如等级、注册时间等 ); -- 创建关联外键的Games表 CREATE TABLE Games( Player_1 VARCHAR NOT NULL, Player_2 VARCHAR NOT NULL, Winner VARCHAR NOT NULL CHECK(Winner IN (Player_1, Player_2)), PRIMARY KEY(Player_1, Player_2), FOREIGN KEY(Player_1) REFERENCES Players(Player_ID), FOREIGN KEY(Player_2) REFERENCES Players(Player_ID), FOREIGN KEY(Winner) REFERENCES Players(Player_ID) );
内容的提问来源于stack exchange,提问作者Miguel Alves
相关产品推荐
相关产品推荐

