MYSQL - 从 Select "itself" 检查可能吗?
MYSQL - Check from Select "itself" possible?
我刚开始 mysql,我不知道进行检查的方法是否正确,或者我走错了方向。
我在 table 中有一个名为 user_num 的 varchar。我需要检查当我插入时,user_num_list 的值必须在 [1,n] 之间,即 "n" 具有相同组的对象的数量有新的对象。
我不会说英语,我敢肯定这有点难以理解,而且为了表达自己,所以有一些代码:
create table player(
group varchar(15),
user_num int(15),
CONSTRAINT ck_player_user CHECK( user_num > 0 AND user_num < SELECT count(*) FROM player WHERE player.group=group)
)ENGINE=InnoDB;
我不知道我是否可以在 CHECK 语句中 "SELECT" 而且我也不知道如何表达 "player.group=group" 意味着该组(新插入 player_group)必须是同样有player.group
谢谢。
你运气不好。
首先,MySQL在8.0.16版本之前不验证CHECK约束。如果您使用的 MySQL 版本早于此版本,MySQL 将记录 CHECK 约束并 默默地忽略它
.
其次,为了强制执行此约束,您需要在其中使用子查询,而 MySQL 不允许将子查询作为 CHECK
约束的一部分。请参阅 13.1.20.7 CHECK Constraints 字面意思:
- Subqueries are not permitted.
CHECK 条件下的子查询的问题是它实际上是不可能实现的。考虑一下当您在此 table 中删除一行时会发生什么。相应组的计数将减少,这可能会违反另一行的 CHECK 约束。系统需要重新评估每一行的支票。如果现在 table 中有一百万行,则每次插入、删除或更新一行时都需要执行一百万个查询。如果您还允许交叉 table 语句,则需要根据任何数据更改重新评估数据库中的所有检查。
理论上可以生成 "reverse check"。系统需要确定哪些操作可能违反检查。在您的情况下,这将是删除一行或更新一个组。 "reverse check" 可能是
NOT EXISTS (
SELECT *
FROM player p
WHERE p.group = OLD.group
AND p.user_num > (SELECT COUNT(*) from player p WHERE p.group = OLD.group)
)
我想你会同意,很难实施一个能够生成这样的反向支票的系统。查询可能比您的复杂得多。对于某些查询,甚至可能不存在反向检查。如果你看看 implement the CHECK constraint 花了多长时间 - 我不希望在未来十年内允许任何子查询。
所以我会说 - 你的选择是:
- 在触发器中执行检查
- 在应用程序代码中执行检查
- 更改要求
我更喜欢最后一个。
我刚开始 mysql,我不知道进行检查的方法是否正确,或者我走错了方向。
我在 table 中有一个名为 user_num 的 varchar。我需要检查当我插入时,user_num_list 的值必须在 [1,n] 之间,即 "n" 具有相同组的对象的数量有新的对象。
我不会说英语,我敢肯定这有点难以理解,而且为了表达自己,所以有一些代码:
create table player(
group varchar(15),
user_num int(15),
CONSTRAINT ck_player_user CHECK( user_num > 0 AND user_num < SELECT count(*) FROM player WHERE player.group=group)
)ENGINE=InnoDB;
我不知道我是否可以在 CHECK 语句中 "SELECT" 而且我也不知道如何表达 "player.group=group" 意味着该组(新插入 player_group)必须是同样有player.group
谢谢。
你运气不好。
首先,MySQL在8.0.16版本之前不验证CHECK约束。如果您使用的 MySQL 版本早于此版本,MySQL 将记录 CHECK 约束并 默默地忽略它 .
其次,为了强制执行此约束,您需要在其中使用子查询,而 MySQL 不允许将子查询作为 CHECK
约束的一部分。请参阅 13.1.20.7 CHECK Constraints 字面意思:
- Subqueries are not permitted.
CHECK 条件下的子查询的问题是它实际上是不可能实现的。考虑一下当您在此 table 中删除一行时会发生什么。相应组的计数将减少,这可能会违反另一行的 CHECK 约束。系统需要重新评估每一行的支票。如果现在 table 中有一百万行,则每次插入、删除或更新一行时都需要执行一百万个查询。如果您还允许交叉 table 语句,则需要根据任何数据更改重新评估数据库中的所有检查。
理论上可以生成 "reverse check"。系统需要确定哪些操作可能违反检查。在您的情况下,这将是删除一行或更新一个组。 "reverse check" 可能是
NOT EXISTS (
SELECT *
FROM player p
WHERE p.group = OLD.group
AND p.user_num > (SELECT COUNT(*) from player p WHERE p.group = OLD.group)
)
我想你会同意,很难实施一个能够生成这样的反向支票的系统。查询可能比您的复杂得多。对于某些查询,甚至可能不存在反向检查。如果你看看 implement the CHECK constraint 花了多长时间 - 我不希望在未来十年内允许任何子查询。
所以我会说 - 你的选择是:
- 在触发器中执行检查
- 在应用程序代码中执行检查
- 更改要求
我更喜欢最后一个。