'how to add contraint on table using view

I try to use View to create a constraint on a Mysql Table.

I have one table with cinemas sessions and one other for tickets, the goal is we can't sell tickets when the session is full.

The session has a number of places, for example, 300 places. When one ticket is sold, the number of places decreases. The rest is 299. (this is what I do with a view)

I will check before the data is written if the amount of places is enough. The condition is place_left >= number (of tickets wanted).

For example, the rest of places is 5 and a user wants 6 places, the request is rejected because the condition is not true. The condition is place_left >= number (of tickets wanted).

Actually I use two views to do that (not tested, just created), I think I can do this in one shot but I failed.

I have seen this possibility here: https://dev.mysql.com/doc/refman/8.0/en/view-check-option.html

I first tried something like that:

CREATE VIEW view_place_left AS 
SELECT sessions.id, 
    (SELECT places FROM rooms WHERE id=sessions.room_id)-(SELECT SUM(number) AS count FROM tickets WHERE session_id=sessions.id)
    AS place_left FROM sessions WHERE place_left>=0
WITH CHECK OPTION;

, but the part WHERE place_left>=0 is not working.

So I do the job in two steps

The first view:

CREATE VIEW view_place_left 
    AS SELECT sessions.id, 
    (SELECT places FROM rooms WHERE id=sessions.room_id)-(SELECT SUM(number) AS count FROM tickets WHERE session_id=sessions.id)
    AS place_left FROM sessions;

And the second view:

CREATE VIEW check_view_place_left AS
    SELECT id, place_left FROM view_place_left WHERE place_left>=0
    WITH CHECK OPTION;

That seems ok, but I think it's possible to do the job in a single view, someone can help?

I work with MySql 8.0

First Add : create sessions table :

CREATE TABLE IF NOT EXISTS sessions
(
    id VARCHAR(36) NOT NULL PRIMARY KEY DEFAULT (UUID()),
    movie_id VARCHAR(36),
    room_id VARCHAR(36),
    date DATETIME,
    FOREIGN KEY (movie_id) REFERENCES movies(id) ON DELETE CASCADE,
    FOREIGN KEY (room_id) REFERENCES rooms(id) ON DELETE CASCADE
) ENGINE = InnoDB CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci;

Create tickets table :

CREATE TABLE IF NOT EXISTS tickets
(
    id VARCHAR(36) NOT NULL PRIMARY KEY DEFAULT (UUID()),
    session_id VARCHAR(36) NOT NULL,
    user_id VARCHAR(36) NOT NULL,
    price_id VARCHAR(36) NOT NULL,
    number INT NOT NULL,
    date DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
    paid INT,    
    FOREIGN KEY (session_id) REFERENCES sessions(id) ON DELETE CASCADE ON UPDATE CASCADE,
    FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE ON UPDATE CASCADE,
    FOREIGN KEY (price_id) REFERENCES prices(id) ON DELETE CASCADE ON UPDATE CASCADE    
) ENGINE = InnoDB CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci;


Solution 1:[1]

SOLUTION So i found my solution. To Check and validate the place left, i just need a trigger before insert. Here is my code :

\! echo "\033[33m*** Create trigger on 'tickets'  ***\033[m";
DELIMITER $$
CREATE TRIGGER check_places BEFORE INSERT ON tickets
    FOR EACH ROW
    BEGIN
        IF PlaceLeft(NEW.session_id, NEW.number) != 1 THEN SIGNAL sqlstate '45000' set message_text = "No enough places";
    END IF;
END$$
DELIMITER ;

The function PlaceLeft

DELIMITER $$
CREATE FUNCTION PlaceLeft(session_id VARCHAR(36), number INT)
RETURNS INT DETERMINISTIC
BEGIN
    DECLARE places INT;
    SELECT place_left INTO places FROM view_place_left;
    IF places>=number THEN RETURN 1;
    ELSE RETURN 0;
    END IF;

END$$

Maybe that can help another lost soul :)

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 David51