【问题标题】:Insert many rows returning id and update that ids in another table插入许多返回 id 的行并在另一个表中更新该 id
【发布时间】:2017-03-18 15:23:01
【问题描述】:

我正在使用 PostgreSQL,我的 sql 结构:

CREATE TEMP TABLE users (
    id_user serial,
    user_name varchar,
    id_user_description int
);

CREATE TEMP TABLE user_description  (
    id_user_description serial,
    age int
);

users 表有一些用户:

INSERT INTO users (user_name)
SELECT column1
FROM (
    VALUES
    ('John'),
    ('Amanda')
) t;

我正在尝试将数据插入表 user_description,并且我还需要将插入的行 ID 更新到表 users。我的查询是这样的:

WITH inserted_user_description AS (
    INSERT INTO user_description (age)
    SELECT age
    FROM (
        SELECT users.id_user,
            t.column1 AS age,
            t.column2 AS user_name
        FROM (
            VALUES
            (21, 'John'),
            (28, 'Amanda')
        ) t
        INNER JOIN users ON users.user_name = t.column2
    ) tt
    RETURNING id_user_description, tt.id_user
)
UPDATE users SET id_user_description = t.id_user_description
FROM (
    SELECT id_user_description, id_user
    FROM inserted_user_description 
) t
WHERE users.id_user = t.id_user;

但我得到错误:

错误:表“tt”缺少 FROM 子句条目 第 15 行:返回 id_user_description、tt.id_user

我该如何解决这个问题?

【问题讨论】:

  • 错误信息与贴出的代码不符
  • 什么意思?为什么不?当然,您应该删除 <...> 我删除了更多列的地方
  • 如果需要帮助,请输入原始sql和错误
  • 我添加了具体的案例和结构
  • “可选的 RETURNING 子句导致 INSERT 根据实际插入的每一行计算并返回值”postgresql.org/docs/9.5/sql-insert.html tt.id_user 不存在于插入的行中。

标签: sql postgresql


【解决方案1】:

这是一个有效的 SQL sn-p,它说明了它是如何工作的。您有 2 张桌子 ab。当您在 a 中插入行时,您希望更新 b

ab 架构:

CREATE TABLE a (
    id serial unique,
    some_int int
);

CREATE TABLE b (
    id serial,
    a_id int,
    some_date timestamp
);

让我们在b 中插入一些行以匹配我们将在a 中插入的行(它们是我们将更新的行):

INSERT INTO b (a_id, some_date)
SELECT generate_series, null
FROM generate_series(1, 100);

现在,这里是如何在a 中插入行并在b 中更新等效行:

WITH inserted as (
    INSERT INTO a (some_int)
    SELECT *
    FROM generate_series(1, 10)
    RETURNING id
)
UPDATE b
SET some_date = NOW()
FROM inserted i
WHERE i.id = b.a_id
;

如您所见,a 中插入了 10 行,b 中更新了 10 行等效:

test=# SELECT * FROM a;
 id | some_int 
----+----------
  1 |        1
  2 |        2
  3 |        3
  4 |        4
  5 |        5
  6 |        6
  7 |        7
  8 |        8
  9 |        9
 10 |       10
(10 rows)

test=# SELECT * FROM b WHERE some_date IS NOT NULL;
 id | a_id |         some_date          
----+------+----------------------------
  1 |    1 | 2017-03-16 17:48:32.257217
  2 |    2 | 2017-03-16 17:48:32.257217
  3 |    3 | 2017-03-16 17:48:32.257217
  4 |    4 | 2017-03-16 17:48:32.257217
  5 |    5 | 2017-03-16 17:48:32.257217
  6 |    6 | 2017-03-16 17:48:32.257217
  7 |    7 | 2017-03-16 17:48:32.257217
  8 |    8 | 2017-03-16 17:48:32.257217
  9 |    9 | 2017-03-16 17:48:32.257217
 10 |   10 | 2017-03-16 17:48:32.257217
(10 rows)

更新:

在您的具体情况下,我认为您的查询应该是这样的(在没有架构的情况下总是很难编写查询!):

WITH inserted_user_description AS (
    INSERT INTO user_description (age, <...>)
    SELECT u.id_user,
        t.column1 AS age,
        <...>
        t.column8 AS user_name
    FROM (
        VALUES
        (21, <...> ,'John'),
        (28, <...> ,'Amanda'),
        <...>
    ) t
    JOIN users u ON u.user_name = t.user_name
    RETURNING id_user_description, u.id_user
)
UPDATE users
SET id_user_description = t.id_user_description
FROM inserted_user_description t
WHERE users.id_user = t.id_user;

【讨论】:

  • 您的第一个示例与我的情况不同,我的情况下的 b.id 和 b.a_id 可以不同。
  • 至于更新。我有错误:INSERT 的表达式比目标列多
  • 我已经用架构的具体情况更新了问题
猜你喜欢
  • 2020-06-23
  • 1970-01-01
  • 1970-01-01
  • 2011-07-31
  • 1970-01-01
  • 2015-07-15
  • 1970-01-01
  • 2019-11-04
  • 1970-01-01
相关资源
最近更新 更多