Объяснение
Это связано с поведением общих табличных выражений в PostgreSQL.
По документам (https://www.postgresql.org/docs/current/queries-with.html):
Подразделенияв WITH выполняются одновременно друг с другом и с основным запросом. Поэтому при использовании операторов модификации данных в WITH порядок, в котором фактически происходят указанные обновления, непредсказуем. Все операторы выполняются с одним и тем же снимком (см. главу 13).), поэтому они не могут «видеть» влияние друг друга на целевые таблицы. Это смягчает последствия непредсказуемости фактического порядка обновлений строк и означает, что данные RETURNING являются единственным способом передачи изменений между различными под-операторами WITH иосновной запрос. Примером этого является то, что в
WITH t AS (
UPDATE products SET price = price * 1.05
RETURNING *
)
SELECT * FROM products;
внешний SELECT будет возвращать исходные цены до действия ОБНОВЛЕНИЕ ...
последнее предложение (ниже фрагмента кода) имеет решающее значение.
Ваш запрос к auВ конце таблицы возвращаются данные, которые были до операторов вставки в CTE.
Альтернативный подход
Альтернативный подход заключается в выполнении этой работы.в функции, где вы можете использовать переменные.
Сначала предложим некоторые изменения в ваших таблицах:
CREATE TABLE author
(
id SERIAL PRIMARY KEY,
name TEXT NOT NULL UNIQUE -- Unique for ON CONFLICT later
);
CREATE TABLE book
(
id SERIAL PRIMARY KEY,
title TEXT NOT NULL,
author_id INT NOT NULL REFERENCES author (id),
UNIQUE (title, author_id) -- Prevent duplicates
);
Пример функции:
CREATE OR REPLACE FUNCTION add_book (in_book_title TEXT, in_author_name TEXT)
RETURNS TABLE
(
author_id INT,
book_id INT,
author_name TEXT,
book_title TEXT
)
AS $$
#variable_conflict use_column
DECLARE
var_author_id INT;
var_book_id INT;
BEGIN
-- Upsert author, return id
INSERT INTO author (name)
VALUES (in_author_name)
ON CONFLICT (name) DO
UPDATE SET name = EXCLUDED.name -- Do update to allow use of returning
RETURNING id INTO var_author_id;
-- Upsert book, return id
INSERT INTO book (title, author_id)
VALUES (in_book_title, var_author_id)
ON CONFLICT (title, author_id) DO
UPDATE SET title = EXCLUDED.title -- Do update to allow use of returning
RETURNING id INTO var_book_id;
-- Return the record using your join (similar)
RETURN QUERY
SELECT a.id, b.id, a.name, b.title
FROM author a
INNER JOIN book b
ON a.id = b.author_id
WHERE b.id = var_book_id;
END;
$$ LANGUAGE PLPGSQL VOLATILE;
Использование:
SELECT * FROM add_book('Artemis Fowl', 'Eoin Colfer');