Oracle ORA-01427: подзапрос с одной строкой возвращает более одной строки, но на самом деле строк нет

Я уже слышу стоны, глядя на мой титул, но, пожалуйста, подождите немного. :)

У меня есть две таблицы, которые имеют несколько общих столбцов и обновляются разными способами. Учитывая определенный идентификатор, я хочу обновить первую таблицу значениями из второй таблицы, если в первой таблице отсутствует какая-либо информация.

Таблица А выглядит примерно так:

Dept_ID  Reviewer  Reviewer_Team  Reviewer_Code
ACM      Null      Null           Null
EOT      Null      Null           Null
QQQ      Joe       Joe's Group    XYZ
ACM      Null      Null           Null
ZZZ      Null      Null           Null

Таблица Б выглядит примерно так:

Dept_ID  Reviewer  Reviewer_Team  Reviewer_Code
AAA      Al        Al's Group     123
BBB      Bob       Bob's Group    234
ZZZ      Zoe       Zoe's Group    567

Если Reviewer_Code имеет значение Null в таблице A, мы хотим найти Dept_ID таблицы A в таблице B и обновить другие поля таблицы A, чтобы они соответствовали таблице B. Обратите внимание, что в таблице A может быть несколько записей с одним и тем же Dept_ID, и в этом случае мы ожидаем, что они будут имеют те же значения, обновленные из таблицы B.

Звучит легко. Если взять приведенные выше таблицы в качестве примера, в таблице B нет совпадений, поэтому записи ACM и EOT не будут обновляться на этом этапе. Однако запись ZZZ таблицы A будет обновляться на основе записи ZZZ таблицы B.

Однако есть шанс, что в таблице B не будет совпадений. Итак, представьте, что в таблице A нет записи ZZZ, а есть только записи ACM и EOT с нулевыми значениями.

Я новичок в Oracle (исходя из SQL Server), поэтому, возможно, я неправильно это тестирую, но у меня есть куча запросов один за другим в окне .sql Oracle SQL Developer. Это, кажется, работает для меня нормально нормально. Когда дело доходит до этого запроса, я получаю ужасную ошибку «подзапрос с одной строкой».

Вот запрос, который я пробовал несколькими способами:

UPDATE VchrImpDetailCombined vchr
SET (Reviewer, Reviewer_Team, Reviewer_Code) =
  (SELECT DISTINCT b.Reviewer, b.Reviewer_Team, b.Reviewer_Code
   FROM GlobPMSDeptIdMapping b 
   WHERE b.Dept_Id = vchr.Dept_Id)
   WHERE vchr.Reviewer_Code IS NULL
     AND vchr.Business_L1 = 'CF'
     AND vchr.Dept_ID IS NOT NULL; 

or

UPDATE VchrImpDetailCombined vchr
SET (Reviewer, Reviewer_Team, Reviewer_Code) =
  (SELECT DISTINCT b.Reviewer, b.Reviewer_Team, b.Reviewer_Code
   FROM GlobPMSDeptIdMapping b 
   inner join VchrImpDetailCombined a
   on b.Dept_Id = a.Dept_Id
   WHERE b.Dept_Id = vchr.Dept_Id)
   WHERE vchr.Reviewer_Code IS NULL
     AND vchr.Business_L1 = 'CF'
     AND vchr.Dept_ID IS NOT NULL; 

Я также пробовал несколько других вещей, таких как «WHERE EXISTS SELECT blahblah» или «WHERE b.Dept_ID IS NOT NULL» и т. д.

Теперь, учитывая данные моего примера выше, подзапрос должен иметь 0 записей, имея в виду, что на самом деле в таблице A нет записи ZZZ, как в моем примере, только ACM и EOT. В таблице B просто нет записей с соответствующим Dept_ID в таблице A. Таким образом, я ожидаю обновления 0 записей и счастливого перехода к следующему запросу.

Когда я запускаю эти запросы в строке других запросов, я получаю сообщение об ошибке. Если я запускаю запрос по одному, я просто получаю «обновлено 3 строки», что кажется странным, что что-то обновляется, учитывая, что совпадений быть не должно. Но 3 обновленные строки, похоже, соответствуют 3 записям ACM и EOT, хотя в таблице B нечего обновлять с учетом критериев.

Должно быть, я упускаю что-то очевидное, но я просто не могу этого понять. Вопросов об ORA-01427 огромное количество, поэтому я был так уверен, что смогу найти ответ уже там, но, похоже, не смог его найти.

Есть идеи?


person JustAGuy    schedule 19.12.2014    source источник
comment
Первое, что я замечаю, это SELECT DISTINCT, который вряд ли будет делать то, что вы хотите. Он вам не нужен, если есть ограничение уникальности на GlobPMSDeptIdMapping.Reviewer_Code (в том числе, если это первичный ключ), и в противном случае не гарантируется сокращение результатов подзапроса до одной строки.   -  person John Bollinger    schedule 20.12.2014


Ответы (1)


Вам нужно указать Oracle, что он должен выполнять обновление только тогда, когда для этого есть данные (и я ожидал, что это потребуется и для SQL Server, но я не уверен). Это преодолеет это препятствие за счет выполнения дополнительного подзапроса:

UPDATE VchrImpDetailCombined vchr
SET (Reviewer, Reviewer_Team, Reviewer_Code) = (
  SELECT b.Reviewer, b.Reviewer_Team, b.Reviewer_Code
   FROM GlobPMSDeptIdMapping b 
   WHERE b.Dept_Id = vchr.Dept_Id
)
WHERE vchr.Reviewer_Code IS NULL
  AND vchr.Business_L1 = 'CF'
  AND vchr.Dept_ID IN (
    SELECT Dept_Id
    FROM GlobPMSDeptIdMapping
  );

Согласно моему комментарию к вопросу, я удалил DISTINCT из (исходного) подзапроса, так как он либо не нужен, либо неэффективен.

person John Bollinger    schedule 19.12.2014