Використовуйте CASE для вибору стовпців у UPDATE запиті?


13

Я можу CASEвибрати, які колонки відображати в SELECTзапиті (Postgres), наприклад:

SELECT CASE WHEN val = 0 THEN column_x
            WHEN val = 1 THEN column_y
            ELSE 0
       END AS update, ...

Чи можливо щось подібне взагалі під час виконання UPDATEзапиту в Postgres (тобто вибирати, які стовпці потрібно оновити)? Я припускаю, що не тому, що я нічого про це не міг знайти, але, можливо, хтось має розумну альтернативу (окрім використання процедури або оновлення кожного стовпця за допомогою а, CASEщоб визначити, чи варто стовпцю присвоїти нове значення або просто переназначити існуюче значення). Якщо немає простої альтернативи, я, звичайно, прийму це як відповідь.

Додаткова інформація : У моєму випадку я маю 14 потенційних стовпців, які можуть бути оновлені, причому лише один оновлюється на відповідний рядок (таблиця, яку потрібно оновити, приєднується до іншої у запиті). Кількість рядків для оновлення буде, швидше за все, різнитися, може становити десятки чи сотні. Я вважаю, що для умов приєднання існують індекси.

Відповіді:


26

Якщо вказати стовпець, слід оновити, він завжди буде оновлюватися, але ви можете змінити значення, яке ви ввели, умовно і повернути початкові значення залежно від ваших умов. Щось на зразок:

UPDATE some_table
SET    column_x = CASE WHEN should_update_x THEN new_value_for_x ELSE column_x END
     , column_y = CASE WHEN should_update_y THEN new_value_for_y ELSE column_y END
     , column_z = CASE WHEN should_update_z THEN new_value_for_z ELSE column_z END
FROM   ...

Тож якщо умови не є правильними для оновлення певного стовпця, ви просто повернете його поточне значення.

Зверніть увагу, що кожне зіставлене рядок буде бачити оновлення (навіть якщо всі стовпці в кінцевому підсумку встановлюються до значень, які вони вже є), якщо ви чітко не встановите цю обставину при фільтруванні пропозицій ON і WHERE, що може бути проблемою з продуктивністю (буде be write, індекси будуть оновлені, відповідні тригери будуть спрацьовувати, ...) якщо їх не зменшити.


Дякую за пораду про все, що оновлюється, якщо це повільно, я можу прийняти пропозицію @Colin 't Hart мати кілька заяв про оновлення.
newenglander

Ви можете усунути цю проблему, переконавшись, що пункти ON і WHERE фільтрують усі рядки, де не потрібні зміни, але це може означати повторення всіх ваших умов як у пункті SET, так і в пункті WHERE (якщо немає більш простої перевірки, що є 100% еквівалентним для всіх цих умов разом). На цей момент цей метод може все-таки бути більш ефективним, але метод декількох оновлень може бути простішим у дотриманні.
Девід Спіллетт

Будьте в курсі також, що оновлення стовпця до того самого значення призведе до того, що повтор буде створено, див. Orainternals.wordpress.com/2010/11/04/…
Colin 't Hart

@Colin: Так, будь-яке оновлення буде проходити через журнал транзакцій БД, включаючи оновлення, які по суті є NoOps через оновлення полів, щоб мати ті самі значення, що і раніше. Окрім потенціалу для негайного вирішення проблем, це може бути важливим фактором, якщо використовувати реплікацію, диференціальне резервне копіювання, доставку журналів тощо, оскільки додаткові операції з оновлення рядків збільшать необхідний для них простір / пропускну здатність.
Девід Спіллетт

Дякую обом за поради, у моєму випадку одне твердження про оновлення спрацювало чудово.
newenglander

5

Скільки різних комбінацій стовпців для оновлення у вас є? Скільки рядків усієї таблиці буде оновлено? Чи є індекси для швидкого доступу до рядків для оновлення?

Залежно від відповідей на ці запитання, можливо, ви зможете виконати кілька операторів оновлення, по одному для кожного стовпця, який ви хочете оновити, і помістіть умову на значення цього стовпця в пункті де оновлення, щоб нульові рядки були оновлені, якщо цей стовпець має неправильне значення.

Спробуйте і подумайте на основі набору, не вважайте, що оновлення потребує оновлення одного рядка, знайденого первинним ключем.


Дякую за відповідь. Я додав ще трохи інформації до свого запитання, сподіваюся, це зрозуміло. Це хороша альтернатива з декількома заявами оновлення (я вважаю за краще одну заяву оновлення, але я бачу, що там є перевага).
newenglander

Це може бути відповідь, яку я шукаю, але ти маєш намір поставити оновлення column_x = new_value_for_x, де @val = 0. Я можу експериментувати на чомусь подібному. Виглядає смішно. Це не простіше зробити, якщо val = 0 почати оновлення column_x = new_value_for_x тощо
CashCow

-1
update Practicing  -- table you will be updating
 set email = case -- column you will be updating
    when FName = 'Glenn' then 'Ace@Assasin.com'
       when FName = 'Riddick' then 'fallguy@Drunk.com'
       when FName = 'Jeffrey' then 'sorcerer@wizcom'
       else email
    end

Це оновлення лише одного стовпця, тоді як запитувач хоче знати, як оновлювати різні стовпці залежно від умов.
Colin 't Hart
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.