#sql #sql-server #tsql #merge
#sql #sql-сервер #tsql #слияние
Вопрос:
Я хочу использовать один оператор SQL (т. Е. «ОБЪЕДИНИТЬ») для управления таблицей, представляющей математический набор: вставить элемент, если true, иначе удалить.
Используя мороженое в качестве примера, я хочу добавить вкус или удалить вкус из списка на основе флага @Exist ниже. Возможно ли это? Я играл с ним в течение нескольких часов, и либо он синтаксически корректен и не вставляет строку, либо я пишу запрос, чтобы сделать то, что, по моему мнению, нужно сделать, но затем не будет компилироваться, потому что синтаксис недопустим. (Страница «man» слияния MSDN)
Вот моя слабая попытка:
CREATE TABLE IceCream(
Flavor VARCHAR(50) NOT NULL,
CONSTRAINT AK_Flavor UNIQUE(Flavor)
)
DECLARE @Flavor varchar(50)
DECLARE @Exist bit
set @Flavor='Vanilla'
set @Exist=1
MERGE IceCream AS T
USING IceCream AS S
ON S.Flavor=T.Flavor AND
S.Flavor=@Flavor AND
T.Flavor=@Flavor
WHEN NOT MATCHED BY TARGET AND @Exist=1
THEN INSERT (Flavor) VALUES (@Flavor)
WHEN NOT MATCHED BY SOURCE AND @Exist=0
THEN DELETE
OUTPUT $action, inserted.*, deleted.*;
Комментарии:
1. Возможно, вы захотите вообще пересмотреть использование СЛИЯНИЯ: mssqltips.com/sqlservertip/3074 /…
Ответ №1:
Хотя существуют разные способы достижения вашей цели, это MERGE
утверждение будет работать:
DECLARE @Flavor varchar(50), @Exist bit;
SET @Flavor = 'Orange';
SET @Exist = 1;
;WITH TGT AS (SELECT Flavor FROM IceCream WHERE Flavor = @Flavor)
MERGE INTO TGT
USING (VALUES(@Flavor, @Exist)) AS SRC(Flavor, Exist)
ON TGT.Flavor = SRC.Flavor
WHEN MATCHED AND SRC.Exist = 0
THEN DELETE
WHEN NOT MATCHED BY TARGET AND SRC.Exist = 1
THEN INSERT (Flavor) VALUES (SRC.Flavor);
Начните с начального списка:
INSERT INTO IceCream VALUES ('Vanilla'), ('Chocolate'), ('Strawberry')
И тестирование с несколькими разными парами (вкус, существует):
[Orange,1]
----------
Chocolate, Orange, Strawberry, Vanilla
[Rasberry,0]
----------
Chocolate, Orange, Strawberry, Vanilla
[Vanilla,0]
----------
Chocolate, Orange, Strawberry
[Chocolate,1]
----------
Chocolate, Orange, Strawberry
[Java,1]
----------
Chocolate, Java, Orange, Strawberry
Упрощение:
На самом деле, я использовал CTE в качестве цели, потому что в вашем исходном примере в WHEN NOT MATCHED BY SOURCE THEN DELETE
девяти случаях из десяти было и, при синхронизации набора, ваша цель должна быть ограничена подзапросом (CTE в случае СЛИЯНИЯ).
Однако ваши фактические потребности, похоже, не требуют WHEN NOT MATCHED BY SOURCE
предложения, и поэтому вы можете упростить приведенное выше утверждение с теми же результатами:
;MERGE INTO IceCream AS TGT
USING (VALUES(@Flavor, @Exist)) AS SRC(Flavor, Exist)
ON TGT.Flavor = SRC.Flavor
WHEN MATCHED AND SRC.Exist = 0
THEN DELETE
WHEN NOT MATCHED BY TARGET AND SRC.Exist = 1
THEN INSERT (Flavor) VALUES (SRC.Flavor);
Комментарии:
1. Ваш упрощенный ответ очень интуитивно понятен и работает как шарм; спасибо!