PostgreSQL:用作表达式的子查询返回的多行

PostgreSQL: more than one row returned by a subquery used as an expression

我有一个 main.comments table 存储用户评论的地方。 我正在尝试向数据库添加评论并获取一些数据作为 return。 这是我的查询

INSERT INTO main.comments (text, post_id, user_id)
VALUES('sample', 11, 1)
RETURNING 
comment_id,
text,
post_id,
(SELECT username FROM main.users WHERE main.users.user_id = user_id) AS username,
created_at,
updated_at

所以我希望添加评论并获得我想要的数据,但事实并非如此,相反我得到了这个错误

ERROR: more than one row returned by a subquery used as an expression SQL state: 21000

我认为我的子查询有问题,所以我单独使用它并且在 return 中只得到一行。 所以我在子查询中使用了 LIMIT 1 并得到了我期望的结果,但这在我的查询中没有意义。有人可以解释这种行为吗? 而且我的 main.users table 不包含任何 user_id 重复项,因为我使用的是 SERIAL 类型。

真正的罪魁祸首是你代码中的这一行

(SELECT username FROM main.users WHERE main.users.user_id = user_id)

像这样尝试:

INSERT INTO comments (text, post_id, user_id)
VALUES('sample', 11, 1)
RETURNING 
comment_id,
text,
post_id,
(SELECT username FROM users t1 WHERE t1.user_id = comments.user_id) AS username,
created_at,
updated_at

DEMO:

I have removed the schema name for clarity

问题是您的子查询中的 user_id 不是 指的是 main.comments 中新插入的行,而是 main.users ,因此条件变为 TRUE 并返回 users 中的所有行。

我会像这样使用 CTE:

WITH ins AS (
   INSERT INTO main.comments (text, post_id, user_id)
   VALUES('sample', 11, 1)
   RETURNING 
      comment_id,
      text,
      post_id,
      user_id,
      created_at,
      updated_at
)
SELECT ins.comment_id,
       ins.text,
       ins.post_id,
       u.username,
       ins.created_at,
       ins.updated_at
FROM ins
   JOIN main.users AS u ON ins.user_id = u.user_id;

您可以先输入空白值

       INSERT INTO main.comments (text, post_id, user_id)
    VALUES('sample', 11, 1)
    RETURNING 
    comment_id,
    text,
    post_id,
    NULL AS username,
    created_at,
updated_at;

然后更新您的 table

UPDATE main.comment 
SET username = (SELECT username )
FROM main.users 
WHERE main.users.user_id = main.comment.user_id;

没有测试但应该可以工作