43

Как выполнить UPDATE с использованием SELECT в SQL Server?

24

В SQL Server можно вставлять строки в таблицу с помощью оператора INSERT.. SELECT. Пример:

INSERT INTO Table (col1, col2, col3)
SELECT col1, col2, col3 
FROM other_table 
WHERE sql = 'cool'

Но есть ли возможность обновить таблицу с помощью SELECT? У меня есть временная таблица, содержащая необходимые значения, и я хотел бы обновить другую таблицу, используя эти значения. Может быть, что-то вроде этого:

UPDATE Table SET col1, col2
SELECT col1, col2 
FROM other_table 
WHERE sql = 'cool'
WHERE Table.id = other_table.id

Как правильно сформулировать запрос для обновления таблицы с использованием значений из другой таблицы?

4 ответ(ов)

60

Ваш запрос обновляет данные в таблице Table_A, используя значения из Table_B, при этом происходит слияние таблиц по идентификатору id. Обновляются поля col1 и col2 в Table_A, если условие в WHERE выполняется, т.е. когда значение col3 равно 'cool'.

Вот более понятное объяснение по шагам:

  1. UPDATE - мы выбираем таблицу для обновления: Table_A.
  2. SET - здесь задаются новые значения для обновляемых столбцов:
    • Table_A.col1 получает значение из Table_B.col1.
    • Table_A.col2 получает значение из Table_B.col2.
  3. FROM - указываем, какие таблицы будем использовать. Здесь мы делаем INNER JOIN между Table_A и Table_B по условию равенства id.
  4. WHERE - фильтруем строки, чтобы обновление прошло только для тех записей, где Table_A.col3 равно 'cool'.

Итак, данная команда обновляет все записи в Table_A, которые соответствуют указанному условию и имеют общие идентификаторы с Table_B, устанавливая новые значения для col1 и col2.

2

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

UPDATE t 
SET t.col1 = o.col1, 
    t.col2 = o.col2
FROM 
    other_table o 
  JOIN 
    t ON t.id = o.id
WHERE 
    o.sql = 'cool'

В этом запросе мы обновляем столбцы col1 и col2 в таблице t, используя значения из таблицы other_table, где условие o.sql = 'cool'. Обратите внимание, что мы связываем таблицы по идентификатору id, чтобы обеспечить корректное обновление только необходимых записей.

1

Ещё одна возможность, которая не была упомянута ранее, — это просто вложить сам оператор SELECT в CTE, а затем обновить этот CTE.

WITH CTE AS (
    SELECT T1.Col1,
           T2.Col1 AS _Col1,
           T1.Col2,
           T2.Col2 AS _Col2
    FROM T1
    JOIN T2 ON T1.id = T2.id
    /* Условие WHERE добавлено для исключения строк, которые совпадают в обеих таблицах
       Корректно обрабатывает NULL значения */
    WHERE EXISTS (
        SELECT T1.Col1, T1.Col2
        EXCEPT
        SELECT T2.Col1, T2.Col2
    )
)
UPDATE CTE
SET Col1 = _Col1,
    Col2 = _Col2;

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

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

1

Для справки (и для других, кто искал так же, как и я), вы можете сделать это в MySQL следующим образом:

UPDATE first_table, second_table
SET first_table.color = second_table.color
WHERE first_table.id = second_table.foreign_id;
Чтобы ответить на вопрос, пожалуйста, войдите или зарегистрируйтесь