【问题标题】:Returning identity of INSERT for new INSERT with data outside of RETURNING clause使用 RETURNING 子句之外的数据返回新 INSERT 的 INSERT 标识
【发布时间】:2020-10-31 17:04:00
【问题描述】:

我使用的是 PostgreSQL 12.3。

与已提出的许多问题类似,例如this one,,但我需要使用 RETURNING 子句中不存在的另一个表中的数据。

举一个人为的例子,考虑三个表:customersproductssales,以及需要在销售点创建客户,并且需要更新销售表的场景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 在returning 子句中没有找到约束,上述显然行不通。我已尝试加入表格以提取额外数据,但无法使其正常工作。

请忽略您在表结构方面可能遇到的任何小问题,因为我正在处理的数据有数百列和许多外键。我试图将问题浓缩为最简单的形式,但冒着看起来做作的风险。

【问题讨论】:

    标签: sql postgresql sql-insert auto-increment


    【解决方案1】:

    您的示例失败,因为您没有提供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;
    

    希望这会有所帮助!

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2011-09-27
      • 2015-06-18
      • 1970-01-01
      • 2023-02-16
      • 2016-10-30
      • 2018-08-18
      • 1970-01-01
      相关资源
      最近更新 更多