Питання Як я можу оновити з SELECT в SQL Server?


В SQL Server, це можливо insert в таблицю з використанням SELECT заява:

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

Це також можливо оновлення через a SELECT? У мене є тимчасовий таблиця, що містить ці значення, і хочеться оновити іншу таблицю, використовуючи ці значення. Можливо щось на зразок цього:

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

3038
2018-02-25 14:36


походження


Коментарі Енді цілком справедливі. Я перетворив мій веб-сайт mysql на PDO нещодавно, думаючи, що я тепер якось врятувавсь від ін'єкційних атак. Тільки під час процесу я зрозумів, що деякі з моїх sql-повідомлень все-таки були побудовані за допомогою введення користувача. Я тоді виправив це, використовуючи підготовлені заяви. Для повноцінного новачка не цілком зрозуміло, що існує відмінність, тому що багато експертів викидають коментар про використання PDO, але не вказують t - Zafar Kurbonov


Відповіді:


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'

4462
2018-02-25 14:39



Якщо ви редагуєте посилання між таблицями (SET Table.other_table_id = @NewValue), потім змініть виписку на щось подібне ON Table.id = @IdToEdit AND other_table.id = @NewValue - Trisped
Хіба це не вистачає WHERE Застереження в питанні? У мене немає сервера на цій системі, щоб перевірити його, але ви не зможете його додати ON люблю: ON Table.id = other_table.id AND other_table.sql='cool'? Чи я помилково трактую питання? - J V
Це працює, використовуючи UPDATE для ітерації над INNER JOIN. Таким чином, функція ON, як ваше пропозиція WHERE та INNER JOIN, пропускають записи, які не знайдені в таблиці JOINed. Додавання пропозиції WHERE також обмежує набір результатів таблиці JOIN. @Roger Ray, яка версія MySQL і який ваш запит, як це робить функція infact, як зазначено. - fyrye
@RogerRay, це питання стосується Microsoft SQL Server. На жаль, синтаксис між різними впровадженнями SQL може відрізнятися. - Charles Wood
Частково пов'язані, я часто намагаюсь написати свої запити UPDATE як вказівки SELECT, щоб я міг побачити дані, які будуть оновлюватися перед виконанням. Себастян висвітлює техніку для цього в останній публікації в блозі: sqlity.net/en/2867/update-from-select - dennislloydjr


У 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;

672
2017-09-09 09:40



MERGE також може бути використаний для запису "Upserting"; це, UPDATE якщо відповідний запис існує INSERT новий запис, якщо не знайдено відповідності - brichins
Це було приблизно в 10 разів швидше, ніж еквівалентне оновлення ... приєднатися до заяви для мене. - Paul Suart
MERGE також може бути використаний для видалення. Але будьте обережні з MERGE, оскільки таблиця TARGET не може бути віддаленою таблицею. - Möoz
Злиття помилок: mssqltips.com/sqlservertip/3074/... - Simon D
@SimonD: виберіть будь-яке ключове слово SQL Server, і ви знайдете помилки. Ваша точка? Я змагаюся, пов'язані з цим більше помилок (і більше фундаментальних) UPDATE ніж MERGE, люди просто навчилися жити з ними, і вони стають частиною ландшафту ("особливостей"). Подумайте, що блоги не існували, коли UPDATE був новим хлопцем на блоці. - onedaywhen


UPDATE table 
SET Col1 = i.Col1, 
    Col2 = i.Col2 
FROM (
    SELECT ID, Col1, Col2 
    FROM other_table) i
WHERE 
    i.ID = table.ID

524
2018-01-22 17:47



Безсумнівно найпростіший! Проте твій пропав Ідентифікатор поле з внутрішнього SELECT. Вам знадобиться це для роботи WHERE - John Doherty
Це буде прагнути працювати майже у всіх СУБД, а це означає, що навчитися один раз, виконувати всюди. Якщо це важливіше для вас, ніж продуктивність, ви можете віддати перевагу цій відповіддю, особливо якщо це оновлення для виправлення деяких даних. - Alan Macdonald
@ dotnetN00b stackoverflow.com/a/2334741/206730 не добре для вас? - Kiquenet


Я модифікував би Відмінна відповідь Робіна на наступне:

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 ви вплинете навіть на рядки, які не потребують впливу, що може (можливо) спричинити перерахунок індексу або тригери пожежі, які дійсно не повинні були звільнені.


253
2017-09-08 21:20



Це припускає, що жоден з стовпців не може бути нульовим. - Martin Smith
Ви маєте рацію, я набираю цей приклад вручну. Я додав третю і четверту статтю до тієї заяви, де це було зроблено. - quillbreaker
WHERE EXISTS(SELECT T1.Col1, T1.Col2 EXCEPT SELECT T2.Col1, T2.Col2)) є більш лаконічним. - Martin Smith
Чи не повинно бути твердження, яке містять ці два в де депозит? (other_table.col1 - нуль та table.col1 не є нулем) або (other_table.col2 - нуль та table.col2 не є нулем) - Barka
Залежить від того, якщо ви хочете замінити нулі в пункті призначення за допомогою nulls з джерела. Часто я цього не роблю. Але якщо ви це зробите, то конструкція Мартіна де-пункту є найкращою для використання. - quillbreaker


Односторонній

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'

180
2018-02-25 14:41





Ще одна можливість, про яку ще не згадувалося ще, є просто патрон 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 уникає, якщо виникає спроба оновити ту ж рядок більше одного разу).


140
2017-11-06 00:18



чи є сенс імені CTE ? - Raptor
@ShivanRaptor - це абревіатура для Вираз загальної таблиці. Просто довільний псевдонім у цьому випадку. - Martin Smith
Це також добре працює з кількома CTE: ;WITH SomeCompexCTE AS (...), CTEAsAbove AS (SELECT T1.Col1,... FROM T1 JOIN SomeComplexCTE...) UPDATE CTEAsAbove SET Col1=_Col1, ... - VeeTheSecond


Для запису (та інших, які шукають як я), ви можете зробити це в MySQL таким чином:

UPDATE first_table, second_table
SET first_table.color = second_table.color
WHERE first_table.id = second_table.foreign_id

95
2017-10-05 14:20



Це добре працювало. Я спробував все вищезазначене запитання, всі вони дають той чи інший вид помилки.
Дякую! Я знаю це старе, але просто хотів сказати, що це працювало для мене. Мій сервер не дозволить використовувати FROM у заяві UPDATE. Тому всі відповіді, що містять положення FROM, повернули синтаксичну помилку. Цей шлях працював ідеально. Цінується. - Todd Withers
Чому це так часто сприймається? Було б точно так само, якби я публікував запис для рубінового коду, якщо хтось запитає про C # ... - isHuman
@isHuman Дуже часто поширюється питання sql-server при пошуку моїх sql-відповідей (і навпаки). Це абсолютно відрізняється від публікації рубінової відповіді в записі C #. - Gabriel