使用 RETURNING 子句之外的数据为新的 INSERT 返回 INSERT 的标识

Returning identity of INSERT for new INSERT with data outside of RETURNING clause

我正在使用 PostgreSQL 12.3。

类似于许多关于此问题的问题,例如 this one, 但我需要使用来自另一个 table 的数据,该数据不在 RETURNING 子句中。

举一个人为的例子,考虑三个 table:customersproductssales,以及需要在销售点,销售 table 需要使用 usersproducts id 进行更新。

CREATE TABLE public.customers (
    id SERIAL PRIMARY KEY,
    first_name TEXT NOT NULL,
    last_name TEXT NOT NULL
) 

CREATE TABLE public.products (
    id SERIAL PRIMARY KEY,
    product TEXT NOT NULL
)

CREATE TABLE public.sales (
    id SERIAL PRIMARY KEY,
    customer_id INTEGER NOT NULL REFERENCES customers(id),
    product_id INTEGER NOT NULL REFERENCES products(id)
) 


INSERT INTO customers (first_name, last_name) VALUES ('Bob', 'Smith');
INSERT INTO customers (first_name, last_name) VALUES ('Jane', 'Doe');

INSERT INTO products (product) VALUES ('widget 1');
INSERT INTO products (product) VALUES ('widget 2');
INSERT INTO products (product) VALUES ('widget 3');

INSERT INTO sales (customer_id, product_id) VALUES (1, 1);
INSERT INTO sales (customer_id, product_id) VALUES (2, 1);
INSERT INTO sales (customer_id, product_id) VALUES (2, 2);

如果我只需要客户 ID,那么以下内容不是问题:

WITH new_customer_and_new_sale AS (

    INSERT INTO customers (first_name, last_name) VALUES ('John', 'Doe') RETURNING id
)   

INSERT INTO sales (customer_id) 

SELECT id FROM new_user_and_new_sale

因为 sales 有在返回子句中找不到的约束,上面显然行不通。我试过加入 tables 来提取额外的数据,但没能成功。

请忽略 table 结构可能存在的任何小问题,因为我正在处理的数据有数百列和许多外键。我试图将问题浓缩为最简单的形式,但可能会显得做作。

您的示例失败,因为您没有提供 product_id 的值,这是必需的。

你可以这样直接指定一个:

WITH inserted_customer AS (
    INSERT INTO customers (first_name, last_name) VALUES ('acacaca', 'Doe') RETURNING id
)
INSERT INTO sales (customer_id, product_id) 
SELECT inserted_customer.id, 2 FROM inserted_customer;

如果您想从现有产品中获取产品 ID,您可以使用子查询(或者 CTE,如果您正在做更复杂的事情)。

WITH inserted_customer AS (
    INSERT INTO customers (first_name, last_name) VALUES ('acacaca', 'Doe') RETURNING id
)
INSERT INTO sales (customer_id, product_id) 
SELECT inserted_customer.id, (SELECT id FROM products ORDER BY id DESC LIMIT 1) FROM inserted_customer;

如果您想即时插入客户和产品,可以执行两个 CTE:

WITH inserted_customer AS (
    INSERT INTO customers (first_name, last_name) VALUES ('acacaca', 'Doe') RETURNING id
),
inserted_product AS (
    INSERT INTO products (product) VALUES ('my product') RETURNING id
)   
INSERT INTO sales (customer_id, product_id) 
SELECT inserted_customer.id, inserted_product.id
FROM inserted_customer, inserted_product;

希望对您有所帮助!