排除多个表的约束?
Exclude constraint across many tables?
考虑以下 table:
todos:
id | floor_start | floor_end
----+-------------+-------------
1 | 10 | 20
2 | 20 | 30
3 | 30 | 40
4 | 35 | 45
为了防止同一楼层有 2 部电梯,我可以选择:
EXCLUDE USING gist(int4range(start,end) with &&)
在这种情况下,3 将与 4 冲突。
不过我确实有加入 table:
occupations:
todo_id | room_id
---------+----------
3 | 1
4 | 2
所以 (3) 在 room_id = 1
中完成,(4) 在 room_id = 2
中完成,它们不会冲突。
1 & 2 没有加入的条目 table,所以所有房间都被占用了。
我知道 exclude
只会在当前 table 的范围内工作 - 我该如何处理它?我应该制作多余的列吗?
将 room_id
添加到 todos
不是一个选项,因为这只是一个最小的例子,在现实生活中我有更多的 0..N 连接。
您可以编写一个 AFTER INSERT OR UPDATE
触发器来检查条件并在不满足条件时抛出错误。
但请注意,此类触发器存在竞争条件——两个并发数据修改无法看到彼此的效果。因此,您要么必须使用 SERIALIZABLE
隔离级别,要么使用 SELECT ... FOR UPDATE
.
锁定触发器中受影响的行
考虑以下 table:
todos:
id | floor_start | floor_end
----+-------------+-------------
1 | 10 | 20
2 | 20 | 30
3 | 30 | 40
4 | 35 | 45
为了防止同一楼层有 2 部电梯,我可以选择:
EXCLUDE USING gist(int4range(start,end) with &&)
在这种情况下,3 将与 4 冲突。
不过我确实有加入 table:
occupations:
todo_id | room_id
---------+----------
3 | 1
4 | 2
所以 (3) 在 room_id = 1
中完成,(4) 在 room_id = 2
中完成,它们不会冲突。
1 & 2 没有加入的条目 table,所以所有房间都被占用了。
我知道 exclude
只会在当前 table 的范围内工作 - 我该如何处理它?我应该制作多余的列吗?
将 room_id
添加到 todos
不是一个选项,因为这只是一个最小的例子,在现实生活中我有更多的 0..N 连接。
您可以编写一个 AFTER INSERT OR UPDATE
触发器来检查条件并在不满足条件时抛出错误。
但请注意,此类触发器存在竞争条件——两个并发数据修改无法看到彼此的效果。因此,您要么必须使用 SERIALIZABLE
隔离级别,要么使用 SELECT ... FOR UPDATE
.