我们有:
Room
Person
PersonRoom
Room
我的最大 Person
,相当于可以进入房间的最多人数。
像这样:
Room
id
maximum_persons
Person
id
name
PersonRoom
id
room_id
person_id
每次有" my_person_id
"我想和#34; my_room_id
"进入一个房间,我应该这样做:
INSERT INTO PersonRoom (room_id, person_id)
VALUES (my_room_id, my_person_id)
但如果房间已满,我不应该插入一个人即我应该做的事情(我知道这不是有效的SQL ):< / p>
@TOTAL = SELECT COUNT(*) FROM PersonRoom
WHERE room_id = my_room_id;
IF @TOTAL < (SELECT maximum_persons) FROM Room WHERE id = my_room_id:
INSERT INTO PersonRoom (room_id, person_id)
VALUES (my_room_id, my_person_id)
我想在数据库端处理这个问题
答案 0 :(得分:1)
在SQLite中,您可以使用trigger
来阻止此操作CREATE TRIGGER max_persons_check
BEFORE INSERT ON PersonRoom
WHEN (SELECT COUNT(*) FROM PersonRoom WHERE room_id = NEW.room_id)
>= (SELECT maximum_persons FROM Room WHERE id = NEW.room_id)
BEGIN
SELECT RAISE(FAIL, "too many persons in this room");
END;
或者只是执行查询以在代码中进行检查。 (在SQLite中,所有事务都是可序列化的。)
答案 1 :(得分:0)
我只能代表PostgreSQL。
有两种解决方案:
在一个事务中运行SELECT
和INSERT
,并在执行personroom
之前锁定表SELECT
。
您需要ACCESS EXCLUSIVE
锁定模式,这意味着所有此类操作都已序列化。这对并发性有害,但简单而安全。
在一次SELECT
交易中运行INSERT
和SERIALIZABLE
。
这将允许并发修改,但仍然可以防止在序列化执行顺序中不可能发生的任何事情。如果存在冲突,其中一个事务将收到序列化错误,并且必须重试该事务。