Как обновить поле таблицы, после обновления другого поля

У меня есть две таблицы

CREATE TABLE account (
    id SERIAL PRIMARY KEY,
    username VARCHAR NOT NULL,
    email VARCHAR NOT NULL UNIQUE,
    phone VARCHAR NOT NULL UNIQUE
);

CREATE TABLE ticket (
    id SERIAL PRIMARY KEY,
    row INT NOT NULL,
    col INT NOT NULL,
    price INT NOT NULL CHECK (price > 0),
    status VARCHAR NOT NULL,
    account_id INT REFERENCES account(id)
);

Входные данные

insert into account(username, email, phone) values ('Kirill', '[email protected]', '+79653248496');
insert into account(username, email, phone) values ('Ivan', '[email protected]', '+79872753471');

insert into ticket(row, col, price, status, account_id) values (1, 1, 500, 'Free', null);
insert into ticket(row, col, price, status, account_id) values (1, 2, 550, 'Free', null);
insert into ticket(row, col, price, status, account_id) values (1, 3, 500, 'Free', null);
insert into ticket(row, col, price, status, account_id) values (2, 1, 600, 'Free', null);
insert into ticket(row, col, price, status, account_id) values (2, 2, 650, 'Free', null);
insert into ticket(row, col, price, status, account_id) values (2, 3, 600, 'Free', null);
insert into ticket(row, col, price, status, account_id) values (3, 1, 650, 'Free', null);
insert into ticket(row, col, price, status, account_id) values (3, 2, 700, 'Free', null);
insert into ticket(row, col, price, status, account_id) values (3, 3, 650, 'Free', null);

Как видно по умолчанию в таблице ticket поле status = Free, а account_id = null. Необходимо сделать так, чтобы после добавления account_id в какую-либо строку, например

update ticket set account_id = 1 where id = 5;

Поле status у данного элемента менялось на Taken. Я предположил, что необходимо создать функцию и триггер, написал такой код

CREATE FUNCTION update_status() RETURNS trigger AS $update_status$
BEGIN
    IF new.account_id IS NOT NULL THEN
        update ticket set status = 'Taken' where id = old.id;
    END IF;
END;
$update_status$ LANGUAGE plpgsql;

CREATE TRIGGER update_status
    AFTER INSERT OR UPDATE ON ticket
    FOR EACH ROW EXECUTE PROCEDURE update_status();

У меня вылетает ошибка переполнения памяти, ошибка в строке

update ticket set status = 'Taken' where id = old.id;

Но как сделать правильно я не понимаю, с триггерами и функциями работал крайне редко, помогите пожалуйста


Ответы (1 шт):

Автор решения: Akina

Используйте generated column:

CREATE TABLE ticket (
    id SERIAL PRIMARY KEY,
    row INT NOT NULL,
    col INT NOT NULL,
    price INT NOT NULL CHECK (price > 0),
    status VARCHAR NOT NULL GENERATED ALWAYS AS (CASE WHEN account_id IS NULL THEN 'Free' ELSE 'Taken' END) STORED,
    account_id INT REFERENCES account(id)
);

https://dbfiddle.uk/?rdbms=postgres_12&fiddle=0295d811566fc6ca32161ee6377b19d7

→ Ссылка