Quassnoi đã đúng; một trình kích hoạt sẽ là cách tốt nhất để đạt được điều này.
Đây là mã:
CREATE OR REPLACE FUNCTION enforce_photo_count() RETURNS trigger AS $$
DECLARE
max_photo_count INTEGER := 10;
photo_count INTEGER := 0;
must_check BOOLEAN := false;
BEGIN
IF TG_OP = 'INSERT' THEN
must_check := true;
END IF;
IF TG_OP = 'UPDATE' THEN
IF (NEW.owner != OLD.owner) THEN
must_check := true;
END IF;
END IF;
IF must_check THEN
-- prevent concurrent inserts from multiple transactions
LOCK TABLE photos IN EXCLUSIVE MODE;
SELECT INTO photo_count COUNT(*)
FROM photos
WHERE owner = NEW.owner;
IF photo_count >= max_photo_count THEN
RAISE EXCEPTION 'Cannot insert more than % photos for each user.', max_photo_count;
END IF;
END IF;
RETURN NEW;
END;
$$ LANGUAGE plpgsql;
CREATE TRIGGER enforce_photo_count
BEFORE INSERT OR UPDATE ON photos
FOR EACH ROW EXECUTE PROCEDURE enforce_photo_count();
Tôi đã bao gồm khóa bảng để tránh các trường hợp trong đó hai lần xử lý đồng thời sẽ tính ảnh cho một người dùng, thấy rằng số lượng hiện tại là 1 dưới giới hạn và sau đó chèn cả hai, điều này sẽ khiến bạn vượt quá giới hạn 1. Nếu đó không phải là mối quan tâm của bạn, tốt nhất là bạn nên tháo khóa vì nó có thể trở thành nút thắt cổ chai với nhiều lần chèn / cập nhật.