Вставить из выбора

Мне нужно выполнить upsert из select, например this, но в SQL Server. Я обнаружил, что кто-то делает апсерт в SQL Server здесь, но это не из избранного.

Мой запрос сейчас выглядит примерно так:

INSERT INTO (table1) (...)
    SELECT (...)
    FROM (table 2)
    WHERE X NOT IN (SELECT Y from (table1) WHERE Y IS NOT NULL)

Но не могу понять, как добавить часть обновления. Я хотел бы добавить часть обновления, так как в 99% случаев это будет вставка.

Изменить: этот код работал бы, если бы я мог сделать это из SELECT:

BEGIN TRY
    INSERT INTO table1 (id, name, itemname, itemcatName, itemQty)
    VALUES ('val1', 'val2', 'val3', 'val4', 'val5')
END TRY
BEGIN CATCH
    UPDATE table1 
    SET name = 'val2', 
        itemname = 'val3', 
        itemcatName = 'val4', 
        itemQty = 'val5'
    WHERE id = 'val1'
END CATCH

person Chsir17    schedule 04.07.2018    source источник
comment
Одним из способов было бы иметь условие ЕСЛИ и либо выполнить, либо обновить, либо вставить в зависимости от того, существует ли запись уже или нет. Другой способ - использовать ОБЪЕДИНЕНИЕ.   -  person Rigerta    schedule 04.07.2018
comment
вы хотите обновить, если там еще вставляете данные?   -  person ARr0w    schedule 04.07.2018
comment
@ ARr0w да, точно, но в идеале я хотел бы сначала вставить и обновить, если дублируются, так как я буду работать с большим количеством записей, и в большинстве случаев это будет простая вставка   -  person Chsir17    schedule 04.07.2018
comment
Почему бы не использовать MERGE? Он создан для этой цели и, вероятно, более эффективен.   -  person Patrick Honorez    schedule 04.07.2018
comment
Я бы использовал слияние с осторожностью из-за некоторых ошибок все еще существуют   -  person Mazhar    schedule 04.07.2018
comment
Я не понимаю, что вы имеете в виду, если я смог сделать это с помощью SELECT. Что вы выбираете сейчас? Другой стол?   -  person Mazhar    schedule 04.07.2018
comment
@Mazhar да я выбираю из другой таблицы   -  person Chsir17    schedule 04.07.2018
comment
Вот хороший пример MERGE для аналогичной проблемы.   -  person Ulrik    schedule 04.07.2018


Ответы (4)


Думаю, тот же образ мыслей:

update t1
set ......
from table1 t1
inner join table2 on t1.Y=table2.X

Обратите внимание на обязательное использование псевдонима для обновленной таблицы для обновления на основе объединения.

В качестве альтернативы вы можете осмотреться (или дождаться ответа) для MERGE. Очень элегантно делать такие вещи, как upsert с помощью одного утверждения, но я не пришел к выводу, стоят ли того вероятные недостатки.

person George Menoutis    schedule 04.07.2018

update table1 
  set name = 'val2', itemname = 'val3', itemcatName = 'val4', itemQty = 'val5'
  where id = 'val1'

IF @@ROWCOUNT = 0
insert into table1(id, name, itemname, itemcatName, itemQty)
  values('val1', 'val2', 'val3', 'val4', 'val5')

Выполните UPSERT: http://en.wikipedia.org/wiki/Upsert

person Dinesh    schedule 04.07.2018
comment
Есть ли способ сделать как обновление, так и вставку из выбора? я знаю, что вы можете сделать: вставить в (...) выберите, но как сделать часть обновления? - person Chsir17; 04.07.2018
comment
Затем вам нужно использовать MERGE, но это снизит производительность. - person Dinesh; 04.07.2018

Если вы хотите INSERT, если запись не существует, или UPDATE, если она существует, попробуйте это

IF EXISTS (SELECT 1 FROM table1 WHERE somecol = @someval)
BEGIN
    UPDATE T1
    SET T1.someCol1 = T2.someCol1
        ,T1.someCol2 = T2.someCol2 
         --, etc,  etc
    FROM table1 T1
    INNER JOIN table2 T2 ON T1.Id = T2.T1_FK
END
ELSE
BEGIN
    INSERT INTO table1 (someCol, someCol2 --,etcetc)
    SELECT T2.someCol1, T2.someCol2 --etc etc
    FROM table2 T2
    WHERE somecol = @someval
END
person Mazhar    schedule 04.07.2018

Сделайте обновление в первую очередь

update t1
SET (...)
FROM (table2) t2
JOIN table1 t1 WHERE t1.Y = t2.X


INSERT INTO (table1) (...)
SELECT (...)
FROM (table2) t2
WHERE NOT EXISTS (SELECT 1 from table1 WHERE Y = t2.X)
person paparazzo    schedule 04.07.2018