Как мне обновить с 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 ]

18 голосов
/ 26 января 2017

Существует даже более короткий метод , и это может вас удивить:

Пример набора данных:

CREATE TABLE #SOURCE ([ID] INT, [Desc] VARCHAR(10));
CREATE TABLE #DEST   ([ID] INT, [Desc] VARCHAR(10));

INSERT INTO #SOURCE VALUES(1,'Desc_1'), (2, 'Desc_2'), (3, 'Desc_3');
INSERT INTO #DEST   VALUES(1,'Desc_4'), (2, 'Desc_5'), (3, 'Desc_6');

Код:

UPDATE #DEST
SET #DEST.[Desc] = #SOURCE.[Desc]
FROM #SOURCE
WHERE #DEST.[ID] = #SOURCE.[ID];
18 голосов
/ 18 июня 2014

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

drop table uno
drop table dos

create table uno
(
    uid int,
    col1 char(1),
    col2 char(2)
)
create table dos
(
    did int,
    col1 char(1),
    col2 char(2),
    [sql] char(4)
)
insert into uno(uid) values (1)
insert into uno(uid) values (2)
insert into dos values (1,'a','b',null)
insert into dos values (2,'c','d','cool')

select * from uno 
select * from dos

ЯВНО:

update uno set col1 = (select col1 from dos where uid = did and [sql]='cool'), 
col2 = (select col2 from dos where uid = did and [sql]='cool')

OR

update uno set col1=d.col1,col2=d.col2 from uno 
inner join dos d on uid=did where [sql]='cool'

select * from uno 
select * from dos

Если имя столбца идентификатора в обеих таблицах одинаковое, просто поместите имя таблицы перед обновляемой таблицей и используйте псевдоним для выбранной таблицы, т. Е .:

update uno set col1 = (select col1 from dos d where uno.[id] = d.[id] and [sql]='cool'),
col2  = (select col2 from dos d where uno.[id] = d.[id] and [sql]='cool')
16 голосов
/ 31 января 2018

Консолидация всех различных подходов здесь.

  1. Выбрать обновление
  2. Обновление с общим табличным выражением
  3. Слияние

Пример структуры таблицы приведен ниже и будет обновляться с Product_BAK до таблицы Product.

Продукт

CREATE TABLE [dbo].[Product](
    [Id] [int] IDENTITY(1, 1) NOT NULL,
    [Name] [nvarchar](100) NOT NULL,
    [Description] [nvarchar](100) NULL
) ON [PRIMARY]

Product_BAK

    CREATE TABLE [dbo].[Product_BAK](
        [Id] [int] IDENTITY(1, 1) NOT NULL,
        [Name] [nvarchar](100) NOT NULL,
        [Description] [nvarchar](100) NULL
    ) ON [PRIMARY]

1. Выберите обновление

    update P1
    set Name = P2.Name
    from Product P1
    inner join Product_Bak P2 on p1.id = P2.id
    where p1.id = 2

2. Обновление с общим табличным выражением

    ; With CTE as
    (
        select id, name from Product_Bak where id = 2
    )
    update P
    set Name = P2.name
    from  product P  inner join CTE P2 on P.id = P2.id
    where P2.id = 2

3. Слияние

    Merge into product P1
    using Product_Bak P2 on P1.id = P2.id

    when matched then
    update set p1.[description] = p2.[description], p1.name = P2.Name;

В этом операторе Merge мы можем сделать вставку, если не найдем подходящую запись в цели, но существуем в источнике и найдем синтаксис:

    Merge into product P1
    using Product_Bak P2 on P1.id = P2.id;

    when matched then
    update set p1.[description] = p2.[description], p1.name = P2.Name;

    WHEN NOT MATCHED THEN
    insert (name, description)
    values(p2.name, P2.description);
14 голосов
/ 27 апреля 2017

В принятом ответе после:

SET
Table_A.col1 = Table_B.col1,
Table_A.col2 = Table_B.col2

Я бы добавил:

OUTPUT deleted.*, inserted.*

Что я обычно делаю, это помещаю все в транзакцию с откатом и использую "OUTPUT": таким образом я вижу все, что должно произойти. Когда я доволен увиденным, я меняю ROLLBACK на COMMIT.

Мне обычно нужно задокументировать, что я сделал, поэтому я использую опцию "results to Text", когда запускаю откатный запрос, и сохраняю как сценарий, так и результат OUTPUT. (Конечно, это не практично, если я изменил слишком много строк)

13 голосов
/ 08 сентября 2016

Другой способ обновления из оператора select:

UPDATE A
SET A.col = A.col,B.col1 = B.col1
FROM  first_Table AS A
INNER JOIN second_Table AS B  ON A.id = B.id WHERE A.col2 = 'cool'
12 голосов
/ 31 июля 2015
UPDATE table AS a
INNER JOIN table2 AS b
ON a.col1 = b.col1
INNER JOIN ... AS ...
ON ... = ...
SET ...
WHERE ...
12 голосов
/ 01 октября 2014

Приведенное ниже решение работает для базы данных MySQL:

UPDATE table1 a , table2 b 
SET a.columname = 'some value' 
WHERE b.columnname IS NULL ;
2 голосов
/ 07 ноября 2018

Вариант 1. Использование внутреннего соединения:

UPDATE
    A
SET
    A.col1 = B.col1,
    A.col2 = B.col2
FROM
    Some_Table AS A
    INNER JOIN Other_Table AS B
        ON A.id = B.id
WHERE
    A.col3 = 'cool'

Вариант 2: Подзапрос, связанный с Co

UPDATE table 
SET Col1 = B.Col1, 
    Col2 = B.Col2 
FROM (
    SELECT ID, Col1, Col2 
    FROM other_table) B
WHERE 
    B.ID = table.ID
1 голос
/ 14 марта 2019
UPDATE table1
SET column1 = (SELECT expression1
               FROM table2
               WHERE conditions)
[WHERE conditions];

Синтаксис оператора UPDATE при обновлении одной таблицы данными из другой таблицы в SQL Server

1 голос
/ 08 октября 2018
declare @tblStudent table (id int,name varchar(300))
declare @tblMarks table (std_id int,std_name varchar(300),subject varchar(50),marks int)

insert into @tblStudent Values (1,'Abdul')
insert into @tblStudent Values(2,'Rahim')

insert into @tblMarks Values(1,'','Math',50)
insert into @tblMarks Values(1,'','History',40)
insert into @tblMarks Values(2,'','Math',30)
insert into @tblMarks Values(2,'','history',80)


select * from @tblMarks

update m
set m.std_name=s.name
 from @tblMarks as m
left join @tblStudent as s on s.id=m.std_id

select * from @tblMarks
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...