Подтвердить что ты не робот

Обновить, если отличается/изменено

Можно ли выполнить инструкцию update в sql, но только обновлять, если обновления отличаются?

например

если в базе данных col1 = "hello"

update table1 set col1 = 'hello'

не должен выполнять любое обновление

однако, если

update table1 set col1 = "bye"

этот должен выполнить обновление.

4b9b3361

Ответ 1

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

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

Ответ 2

Идея не выполняет никакого обновления, если новое значение такое же, как в БД прямо сейчас

WHERE col1 != @newValue

(очевидно, также должно быть какое-то поле Id для идентификации строки)

WHERE Id = @Id AND col1 != @newValue

PS: Изначально вы хотите обновить, только если значение "bye", поэтому просто добавьте AND col1 = 'bye', но я чувствую, что это избыточно, я просто предполагаю

Ответ 3

Если вы хотите изменить поле на 'hello', только если оно 'bye', используйте это:

UPDATE table1
SET col1 = 'hello'
WHERE col1 = 'bye'

Если вы хотите обновить, только если оно отличается от 'hello', используйте:

UPDATE table1
SET col1 = 'hello'
WHERE col1 <> 'hello'

Есть ли причина для этого странного подхода? Как прокомментировал Даниэль, нет особого выигрыша - кроме, может быть, если у вас есть тысячи строк с col1='hello'. Это тот случай?

Ответ 4

Во время компиляции и выполнения запросов SQL Server не находит времени, чтобы выяснить, действительно ли оператор UPDATE изменит любые значения или нет. Он просто выполняет записи, как ожидалось, даже если это необязательно.

В сценарии типа

update table1 set col1 = 'hello'

вы можете подумать, что SQL ничего не сделает, но он будет - он выполнит все необходимые записи, как если бы вы действительно изменили значение. Это происходит как для физической таблицы (или кластерного индекса), так и для любых некластеризованных индексов, определенных в этом столбце. Это приводит к записи в физические таблицы/индексы, пересчет индексов и записи журнала транзакций. При работе с большими наборами данных существует огромное преимущество в производительности только для обновления строк, которые получат изменения.

Если мы хотим избежать накладных расходов на эти записи, когда это не необходимо, мы должны разработать способ проверки необходимости обновления. Один из способов проверить необходимость обновления - это добавить что-то вроде "where col < > " hello ".

update table1 set col1 = 'hello' where col1 <> 'hello'

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

Но есть намного лучшая альтернатива, использующая комбинацию предложения EXISTS с предложением EXCEPT. Идея состоит в том, чтобы сравнить значения в строке назначения со значениями в строке источника сопоставления, чтобы определить, действительно ли обновление действительно необходимо. Посмотрите на измененный запрос ниже и изучите дополнительный фильтр запросов, начиная с EXISTS. Обратите внимание, что внутри предложения EXISTS инструкции SELECT не имеют предложения FROM. Эта часть особенно важна, потому что это добавляет только дополнительную проверку и операцию фильтра в плане запроса (стоимость обоих тривиальна). Итак, в конечном итоге вы получаете очень легкий метод определения необходимости UPDATE в первую очередь, избегая ненужных накладных расходов.

update table1 set col1 = 'hello'
/* AVOID NET ZERO CHANGES */
where exists 
    (
    /* DESTINATION */
    select table1.col1
    except
    /* SOURCE */
    select col1 = 'hello'
    )

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

Более полным примером может быть

update table1
   set col1 = 'hello',
       col2 = 'hello',
       col3 = 'hello'
/* Only update rows from CustomerId 100, 101, 102 & 103 */
where table1.CustomerId IN (100, 101, 102, 103)
/* AVOID NET ZERO CHANGES */
  and exists 
    (
    /* DESTINATION */
    select table1.col1
           table1.col2
           table1.col3
    except
    /* SOURCE */
    select z.col1,
           z.col2,
           z.col3
      from #anytemptableorsubquery z
     where z.CustomerId = table1.CustomerId
    )

Ответ 5

CREATE OR REPLACE PROCEDURE stackoverflow([your_value] IN TYPE) AS
BEGIN
   UPDATE   [your_table] t
     SET t.[your_collumn] = [your_value]
   WHERE t.[your_collumn] != [your_value];
  COMMIT;


EXCEPTION
 [YOUR_EXCEPTION];

END stackoverflow;

Ответ 6

update table1 set col1 = 'bye'
WHERE col1 != 'hello'

Ответ 7

Старый вопрос, но ни один из ответов правильно не соответствует значениям null.

Используя < > или! =, вы столкнетесь с проблемой при сравнении значений для различий, если есть потенциальный null в новом или старом значении, чтобы безопасно обновлять только при изменении использования оператора is distinct from в Postgres. Подробнее об этом здесь

Ответ 8

не объявляя какую-либо переменную или подобное, трудно ссылаться на вставленное жестко кодированное значение. Если это ваша цель, вы должны рассмотреть решение Даниэля Хильгарта. Обычно у вас будет ценность. В этом случае так вы можете сделать.

declare @t table (col1 varchar(10))

insert @t values ('hello')
insert @t values ('bye')

declare @newvalueforallrows varchar(10)
set @newvalueforallrows = 'hello'

update @t set col1 = @newvalueforallrows
where col1 <> @newvalueforallrows

-- 1 row updated

Ответ 9

Я думаю, что это должно сделать трюк для тебя...

create trigger [trigger_name] on [table_name]
for insert 
AS declare  @new_val datatype,@id int;
select @new_val = i.column_name from inserted i;
select @id = i.Id from inserted i;
update table_name set column_name = @new_val
where table_name.Id = @id and column_name != @new_val;

Ответ 10

Вам нужна уникальная клавиша id в вашей таблице (пусть предположим, что это значение равно 1), чтобы сделать что-то вроде:

UPDATE table1 SET col1="hello" WHERE id=1 AND col1!="hello"