Potgres SQL INSERT INTO SELECT CASE проблема - PullRequest
1 голос
/ 25 апреля 2020

У меня следующий запрос, и я хотел бы вставить любое количество строк из подзапросов. Конечно, я получаю сообщение об ошибке 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.

Как мне решить эту проблему?

Ответы [ 2 ]

1 голос
/ 25 апреля 2020

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';
0 голосов
/ 25 апреля 2020

Для этого требуется процедурный код, либо на стороне клиента базы данных на вашем любимом языке программирования (TM), либо процедурный язык на стороне сервера базы данных . Обычный SQL является декларативным языком и не имеет продвинутых условных выражений . SQL CASE недостаточно для работы.

В Pl / Pg SQL это будет выглядеть так:

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$;
...