I have a table showtime and a table ticket.
CREATE TABLE showtime (
showtime_id SERIAL PRIMARY KEY,
theatre_id INT REFERENCES theatre(theatre_id),
showroom_id INT REFERENCES showroom(showroom_id),
movie_id INT REFERENCES movie(movie_id),
start_time TIME,
end_time TIME,
show_date DATE
);
CREATE TABLE ticket (
showtime_id INT REFERENCES showtime(showtime_id),
seat_number SERIAL UNIQUE,
price NUMERIC(1000, 2) NOT NULL,
time_bought TIME,
date_bought DATE,
wasUsed BOOLEAN,
PRIMARY KEY (showtime_id, seat_number)
);
As you can see, each row in showtime will have a unique showtime_id. What I want to happen is when a new ticket is added, the seat_number should auto-increment from the last value tied with showtime_id:
ticket
showtime_id | seat_number | instead_of |
1 | 1 | 1 |
1 | 2 | 2 |
1 | 3 | 3 |
1 | 4 | 4 |
2 | 1 | 5 |
2 | 2 | 6 |
3 | 1 | 7 |
4 | 1 | 8 |
Is this possible in PostgreSQL?
Rephrasing your question, this is what you want: Whenever you INSERT ticket with a certain showtime_id you want to assign seat_number to the next higher number than already present in ticket for that showtime_id. So what is the highest seat_number already present? Simple:
SELECT max(seat_number)
FROM ticket
WHERE showtime_id = ?; -- The ? being a parameter placeholder in languages like Java
The seat_number data type should not be serial because you will have duplicate seat numbers for different showtimes_ids. Make it a simple integer.
In a single INSERT statement:
INSERT INTO ticket VALUES
(45,
(SELECT max(seat_number) FROM ticket WHERE showtime_id = 45) + 1,
...
);
To shield this logic from your users or application, you can use an insert trigger to avoid an erroneous or illegal (PK violation) seat number being entered:
CREATE FUNCTION assign_showtime_seat() RETURNS TRIGGER AS $$
BEGIN
SELECT max(seat_number) + 1 INTO NEW.seat_number
FROM ticket
WHERE showtime_id = NEW.showtime_id;
RETURN NEW;
END;
$$ LANGUAGE plpgsql;
CREATE TRIGGER tr_assign_showtime_seat
BEFORE INSERT ON ticket
FOR EACH ROW EXECUTE PROCEDURE assign_showtime_seat();
There is a small chance that you encounter a concurrency problem where two tickets for the same showtime_id are entered almost simultaneously. The first insert enters the trigger and computes a new seat_number. Before the INSERT completes the second ticket insert enters the trigger and computes the same seat_number. Either one then manages the actual INSERT and completes, the second ticket entry then fails on insert with a duplicate PRIMARY KEY violation. The documentation provides an example of recovering from such a concurrency problem.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With