Как мне обновить с SELECT в SQL Server? - PullRequest
3399 голосов
/ 25 февраля 2010

В 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

Ответы [ 33 ]

4944 голосов
/ 25 февраля 2010
UPDATE
    Table_A
SET
    Table_A.col1 = Table_B.col1,
    Table_A.col2 = Table_B.col2
FROM
    Some_Table AS Table_A
    INNER JOIN Other_Table AS Table_B
        ON Table_A.id = Table_B.id
WHERE
    Table_A.col3 = 'cool'
721 голосов
/ 09 сентября 2011

В SQL Server 2008 (или лучше) используйте MERGE

MERGE INTO YourTable T
   USING other_table S 
      ON T.id = S.id
         AND S.tsql = 'cool'
WHEN MATCHED THEN
   UPDATE 
      SET col1 = S.col1, 
          col2 = S.col2;

В качестве альтернативы:

MERGE INTO YourTable T
   USING (
          SELECT id, col1, col2 
            FROM other_table 
           WHERE tsql = 'cool'
         ) S
      ON T.id = S.id
WHEN MATCHED THEN
   UPDATE 
      SET col1 = S.col1, 
          col2 = S.col2;
586 голосов
/ 22 января 2012
UPDATE table 
SET Col1 = i.Col1, 
    Col2 = i.Col2 
FROM (
    SELECT ID, Col1, Col2 
    FROM other_table) i
WHERE 
    i.ID = table.ID
267 голосов
/ 09 сентября 2011

Я бы изменил Отличный ответ Робина на следующее:

UPDATE Table
SET Table.col1 = other_table.col1,
 Table.col2 = other_table.col2
FROM
    Table
INNER JOIN other_table ON Table.id = other_table.id
WHERE
    Table.col1 != other_table.col1
OR Table.col2 != other_table.col2
OR (
    other_table.col1 IS NOT NULL
    AND Table.col1 IS NULL
)
OR (
    other_table.col2 IS NOT NULL
    AND Table.col2 IS NULL
)

Без предложения WHERE вы будете влиять даже на строки, которые не должны быть затронуты, что может (возможно) привести к пересчету индекса или срабатыванию триггеров, которые действительно не должны запускаться.

194 голосов
/ 25 февраля 2010

В одну сторону

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'
151 голосов
/ 06 ноября 2011

Еще одна возможность, которая еще не упомянута, - это просто поместить сам оператор 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 clause added to exclude rows that are the same in both tables
           Handles NULL values correctly*/
         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 избегает, вызывая ошибку, если есть попытка обновить одну и ту же строку более одного раза).

106 голосов
/ 05 октября 2012

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

UPDATE first_table, second_table
SET first_table.color = second_table.color
WHERE first_table.id = second_table.foreign_id
85 голосов
/ 23 мая 2012

Использование псевдонима:

UPDATE t
   SET t.col1 = o.col1
  FROM table1 AS t
         INNER JOIN 
       table2 AS o 
         ON t.id = o.id
65 голосов
/ 14 ноября 2012

Простой способ сделать это:

UPDATE
    table_to_update,
    table_info
SET
    table_to_update.col1 = table_info.col1,
    table_to_update.col2 = table_info.col2

WHERE
    table_to_update.ID = table_info.ID
53 голосов
/ 11 июня 2012

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

update
    Table
set
    Table.example = a.value
from
    TableExample a
where
    Table.field = *key value* -- finds the row in Table 
    AND a.field = *key value* -- finds the row in TableExample a
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...