如何在 Postgres 中为 Table 中的行数限制建模
How can I model a limit of number of Rows in a Table in Postgres
我目前正在学习如何在全栈 Web 开发环境中使用数据库。我想模拟一个场景,学生可以参加具有一定容量的各种活动。我已经看过这个帖子了:
How to write a constraint concerning a max number of rows in postgresql?
但不能完全应用于我的场景,因为应该可以有不同的容量,例如,当房间更新时,容量也可以改变(容量参考房间的容量列 table)
有没有一种优雅的建模方法?
我目前的解决方案是有一个容量列和一个注册量列,每个 insert/delete 获得 in-/decremented。
这种粗略的检查也会发生在客户端 atm 上,我知道出于多种原因这是一种不好的做法,我对此绝对不满意,这就是我创建此 post.
的原因
我认为至少可以使用 Postgres 函数对服务器端进行建模,但由于我还不熟悉这些函数,所以我想先问一下,是否有一种通常更好的建模方法。我正在为我的项目使用 Supabase 实例。
先谢谢大家了!
有很多方法可以做到这一点,但如果你只是想让 PostgreSQL 确保你永远不会超额预订一个事件,你可以为 INSERT
和 UPDATE
编写一个 TRIGGER你的 registration
table.
我在我的 Supabase 实例上测试了这个,因为没有什么比从 Whosebug 得到一个不起作用的专家答案更烦人的了!
CREATE TABLE person (id INTEGER UNIQUE PRIMARY KEY, firstname TEXT, lastname TEXT);
CREATE TABLE event (id INTEGER UNIQUE PRIMARY KEY, event_name TEXT, capacity INTEGER);
CREATE TABLE registration (id INTEGER UNIQUE PRIMARY KEY, event_id INTEGER , person_id INTEGER);
INSERT INTO person (id, firstname, lastname) VALUES (1, 'Bob','Barker'),(2, 'Jamie','Oliver'),(3, 'Gary ','Busey');
INSERT INTO event (id, event_name, capacity) VALUES (1, 'Fireman''s Ball', 2);
CREATE OR REPLACE FUNCTION check_registration_capacity()
RETURNS TRIGGER AS $$
BEGIN
IF (SELECT count(*) FROM registration as r1 WHERE r1.event_id = NEW.event_id) >
((SELECT capacity FROM event WHERE event.id = NEW.event_id) - 1)
THEN
RAISE EXCEPTION 'Event is full';
END IF;
RETURN NEW;
END;
$$ LANGUAGE plpgsql;
CREATE TRIGGER verify_registration_capacity
BEFORE INSERT OR UPDATE ON registration
FOR EACH ROW EXECUTE PROCEDURE check_registration_capacity();
-- register Bob for the Fireman's Ball
INSERT INTO registration (id, event_id, person_id) VALUES (1, 1, 1);
-- register Jamie for the Fireman's Ball
INSERT INTO registration (id, event_id, person_id) VALUES (2, 1, 2);
-- sorry, Gary, the next line throws an 'Event is full' error
INSERT INTO registration (id, event_id, person_id) VALUES (3, 1, 3);
我目前正在学习如何在全栈 Web 开发环境中使用数据库。我想模拟一个场景,学生可以参加具有一定容量的各种活动。我已经看过这个帖子了:
How to write a constraint concerning a max number of rows in postgresql?
但不能完全应用于我的场景,因为应该可以有不同的容量,例如,当房间更新时,容量也可以改变(容量参考房间的容量列 table)
有没有一种优雅的建模方法?
我目前的解决方案是有一个容量列和一个注册量列,每个 insert/delete 获得 in-/decremented。 这种粗略的检查也会发生在客户端 atm 上,我知道出于多种原因这是一种不好的做法,我对此绝对不满意,这就是我创建此 post.
的原因我认为至少可以使用 Postgres 函数对服务器端进行建模,但由于我还不熟悉这些函数,所以我想先问一下,是否有一种通常更好的建模方法。我正在为我的项目使用 Supabase 实例。
先谢谢大家了!
有很多方法可以做到这一点,但如果你只是想让 PostgreSQL 确保你永远不会超额预订一个事件,你可以为 INSERT
和 UPDATE
编写一个 TRIGGER你的 registration
table.
我在我的 Supabase 实例上测试了这个,因为没有什么比从 Whosebug 得到一个不起作用的专家答案更烦人的了!
CREATE TABLE person (id INTEGER UNIQUE PRIMARY KEY, firstname TEXT, lastname TEXT);
CREATE TABLE event (id INTEGER UNIQUE PRIMARY KEY, event_name TEXT, capacity INTEGER);
CREATE TABLE registration (id INTEGER UNIQUE PRIMARY KEY, event_id INTEGER , person_id INTEGER);
INSERT INTO person (id, firstname, lastname) VALUES (1, 'Bob','Barker'),(2, 'Jamie','Oliver'),(3, 'Gary ','Busey');
INSERT INTO event (id, event_name, capacity) VALUES (1, 'Fireman''s Ball', 2);
CREATE OR REPLACE FUNCTION check_registration_capacity()
RETURNS TRIGGER AS $$
BEGIN
IF (SELECT count(*) FROM registration as r1 WHERE r1.event_id = NEW.event_id) >
((SELECT capacity FROM event WHERE event.id = NEW.event_id) - 1)
THEN
RAISE EXCEPTION 'Event is full';
END IF;
RETURN NEW;
END;
$$ LANGUAGE plpgsql;
CREATE TRIGGER verify_registration_capacity
BEFORE INSERT OR UPDATE ON registration
FOR EACH ROW EXECUTE PROCEDURE check_registration_capacity();
-- register Bob for the Fireman's Ball
INSERT INTO registration (id, event_id, person_id) VALUES (1, 1, 1);
-- register Jamie for the Fireman's Ball
INSERT INTO registration (id, event_id, person_id) VALUES (2, 1, 2);
-- sorry, Gary, the next line throws an 'Event is full' error
INSERT INTO registration (id, event_id, person_id) VALUES (3, 1, 3);