ORA-01427 Подзапрос с одной строкой возвращает более 1 строки - PullRequest
0 голосов
/ 27 февраля 2020

Эта ошибка, кажется, популярна, и есть много связанных ответов. Однако существующие ответы, похоже, не относятся к моей ситуации.

Я упрощаю свое дело, используя 2 таблицы: Test1 и Test3 (см. Иллюстрацию)

Я пытаюсь сделать попытку найти записи в таблице test3, которые не соответствуют значению в поле value1 (если поле check_condition1 = 1, если оно равно 0, мне все равно)

, поэтому в основном результат должен быть похож на этот запрос в этот конкретный сценарий:

select distinct t3.* from test3 t3, test1 t1
where t3.department=t1.department
and t3.value1 not in ('A','B');

enter image description here

enter image description here

enter image description here

Однако, если я использую это утверждение:

select distinct t3.* from test3 t3, test1 t1
where t3.department=t1.department
and t3.value1 not in 
(
  case t1.CHECK_CONDITION1
  when 0 then
    (select '1' from dual where 1=2)
  when 1 then
     ( select value1 from test1 where department=t3.DEPARTMENT)
  end
)

Я получил это сообщение:

ORA-01427: single-row subquery returns more than one row
01427. 00000 -  "single-row subquery returns more than one row"
*Cause:    
*Action:

Я думал, что мой подзапрос "выберите значение1 из test1, где отдел = t3.DEPARTMENT "должен вернуть набор для t3.value1 для проверки.

Как следует исправить утверждение? Моя цель - использовать таблицу Test1 в качестве управляющей таблицы, поля Check_condition1, check_condition2 являются «переключателями», которые можно включать и выключать без необходимости изменения основного запроса. Пожалуйста, сообщите, если моя мысль имеет смысл.

Прилагается скрипт для создания таблиц test1 и test3 для упрощения дублирования моей проблемы.

  CREATE TABLE "TEST1" 
   (    "DEPARTMENT" NUMBER(3,0), 
    "VALUE1" VARCHAR2(26 BYTE), 
    "VALUE2" VARCHAR2(26 BYTE), 
    "CHECK_CONDITION1" NUMBER(3,0), 
    "CHECK_CONDITION2" NUMBER(3,0)
   ) 
Insert into TEST1 (DEPARTMENT,VALUE1,VALUE2,CHECK_CONDITION1,CHECK_CONDITION2) values (1,'A','Z',1,0);
Insert into TEST1 (DEPARTMENT,VALUE1,VALUE2,CHECK_CONDITION1,CHECK_CONDITION2) values (1,'B','Y',1,0);

  CREATE TABLE "TEST3" 
   (    "DEPARTMENT" NUMBER(3,0), 
    "VALUE1" VARCHAR2(26 BYTE), 
    "VALUE2" VARCHAR2(26 BYTE), 
    "VALUE3" VARCHAR2(26 BYTE)
   );
Insert into TEST3 (DEPARTMENT,VALUE1,VALUE2,VALUE3) values (1,'A','T','Whatever');
Insert into TEST3 (DEPARTMENT,VALUE1,VALUE2,VALUE3) values (1,'Z','Y','Whatever');
Insert into TEST3 (DEPARTMENT,VALUE1,VALUE2,VALUE3) values (1,'B','Y','Whatever');

Ответы [ 2 ]

1 голос
/ 27 февраля 2020

Из документации CASE выражений :

Как для простых, так и для поиска выражений CASE все return_expr должны иметь одинаковый тип данных ( CHAR, VARCHAR2, NCHAR или NVARCHAR2, NUMBER, BINARY_FLOAT или BINARY_DOUBLE) или все должны иметь тип данных цифра c. Если все возвращаемые выражения имеют числовой тип c, тогда Oracle определяет аргумент с наивысшим приоритетом числового c, неявно преобразует остальные аргументы в этот тип данных и возвращает этот тип данных.

return_expr оператора CASE ожидает единственное значение, поэтому ваш подзапрос:

( select value1 from test1 where department=t3.DEPARTMENT)

- это то, что вызывает исключение.

Вместо этого используйте фильтр в подпрограмме -query:

select distinct t3.*
from   test3 t3
       INNER JOIN test1 t1
       ON ( t3.department=t1.department )
WHERE  t3.value1 not in (
         select value1
         from   test1
         where  department=t3.DEPARTMENT
         AND    t1.CHECK_CONDITION1 = 1
       )

Который, для ваших тестовых данных, выводит:

DEPARTMENT | VALUE1 | VALUE2 | VALUE3  
---------: | :----- | :----- | :-------
         1 | Z      | Y      | Whatever

db <> Fiddle здесь

1 голос
/ 27 февраля 2020

Это было бы примерно так, я полагаю:

SQL> select distinct t3.*
  2  from test3 t3 join test1 t1 on t3.department=t1.department
  3  where t3.value1 not in
  4    (select t1.value1 from test1 t1
  5     where t1.department = t3.department
  6       and 1 = case when t1.check_condition1 = 1 then 1
  7                    else 0
  8               end
  9    );

DEPARTMENT VALUE1     VALUE2     VALUE3
---------- ---------- ---------- ----------
         1 Z          Y          Whatever

SQL>

Если условие было 0, вы сказали, что вам все равно, поэтому:

SQL> update test1 set check_condition1 = 0;

2 rows updated.

SQL> select distinct t3.*
  2  from test3 t3 join test1 t1 on t3.department=t1.department
  3  where t3.value1 not in
  4    (select t1.value1 from test1 t1
  5     where t1.department = t3.department
  6       and 1 = case when t1.check_condition1 = 1 then 1
  7                    else 0
  8               end
  9    );

DEPARTMENT VALUE1     VALUE2     VALUE3
---------- ---------- ---------- ----------
         1 B          Y          Whatever
         1 A          T          Whatever
         1 Z          Y          Whatever

SQL>
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...