postgresql 如何在子查询的结果中插入多个值?

8qgya5xd  于 6个月前  发布在  PostgreSQL
关注(0)|答案(2)|浏览(49)

我使用PostgreSQL 14.10。我有表users

| id | name |

字符串
user_actions

| id | dept_id | user_id | num_tickets |


我想在user_actions中插入一行数据。dept_idnum_tickets是已知值,但我只有用户名,而不是id作为输入。因此,我想将INPUT插入user_actions,并将user_id值作为SELECT语句的结果,类似于:

INSERT INTO user_actions(dept_id,user_id,num_tickets)
VALUES('4', SELECT users.id FROM users WHERE users.name = 'Alice', '2')


这种精确的形式显然是错误的,因为它给出了错误

syntax error at or near "SELECT"
LINE 3:     VALUES('1', SELECT users.id FROM users WHERE user...
                        ^


This thread表示应该可以使用SELECT语句的结果来INSERT。然而,所有的例子都使用SELECT来获得 * 所有 * 的输入值,所以没有一个例子完全像我的例子,只有一个值是从子查询中派生出来的。
我无法理解INSERT的官方Postgres文档页面,无法更精确地确定语法。不过,我没有看到任何例子,其中只有一个INSERT值是从SELECT语句派生的。
当我尝试以下变量时,我得到相应的错误:

# No single quotes around values
INSERT INTO user_actions(dept_id,user_id,num_tickets)
VALUES(4, SELECT users.id FROM users WHERE users.name = 'Alice', 2)

syntax error at or near "SELECT"
LINE 3:     VALUES(1, SELECT users.id FROM users WHERE users...
                      ^

# No VALUES, with quotes
INSERT INTO user_actions(dept_id,user_id,num_tickets)
('4', SELECT users.id FROM users WHERE users.name = 'Alice', '2')

syntax error at or near "'1'"
LINE 3:     '1', SELECT monsters.id FROM monsters WHERE monsters.nam...
            ^

# No VALUES, no parentheses, with quotes
INSERT INTO user_actions(dept_id,user_id,num_tickets)
'4', SELECT users.id FROM users WHERE users.name = 'Alice', '2'

syntax error at or near "'1'"
LINE 3:     '1', SELECT users.id FROM users WHERE users.nam...
            ^

# No VALUES, no quotes
INSERT INTO user_actions(dept_id,user_id,num_tickets)
(4, SELECT users.id FROM users WHERE users.name = 'Alice', 2)

syntax error at or near "1"
LINE 3:     (1, SELECT users.id FROM users WHERE users.name...
             ^

# No VALUES, no quotes, no parentheses
INSERT INTO user_actions(dept_id,user_id,num_tickets)
4, SELECT users.id FROM users WHERE users.name = 'Alice', 2

psycopg2.errors.SyntaxError: syntax error at or near "1"
LINE 3:     (1, SELECT users.id FROM users WHERE users.name...
             ^

# Quotes, no parentheses
INSERT INTO user_actions(dept_id,user_id,num_tickets)
VALUES '4', SELECT users.id FROM users WHERE users.name = 'Alice', '2'

syntax error at or near "'1'"
LINE 3:     VALUES '1', SELECT users.id FROM users WHERE users...
                   ^

# No quotes, no parentheses
INSERT INTO user_actions(dept_id,user_id,num_tickets)
VALUES 4, SELECT users.id FROM users WHERE users.name = 'Alice', 2

syntax error at or near "1"
LINE 3:     VALUES 1, SELECT users.id FROM users WHERE users...


This accepted answer建议对所有内容执行SELECT,即使是已知的量,也应该可以工作。

# SELECT everything
INSERT INTO user_actions(dept_id,user_id,num_tickets)
SELECT 4, users.id FROM users WHERE users.name = 'Alice', 2

syntax error at or near ","
LINE 3: ...4, users.id FROM users WHERE users.name = 'Alice', 2
                                                            ^


我没办法了。语法是什么?

ttisahbt

ttisahbt1#

最后一种方法是执行SELECT和SELECT的正确方法。
进入user_actions(dept_id,user_id,num_tickets)SELECT 4,users.id FROM users WHERE users.name = 'Alice',2
语法错误“,”行3:.4,users.id FROM users WHERE users.name = 'Alice',2
这里不是SELECT 4, users.id FROM users WHERE users.name = 'Alice', 2
SELECT查询返回的字段数必须与查询的SELECT部分中指定的列列表相匹配。

SELECT 4, users.id, 2 FROM users WHERE users.name = 'Alice'

字符串
您的最终查询将如下所示:

INSERT INTO user_actions(dept_id,user_id,num_tickets) 
SELECT 4, users.id, 2 FROM users WHERE users.name = 'Alice'

ki0zmccv

ki0zmccv2#

可以将子选择用作标量值,但必须将其放入()中。

INSERT INTO user_actions(dept_id,user_id,num_tickets)
VALUES('4', (SELECT users.id FROM users WHERE users.name = 'Alice'), '2')

字符串
这是一个依赖子查询,它可以在标量值适合的任何地方使用,例如在SELECT中。

SELECT a,b,(SELECT count(*) FROM bar WHERE bar.a=foo.a) FROM foo;


它给出了相同的结果

SELECT f.a,f.b,count(*) FROM foo f JOIN bar b USING (a) GROUP BY f.a,f.b;


然而,具有依赖子查询的查询计划可能比连接差得多。这是因为依赖子查询是针对需要值的每一行执行的,而JOIN只执行一次。因此JOIN可以使用依赖子查询不可用的优化。例如,在上述情况下,由于必须完全读取两个表,JOIN将只构建一次哈希或合并,然后将其用于所有行,而依赖子查询则不会。
对于你的SQL,依赖子查询和SQL SELECT之间有重要的区别,就像Ashwin的答案一样。

  • CSRSELECT允许你从辅助表中提取多个列,而依赖子查询只返回一个。所以如果你需要两个或更多列,CSRSELECT是非常实用的。
  • 如果users.name不是唯一的,则SELECT将返回所有具有该名称的行,导致每行一个查询。依赖子查询只允许输出一个值,因此如果多行匹配,则会抛出错误。

相关问题