Ошибка «Подзапрос вернул не одну строку» - PullRequest
1 голос
/ 02 ноября 2019

Я искал в сети всю ночь, пытаясь найти ответ на этот вопрос ... Пока что не повезло. Все другие решения, которые я пробовал, приводили к синтаксическим ошибкам.

Я пытаюсь запустить оператор обновления, чтобы обновить значения location_id для элементов выбора. У меня есть две таблицы: существующая таблица INVENTORY и таблица TEMP_INV, содержащая подмножество значений item_id и новых значений location_id. Я хочу обновить текущие значения location_id в таблице INVENTORY новыми значениями location_id в таблице TEMP_INV, но только для элементов в таблице TEMP_INV.

INVENTORY таблица

item_id    location_id

123453     12-099
123454     12-100
123456     12-101
123457     12-102
123458     12-103

TEMP_INV таблица

item_id    location_id

123456     13-101
123457     13-102
123458     13-103

Желаемые результаты:

ИНВЕНТАРЬ таблица

item_id    location_id

123453     12-099
123454     12-100
123456     13-101
123457     13-102
123458     13-103

I 'm запустил приведенный ниже оператор обновления и получил ошибку «284: подзапрос вернул не одну строку».

UPDATE inventory
SET location_id =
(SELECT location_id
FROM temp_inv
WHERE item_id=item_id)

Ответы [ 3 ]

1 голос
/ 02 ноября 2019

Возможно, проблема в корреляции. Укажите имена столбцов!

UPDATE inventory
    SET location_id = (SELECT temp_inv.location_id
                       FROM temp_inv
                       WHERE inventory.item_id = temp_inv.item_id
                      );

Если у вас все еще есть проблема, вам нужно выбрать одну подходящую строку - или выяснить, почему у вас есть дубликаты! Одним из решений является limit, которое, я думаю, Informix поддерживает в подзапросах:

UPDATE inventory
    SET location_id = (SELECT temp_inv.location_id
                       FROM temp_inv
                       WHERE inventory.item_id = temp_inv.item_id
                       LIMIT 1
                      );

В противном случае агрегация работает:

UPDATE inventory
    SET location_id = (SELECT MAX(temp_inv.location_id)
                       FROM temp_inv
                       WHERE inventory.item_id = temp_inv.item_id
                      );

Примечание. Ваш запрос - и все эти -установит значение NULL для несоответствующих строк.

0 голосов
/ 02 ноября 2019

Вы можете попробовать что-то вроде этого (см. fiddle ). Я выбрал PostgreSQL в качестве примера, потому что Informix - это продукт, который происходит от стабильной версии Postgres (в них принимал участие Майкл Стоунбрейкер), и я не знаю ни одной скрипки Informix, о которой я знаю. Эти обновления могут быть сложными из-за различного синтаксиса среди поставщиков.

Создание и заполнение таблицы inventory:

CREATE TABLE inventory
(
  item_id INTEGER NOT NULL,
  location_id VARCHAR (25) NOT NULL
);


INSERT INTO inventory VALUES (123453, '12-099'), (123454, '12-100'), (123456, '12-101'),
(123457, '12-102'), (123458, '12-103');

То же самое для temp_inv:

CREATE TABLE temp_inv
(
  item_id INTEGER NOT NULL,
  location_id VARCHAR (25) NOT NULL
);

INSERT INTO temp_inv VALUES (123456, '13-101'), (123457, '13-102'), (123458, '13-103');

Затем выполните следующий SQL:

UPDATE inventory
SET location_id = temp_inv.location_id
FROM temp_inv
WHERE inventory.item_id = temp_inv.item_id;

Результат (как и ожидалось):

3 rows affected

Затем

SELECT * FROM inventory;

Результат:

item_id location_id
 123453      12-099
 123454      12-100
 123456      13-101
 123457      13-102
 123458      13-103

Et voilà! ps добро пожаловать на форум! : -)

0 голосов
/ 02 ноября 2019

Использовать запрос на соединение:

UPDATE inventory i
INNER JOIN  temp_inv it
ON i.item_id    = it.item_id    
SET i.location_id= it.location_id;
...