Можно ли выполнять несколько обновлений с помощью одного оператора UPDATE SL?

Мне нужно изменить все значения заголовковой колонки:

  1. с "a-1" на "a1",
  2. с "a.1" на "a1",
  3. с "b-1" до "b1",
  4. от "b.1" до "b1".

Прямо сейчас, я выполняю два заявления UPDATE:

UPDATE tbl SET title='a1' WHERE title IN ('a-1', 'a.1')
UPDATE tbl SET title='b1' WHERE title IN ('b-1', 'b.1')

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

Вы, наверное, гость его - у меня есть огромный стол для решения (одно заявление завершается примерно за 90 секунд), и у меня есть огромное количество обновлений для выполнения.

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

EDIT: Обратите внимание, что реальные данные, с которыми я работаю, и изменения в данных, которые я должен выполнять, не так просты - строки длиннее, и они не следуют никакой шаблон (это пользовательские данные, так что никаких предположений не может быть сделано - это может быть что угодно).

Допустим, у меня есть таблица tbl с колонками ID и название .

Ответ на: "Можно ли выполнять несколько обновлений с помощью одного оператора UPDATE SL?"

Количество ответов:5

Если преобразования так же просты, как ваши примеры, вы могли бы сделать обновление с немного строки манипуляции:

UPDATE tbl 
SET title = left(title, 1) + right(title, 1) 
WHERE title IN ('a-1', 'a.1', 'b-1', 'b.1')

Будет ли что-то подобное работать для вас?

Вы можете использовать одно заявление и ряд случаев заявления

update tbl
  set title = 
    case
      when title in ('a-1', 'a.1') then 'a1'
      when title in ('b-1', 'b.1') then 'b1'
      else title
    end

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

update tbl
  set title = 
    case
      when title in ('a-1', 'a.1') then 'a1'
      when title in ('b-1', 'b.1') then 'b1'
      else title
    end
where
  title in ('a.1', 'b.1', 'a-1', 'b-1')

Это сократит количество записей в таблицу.

или

   Update Table set 
     title = Replace(Replace(title, '.', ''), '-', '')
   Where title Like '[ab][.-]1'

В более общем случае, где может быть много сотен отображений для каждого из новых значений, вы создадите отдельную таблицу старых и новых значений, а затем использовать его в заявлении UPDATE. В одном диалекте S'L:

CREATE TEMP TABLE mapper (old_val CHAR(5) NOT NULL, new_val CHAR(5) NOT NULL);
...multiple inserts into mapper...
INSERT INTO mapper(old_val, new_val) VALUES('a.1', 'a1');
INSERT INTO mapper(old_val, new_val) VALUES('a-1', 'a1');
INSERT INTO mapper(old_val, new_val) VALUES('b.1', 'b1');
INSERT INTO mapper(old_val, new_val) VALUES('b-1', 'b1');
...etcetera...

UPDATE tbl
   SET title = (SELECT new_val FROM mapper WHERE old_val = tbl.title)
   WHERE title IN (SELECT old_val FROM mapper);

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

Для нескольких альтернатив, CASE операций в порядке. Но если у вас есть сотни, тысячи или миллионы карт для выполнения, то вы, вероятно, превысите пределы длины оператора S'L в вашем DBMS.

Работа от ответа Джонатана.

UPDATE tbl
   SET title = new_val
FROM mapper
WHERE title IN (SELECT old_val FROM mapper)
     AND mapper.old_val = tbl.title;

Его первоначальная версия потребует большого количества считывок к таблице картографа.