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

问题描述

我有一个main.comments表,用于存储用户评论。 我正在尝试向数据库添加注释并获取一些数据作为回报。 这是我的查询

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

所以我原本希望添加评论获取所需的数据,但事实并非如此,而是出现了此错误

错误:由子查询返回的多于一行用作表达式 sql状态:21000

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

  • Postgresql 12.4

解决方法

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

(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,(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,因此条件变为TRUEusers中的所有行都将返回。

我会像这样使用CTE:

WITH ins AS (
   INSERT INTO main.comments (text,user_id)
   VALUES('sample',1)
   RETURNING 
      comment_id,user_id,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,user_id)
    VALUES('sample',1)
    RETURNING 
    comment_id,NULL AS username,updated_at;

然后更新表格

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

没有测试但是应该可以工作