2

我确信有一种方法可以搜索这个以找到现有的答案,但大多数结果要么通过阻止更新来强制执行唯一列,要么在两行之间交换唯一值(这在 MySQL 中显然被破坏了) )。我不想交换我只想将当前具有唯一值的行更新为NULL.

以下是我如何使用两个查询来做到这一点(使用两列表,其中第二列 person_id 必须是唯一的):

UPDATE bathroom_occupant
SET person_id = NULL
WHERE person_id = '$person_id';

UPDATE bathroom_occupant
SET person_id = '$person_id' 
WHERE bathroom_id = '$new_bathroom_id';

person_id以上从当前配对中删除了bathroom_id,然后将其放置在person_idbathroom_id配对中。我想要的是只有一个查询,它要么使用某种形式COALESCE将一行设置为 NULL,另一行设置为,person_id要么使用一些表级规则,类似于我认为的唯一约束,其中运行第二个对于已设置为唯一值的任何其他行,单独查询会自动将列值设置为 NULL。

举一个更简单的例子:我知道可以使用唯一约束来阻止学生注册同一班级的两个部分。但不是通过阻塞来阻止,是否可以通过“移动”来阻止?

4

1 回答 1

1

这比我想象的要棘手;首先,我按照 acfrancis 在评论中的建议使用触发器进行了调查,但是在 MySQL 触发器中,您无法更新触发器所在的表 - 因此 INSERT 触发器和 UPDATE 触发器都已退出。如果您的 DBMS 支持它,这将是一种可能性。

所以,你留下了约束概念,你需要考虑你在限制什么。如果您想确保一个人没有被记录为在多个浴室中,那么您可以添加相关约束,如下所示:

mysql> DROP TABLE IF EXISTS bathroom_occupant;
Query OK, 0 rows affected (0.03 sec)

mysql> CREATE TABLE bathroom_occupant (bathroom_id INT, person_id INT);
Query OK, 0 rows affected (0.12 sec)

mysql> ALTER TABLE bathroom_occupant ADD CONSTRAINT
    -> UNIQUE INDEX person_id (person_id);
Query OK, 0 rows affected (0.15 sec)
Records: 0  Duplicates: 0  Warnings: 0

然后人 1 进入浴室 1,人 2 进入浴室 2

mysql> INSERT INTO bathroom_occupant (bathroom_id, person_id) VALUES (1, 1);
Query OK, 1 row affected (0.03 sec)

mysql> INSERT INTO bathroom_occupant (bathroom_id, person_id) VALUES (2, 2);
Query OK, 1 row affected (0.01 sec)

然后,当您想要更新某人所在的浴室时,您可以使用 INSERT 查询并添加 ON DUPLICATE KEY UPDATE 语句。下面的人 1 移动到浴室 2

mysql> INSERT INTO bathroom_occupant (bathroom_id, person_id) VALUES (2, 1)
    -> ON DUPLICATE KEY UPDATE bathroom_id = VALUES(bathroom_id);
Query OK, 2 rows affected (0.02 sec)

mysql> SELECT * FROM bathroom_occupant;
+-------------+-----------+
| bathroom_id | person_id |
+-------------+-----------+
|           2 |         1 |
|           2 |         2 |
+-------------+-----------+
2 rows in set (0.00 sec)

如您所见,浴室 2 有两条记录 - 因为我们的限制是只有一个人在不超过一间浴室。在现实世界中,这没关系——两个人可以进入同一个浴室。而且我认为它适用于您的另一个示例 - 学生注册到同一班级的两个部分(许多学生可以在同一部分,但一个学生只能在一个部分)。

但是,您将您的表命名为浴室占用者——对我来说,这个名称表明该表显示了谁是每个浴室的居住者——也许您希望每个浴室只有一个居住者。如果这是你所需要的——即你有一个限制,每个人只能在一个浴室里,每个浴室只能容纳一个人——那么这变得更加困难。我认为当人 1 进入时将人 2 从浴室 2 踢出的逻辑超出了 MySQL 在内部可以做的事情。如果要在表上添加另一个约束,这次是针对浴室 ID,则插入将失败,因为 ON DUPLICATE KEY UPDATE 语句仅修复了一条记录的问题。

如果您很高兴多个人可以在一个浴室里,那么您可以在想要将某人放入浴室时使用以下代码:

INSERT INTO bathroom_occupant (bathroom_id, person_id) 
VALUES ('$new_bathroom_id', '$person_id')
ON DUPLICATE KEY UPDATE bathroom_id = VALUES(bathroom_id);

这是一个查询 - 根据要求。:-)

于 2013-11-11T00:45:12.263 回答