PostgreSQL INSERT INTO SELECT CASE 问题

Posted

技术标签:

【中文标题】PostgreSQL INSERT INTO SELECT CASE 问题【英文标题】:PotgresSQL INSERT INTO SELECT CASE problem 【发布时间】:2020-04-25 11:06:44 【问题描述】:

我有以下查询,我想从子查询中插入任意数量的行。当然我得到一个错误SQL Error [21000]: ERROR: more than one row returned by a sub query used as an expression,因为一些子查询返回多行

insert into logs (_timestap, _message, _mode, _user_id)
select :_timestamp, :_message, :_mode,
case :_mode

    -- select all users that have the given grade. NOTE that this sub query returns multiple rows
    when 'byGrade' then (select u.id from users u where grade = :_grade)

    -- The user id value is already passed
    when 'byIndividual' then (select :_user_id limit 1)

    -- This sub query also returns multiple rows (all infact) from the users table
    when 'everyone' then (select id from users)
end

PostgreSQL 版本 10。

我该如何解决这个问题?

【问题讨论】:

【参考方案1】:

union all可以帮忙:

insert into logs (_timestap, _message, _mode, _user_id)

select :_timestamp, :_message, :_mode, id
from users
where :_mode = 'byGrade' and grade = :_grade

union all

select :_timestamp, :_message, :_mode, :_user_id
where :_mode = 'byIndividual'

union all

select :_timestamp, :_message, :_mode, id
from users
where :_mode = 'everyone';

【讨论】:

【参考方案2】:

这需要过程代码,可以在数据库客户端使用您最喜欢的编程语言 (TM) 或 database server-side procedural language。普通 SQL 是声明性语言,没有高级 conditionals。 SQL CASE 不足以完成这项工作。

在 Pl/PgSQL 中它看起来像:

CREATE FUNCTION do_the_thing(
  p_timestap timestamptz,
  p_message text,
  p_mode text,
  p_user_id integer)
RETURNS VOID
LANGUAGE plpgsql AS $definition$
BEGIN
if p_mode = 'byGrade' then
  insert into logs (_timestap, _message, _mode, _user_id)
  select p_timestamp, p_message, p_mode, u.id from users u where grade = p_grade;
elsif p_mode = 'byIndividual' then
  insert into logs (_timestap, _message, _mode, _user_id)
  select p_timestamp, p_message, p_mode, p_user_id;
elsif p_mode = 'everyone' then
  insert into logs (_timestap, _message, _mode, _user_id)
  select p_timestamp, p_message, p_mode, id from users;
end if;
END; 
$definition$;

【讨论】:

以上是关于PostgreSQL INSERT INTO SELECT CASE 问题的主要内容,如果未能解决你的问题,请参考以下文章

PostgreSQL SELECT INTO和INSERT INTO SELECT 两种表复制语句

PostgreSQL INSERT INTO SELECT CASE 问题

PostgreSQL v12.6 中的 PLpgSQL INSERT-RETURNING-INTO 错误?

INSERT INTO MySQL 表 SELECT FROM PostgreSQL 表

Postgresql中无则插入的使用方法INSERT INTO WHERE NOT EXISTS

“INSERT INTO ... FETCH ALL FROM ...”无法编译