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

Более быстрые результаты могут быть достигнуты с помощью numpy.where .

Например, при настройке unubtu -

In [76]: df.iloc[np.where(df.A.values=='foo')]
Out[76]: 
     A      B  C   D
0  foo    one  0   0
2  foo    two  2   4
4  foo    two  4   8
6  foo    one  6  12
7  foo  three  7  14

Сроки сравнения:

In [68]: %timeit df.iloc[np.where(df.A.values=='foo')]  # fastest
1000 loops, best of 3: 380 µs per loop

In [69]: %timeit df.loc[df['A'] == 'foo']
1000 loops, best of 3: 745 µs per loop

In [71]: %timeit df.loc[df['A'].isin(['foo'])]
1000 loops, best of 3: 562 µs per loop

In [72]: %timeit df[df.A=='foo']
1000 loops, best of 3: 796 µs per loop

In [74]: %timeit df.query('(A=="foo")')  # slowest
1000 loops, best of 3: 1.71 ms per loop

29
задан nami 13 July 2011 в 10:30
поделиться

9 ответов

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

  1. Производительность: здесь нет прироста производительности, потому что обновление не только должно найти правильную строку, но и дополнительно сравните данные.
  2. Триггер: если вы хотите, чтобы триггер срабатывал только при наличии реальных изменений, вам нужно реализовать свой триггер так, чтобы он сравнивал все старые значения с новыми, прежде чем что-либо делать.
7
ответ дан Daniel Hilgarth 13 July 2011 в 10:30
поделиться

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

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

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

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

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

8
ответ дан ypercubeᵀᴹ 13 July 2011 в 10:30
поделиться
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;
3
ответ дан Hussain 13 July 2011 в 10:30
поделиться
  • 1
    @DJTripleThreat - Можно использовать e.target и передача, которая к callRemote, вероятно, самый легкий маршрут, просто имейте его, принимают параметр события, используют e.target внутренняя часть, можно проверить if($(e.target).is(":submit"))... – Nick Craver♦ 24 October 2010 в 11:53
  • 2
    @DJTripleThreat - Можно использовать e.target и передача, которая к callRemote, вероятно, самый легкий маршрут, просто имейте его, принимают параметр события, используют e.target внутренняя часть, можно проверить if($(e.target).is(":submit"))... – Nick Craver♦ 24 October 2010 в 11:53
  • 3
    @DJTripleThreat - Можно использовать e.target и передача, которая к callRemote, вероятно, самый легкий маршрут, просто имейте его, принимают параметр события, используют e.target внутренняя часть, можно проверить if($(e.target).is(":submit"))... – Nick Craver♦ 24 October 2010 в 11:53
  • 4
    @DJTripleThreat - Можно использовать e.target и передача, которая к callRemote, вероятно, самый легкий маршрут, просто имейте его, принимают параметр события, используют e.target внутренняя часть, можно проверить if($(e.target).is(":submit"))... – Nick Craver♦ 24 October 2010 в 11:53
  • 5
    @DJTripleThreat - Можно использовать e.target и передача, которая к callRemote, вероятно, самый легкий маршрут, просто имейте его, принимают параметр события, используют e.target внутренняя часть, можно проверить if($(e.target).is(":submit"))... – Nick Craver♦ 24 October 2010 в 11:53

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

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

1
ответ дан maxTrialfire 13 July 2011 в 10:30
поделиться
  • 1
    Вы don' t нужно эти each, вызов - просто звонит click непосредственно на объекте jQuery, представляющем все входные элементы – SpoonMeiser 1 May 2014 в 14:16
  • 2
    Вы don' t нужно эти each, вызов - просто звонит click непосредственно на объекте jQuery, представляющем все входные элементы – SpoonMeiser 1 May 2014 в 14:16
  • 3
    Вы don' t нужно эти each, вызов - просто звонит click непосредственно на объекте jQuery, представляющем все входные элементы – SpoonMeiser 1 May 2014 в 14:16
  • 4
    Вы don' t нужно эти each, вызов - просто звонит click непосредственно на объекте jQuery, представляющем все входные элементы – SpoonMeiser 1 May 2014 в 14:16
  • 5
    Вы don' t нужно эти each, вызов - просто звонит click непосредственно на объекте jQuery, представляющем все входные элементы – SpoonMeiser 1 May 2014 в 14:16

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

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
0
ответ дан t-clausen.dk 13 July 2011 в 10:30
поделиться
update table1 set col1 = 'bye'
WHERE col1 != 'hello'
-1
ответ дан ysrb 13 July 2011 в 10:30
поделиться
  • 1
    +1 Хорошее учебное руководство. Похож на очень большую работу все же. Не что-то, чтобы поощрить то писать владеет документацией. Я предполагаю, что это должен быть WRI' s задание для создания этого несколько более легким в использовании. Поскольку это теперь, необходимо перейти через большое количество обручей. How' s Ваш опыт с генерацией документации с помощью Инструментальных средств? – Sjoerd C. de Vries 4 July 2011 в 19:34
  • 2
    +1 Хорошее учебное руководство. Похож на очень большую работу все же. Не что-то, чтобы поощрить то писать владеет документацией. Я предполагаю, что это должен быть WRI' s задание для создания этого несколько более легким в использовании. Поскольку это теперь, необходимо перейти через большое количество обручей. How' s Ваш опыт с генерацией документации с помощью Инструментальных средств? – Sjoerd C. de Vries 4 July 2011 в 19:34
  • 3
    +1 Хорошее учебное руководство. Похож на очень большую работу все же. Не что-то, чтобы поощрить то писать владеет документацией. Я предполагаю, что это должен быть WRI' s задание для создания этого несколько более легким в использовании. Поскольку это теперь, необходимо перейти через большое количество обручей. How' s Ваш опыт с генерацией документации с помощью Инструментальных средств? – Sjoerd C. de Vries 4 July 2011 в 19:34
  • 4
    +1 Хорошее учебное руководство. Похож на очень большую работу все же. Не что-то, чтобы поощрить то писать владеет документацией. Я предполагаю, что это должен быть WRI' s задание для создания этого несколько более легким в использовании. Поскольку это теперь, необходимо перейти через большое количество обручей. How' s Ваш опыт с генерацией документации с помощью Инструментальных средств? – Sjoerd C. de Vries 4 July 2011 в 19:34
  • 5
    +1 Хорошее учебное руководство. Похож на очень большую работу все же. Не что-то, чтобы поощрить то писать владеет документацией. Я предполагаю, что это должен быть WRI' s задание для создания этого несколько более легким в использовании. Поскольку это теперь, необходимо перейти через большое количество обручей. How' s Ваш опыт с генерацией документации с помощью Инструментальных средств? – Sjoerd C. de Vries 4 July 2011 в 19:34

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

UPDATE table1 SET col1="hello" WHERE id=1 AND col1!="hello"
1
ответ дан Claudio Bogado Pompa 13 July 2011 в 10:30
поделиться

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

В сценарии, подобном

update table1 set col1 = 'hello'

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

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

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

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

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

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
    )
18
ответ дан Dude0001 13 July 2011 в 10:30
поделиться

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

WHERE col1 != @newValue

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

WHERE Id = @Id AND col1 != @newValue

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

25
ответ дан sll 13 July 2011 в 10:30
поделиться
Другие вопросы по тегам:

Похожие вопросы: