Возврат столбца из INSERTED записи через обновляемое представление - PullRequest
0 голосов
/ 07 мая 2020

У меня есть представление, которое мне нужно разрешить моим пользователям обновлять и вставлять. Важно отметить, что при вставке они должны иметь возможность возвращать новое значение из вставленной строки, однако сейчас они получают NULL. Это должно быть представление, так как в SELECT представления оно должно иметь возможность возвращать значения, которые являются результатом соединения.

Мои определения базовой таблицы:

CREATE TABLE my_assets (
    asset_id bigserial not null primary key,
    asset_price NUMERIC(32,10) -- This will vary constantly via an independent process
);

CREATE TABLE my_transactions (
    id bigserial not null primary key,
    asset_id bigint not null REFERENCES my_assets(asset_id),
    some_text varchar(100)
);
INSERT INTO my_assets(asset_price) SELECT 100 as asset_price;

Мое представление, которое показывает результат таблицы:

CREATE VIEW my_transactions_view AS
SELECT tx.id, tx.asset_id, tx.some_text, a.asset_price
FROM my_transactions tx
JOIN my_assets a ON tx.asset_id = a.asset_id

Мой триггер, который позволяет вставлять в my_transactions_view:

CREATE OR REPLACE FUNCTION trigfx_insert_to_my_transactions_view()
RETURNS trigger AS
    $BODY$
BEGIN
    INSERT INTO my_transactions(asset_id, some_text)
    SELECT NEW.asset_id, NEW.some_text;
    RETURN NEW;
END
    $BODY$
    LANGUAGE 'plpgsql';

CREATE TRIGGER trig_my_transactions_view INSTEAD OF INSERT on my_transactions_view
FOR EACH ROW EXECUTE PROCEDURE trigfx_insert_to_my_transactions_view();

Пока все хорошо. Однако проблема возникает из-за попытки запустить следующее SQL:

INSERT INTO my_transactions_view(asset_id, some_text)
    SELECT 1 as asset_id, 'Hello World' as some_text
    RETURNING id, asset_id, some_text;

Возвращенная таблица возвращает NULL для ID , но я хочу вернуть недавно обновленный идентификатор из my_transactions таблица:

|---------------------|------------------|------------------|
|         ID          |     asset_id     |    some_text     |
|---------------------|------------------|------------------|
|        null         |         1        |  Hello World     |
|---------------------|------------------|------------------|

Выполнение последующего SELECT * FROM my_transactions_view ДЕЙСТВИТЕЛЬНО дает обновленный результат:

|------------------|------------------|------------------|------------------|
|         ID       |     asset_id     |    some_text     |    asset_price   |
|------------------|------------------|------------------|------------------|
|         1        |         1        |  Hello World     |  100.0000000     |
|------------------|------------------|------------------|------------------|

, но мне нужно, чтобы он был получен во время ВОЗВРАТА оператора INSERT.

Спасибо !!!

Ответы [ 2 ]

1 голос
/ 07 мая 2020

Вы можете заполнить запись new сгенерированным идентификатором:

CREATE OR REPLACE FUNCTION trigfx_insert_to_my_transactions_view()
RETURNS trigger AS
    $BODY$
BEGIN
    INSERT INTO my_transactions(asset_id, some_text)
    values (NEW.asset_id, NEW.some_text);
    new.id := lastval(); --<< this gets the generated id from the transactions table
    RETURN NEW;
END
$BODY$
LANGUAGE plpgsql;

Онлайн-пример

В качестве альтернативы вы можете использовать currval(pg_get_serial_sequence('my_transactions','id')) вместо lastval()

0 голосов
/ 12 мая 2020

Оказывается, мы можем избежать дополнительного вызова функции через SELECT INTO из CTE:

CREATE OR REPLACE FUNCTION trigfx_insert_to_my_transactions_view()
RETURNS trigger AS
    $BODY$
BEGIN
    WITH ins_q as (INSERT INTO my_transactions(asset_id, some_text)
    values (NEW.asset_id, NEW.some_text)
    RETURNING id, asset_id, some_text)
    SELECT ins_q.id, ins_q.asset_id, ins_q.some_text
    INTO NEW.id, NEW.asset_id, NEW.some_text
    FROM ins_q;
    RETURN NEW;
END
$BODY$
LANGUAGE plpgsql;

См. Онлайн-пример здесь. Я столкнулся с ошибками инициализации (lastval is not yet defined in this session) с подходом new.id := lastval();.

...