T-SQL: использование CASE в операторе UPDATE для обновления определенных столбцов в зависимости от условия

109

Мне интересно, возможно ли это вообще. Я хочу обновить столбец x, если условие истинно, иначе столбец y будет обновлен

UPDATE table SET
     (CASE (CONDITION) WHEN TRUE THEN columnx
                       ELSE columny
      END)
= 25

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

pqsk
источник
Если предположить, что все в одной таблице, да. Вы всегда можете запустить его в транзакции и выполнить откат при ошибке, чтобы убедиться в этом сами.
OMG Ponies
Я не уверен, что ты имеешь в виду. Я пробовал поставить для столбца условие, но это не сработало. Он работает для оператора select, но не для оператора обновления. (Select (case (condition) when true then columnx else columny end) из myTable .... обновление не работает, и я могу понять почему. Кажется, это не способ заставить это работать.
pqsk

Ответы:

189

Вы не можете использовать условие для изменения структуры вашего запроса, только задействованные данные. Вы могли сделать это:

update table set
    columnx = (case when condition then 25 else columnx end),
    columny = (case when condition then columny else 25 end)

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

Единственный способ сделать именно то, что вы просите, - использовать динамический SQL. Однако я бы посоветовал вам держаться от этого подальше. Приведенного выше решения почти наверняка будет достаточно для того, что вам нужно.

Адам Робинсон
источник
Я согласен насчет динамического SQL. Но будут ли затронуты мои данные? Я имею в виду, что не хочу, чтобы его меняли в определенных условиях. Значит, он просто повторно вставит то, что уже там есть? Количество попаданий в базу данных может быть не так уж и плохо.
pqsk
@pqsk: это не должно повлиять на ваши данные, нужно просто повторно вставить то, что уже есть, для любого столбца, который не должен быть затронут.
Адам Робинсон
Спасибо. Я собираюсь пойти с этим. Настолько просто, что это может сделать даже пещерный человек. ха-ха.
pqsk
1
@AdamRobinson Прошло 1,5 года, знаете ли вы более эффективный способ обновить только один столбец
@Somebodyisintrouble: единственный способ обновить один столбец - использовать другой запрос.
Адам Робинсон
23
UPDATE  table
SET     columnx = CASE WHEN condition THEN 25 ELSE columnx END,
        columny = CASE WHEN condition THEN columny ELSE 25 END
Quassnoi
источник
1
Вы просто скопировали ответ Адама, или он был взят из другого места? ха-ха. Просто заметил это.
pqsk
1
@pqsk: Наши ответы разошлись примерно на 1 минуту, так что я мог бы представить, что просто нажал «Отправить» немного быстрее;)
Адам Робинсон
24
@pqsk: да, я просто скопировал ответ Адама за 23секунды до того, как он его опубликовал. Я один быстрый копипастер!
Quassnoi
2
@pqsk: если вы наведете курсор на * min ago, он покажет вам точное время публикации.
Quassnoi
2
Честно говоря, даже при том, что оба они одинаковы: если бы Адам вышел после вашего, он уточнил еще кое-что. Вот почему я отметил его как ответ. Спасибо хоть.
pqsk
4

введите описание изображения здесь

Я хочу изменить или обновить свой контактный номер до 8018070999, где 8018070777, используя оператор Case

update [Contacts] set contactNo=(case 
when contactNo=8018070777 then 8018070999
else
contactNo
end)

введите описание изображения здесь

Дебендра Даш
источник
1
для этого почему бы не использовать этот запрос UPDATE [Контакты] SET contactNo = 8018070999 WHERE contactNo = 8018070777
NewGuy
4

Я знаю, что это очень старый вопрос, но у меня это сработало:

UPDATE TABLE SET FIELD1 =
CASE 
WHEN FIELD1 = Condition1 THEN 'Result1'
WHEN FIELD1 = Condition2 THEN 'Result2'
WHEN FIELD1 = Condition3 THEN 'Result3'
END;

С уважением

Виктор Эдуардо Салазар Рамирес
источник
1

Я знаю, что это очень старый вопрос, и проблема помечена как исправленная. Однако, если у кого-то есть случай, подобный моему, где таблица имеет триггер для регистрации данных при событиях обновления, это вызовет проблему. Оба столбца получат обновление, а журнал сделает бесполезные записи. Как я сделал

IF (CONDITION) IS TRUE
BEGIN
    UPDATE table SET columnx = 25
END
ELSE
BEGIN
    UPDATE table SET columny = 25
END

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

Суровый
источник
это хороший момент и хорошая альтернатива! Я больше не работаю с исходным кодом, ведущим к этой теме, но всегда хорошо иметь разные решения, и я думаю, что это хорошее решение
pqsk
-1

Я считаю, что вы можете не обновлять «нежелательные» столбцы, настроив другие ответы следующим образом:
update table set columnx = (case when condition1 then 25 end), columny = (case when condition2 then 25 end)

Насколько я понимаю, это обновится только при выполнении условия.

После прочтения всех комментариев это наиболее эффективно:
Update table set ColumnX = 25 where Condition1 Update table set ColumnY = 25 where Condition1

Образец таблицы:
CREATE TABLE [dbo].[tblTest]( [ColX] [int] NULL, [ColY] [int] NULL, [ColConditional] [bit] NULL, [id] [int] IDENTITY(1,1) NOT NULL ) ON [PRIMARY]
образец данных:
Insert into tblTest (ColX, ColY, ColConditional) values (null, null, 0) Insert into tblTest (ColX, ColY, ColConditional) values (null, null, 0) Insert into tblTest (ColX, ColY, ColConditional) values (null, null, 1) Insert into tblTest (ColX, ColY, ColConditional) values (null, null, 1) Insert into tblTest (ColX, ColY, ColConditional) values (1, null, null) Insert into tblTest (ColX, ColY, ColConditional) values (2, null, null) Insert into tblTest (ColX, ColY, ColConditional) values (null, 1, null) Insert into tblTest (ColX, ColY, ColConditional) values (null, 2, null)

теперь я предполагаю, что вы можете написать условное выражение, которое обрабатывает значения NULL. В моем примере я предполагаю, что вы написали такое условие, которое оценивается как True, False или Null. Если вам понадобится помощь, дайте мне знать, и я сделаю все возможное.

Теперь выполнение этих двух строк кода фактически изменяет X на 25 тогда и только тогда, когда ColConditional имеет значение True (1), а Y - на 25, если и только если ColConditional имеет значение False (0)

Update tblTest set ColX = 25 where ColConditional = 1 Update tblTest set ColY = 25 where ColConditional = 0

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

Джон Грейнер
источник
1
На самом деле это не работает. Во-первых, если столбец допускает значения NULL, то, когда условие не выполняется, присваивается значение NULL. В случае, если значения NULL не разрешены, обновление не будет выполнено. Ваш последний "эффективный" запрос - недопустимый sql, по крайней мере, в TSQL. Вы тестировали это на конкретном движке, и это сработало у вас?
pqsk
Я тестировал это на SQL Server 2005, и он отлично работает, как показано. Я обязательно хотел бы знать, почему он был отклонен, и пример, показывающий, что значение NULL обновляется, потому что в моем тесте выше нулевое значение не обновляется. Я всегда думал, что самый простой ответ - лучший, и если я имею дело с базой данных с миллионами записей, я точно не хочу обновлять ненужные строки.
Джон Грейнер