Использование псевдонима в предложении WHERE для SELECT в UPDATE

Мне нужно обновить пару сотен строк в таблице данными из других таблиц. Код работает, но есть ли возможность не менять id и ключ и использовать id IN('56454', '56546'...)

UPDATE kontakt ko
SET  ko.Strasse1 = (SELECT old FROM audit WHERE key = '962881' AND cname = 'STRASSE1' AND old IS NOT NULL)
    ,ko.plz = (SELECT old FROM audit WHERE key = '962881' AND cname = 'PLZ' AND old IS NOT NULL)
    ,ko.ort = (SELECT old FROM audit WHERE key = '962881' AND cname = 'ORT' AND old IS NOT NULL)
WHERE id = 962881;

COMMIT;

Я пробовал использовать AS или заменять имена, но безуспешно. Я не смог найти ответа.

🤔 А знаете ли вы, что...
SQL поддерживает фильтрацию данных с использованием условий WHERE.


1
51
2

Ответы:

Решено

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

UPDATE kontakt ko
SET  ko.Strasse1 = (SELECT old FROM audit WHERE key = TO_CHAR(ko.id) AND cname = 'STRASSE1' AND old IS NOT NULL)
    ,ko.plz      = (SELECT old FROM audit WHERE key = TO_CHAR(ko.id) AND cname = 'PLZ' AND old IS NOT NULL)
    ,ko.ort      = (SELECT old FROM audit WHERE key = TO_CHAR(ko.id) AND cname = 'ORT' AND old IS NOT NULL)
WHERE id IN (56454, 56546, ...);

COMMIT;

Однако ваше заявление (и мое соответственно) выглядит несколько некорректно. Подзапросы должны возвращать по одному значению каждый (или не возвращать ни одной строки, которая в этом случае будет считаться нулевой). Следовательно, похоже, что вы ожидаете, что аудит таблицы будет содержать несколько значений для каждого ключа и cname, из которых только одно старое значение не равно нулю. Действительно ли это гарантированно так и будет? Или вы пытаетесь добиться чего-то другого?

Возможно, ключ и cname уникальны в таблице аудита, и вы действительно хотите сохранить исходное значение на случай, если значение аудита будет нулевым (или не существует). Для этого потребуется COALESCE (или NVL):

UPDATE kontakt ko
SET  ko.strasse1 = COALESCE((SELECT old FROM audit WHERE key = TO_CHAR(ko.id) AND cname = 'STRASSE1'), ko.strasse1)
    ,ko.plz      = COALESCE((SELECT old FROM audit WHERE key = TO_CHAR(ko.id) AND cname = 'PLZ'), ko.plz)
    ,ko.ort      = COALESCE((SELECT old FROM audit WHERE key = TO_CHAR(ko.id) AND cname = 'ORT'), ko.ort)
WHERE id IN (56454, 56546, ...);

COMMIT;

Используйте оператор MERGE и поверните таблицу audit:

MERGE INTO kontakt dst
USING (
  SELECT key,
         MAX(CASE cname WHEN 'STRASSE1' THEN old END) AS strasse1,
         MAX(CASE cname WHEN 'PLZ'      THEN old END) AS plz,
         MAX(CASE cname WHEN 'ORT'      THEN old END) AS ort
  FROM   audit
  WHERE  key IN ('56454', '56546')
  GROUP BY key
) src
ON (src.key = dst.key)
WHEN MATCHED THEN
  UPDATE
  SET strasse1 = src.strasse1,
      plz      = src.plz,
      ort      = src.ort;