Nem*_*emo 24 mysql sql sql-server
我试图在Sql Server(2012)中找到等效的以下MySql查询?
INSERT INTO mytable (COL_A, COL_B, COL_C, COL_D)
VALUES ( 'VAL_A','VAL_B', 'VAL_C', 'VAL_D')
ON DUPLICATE KEY UPDATE COL_D= VALUES(COL_D);
Run Code Online (Sandbox Code Playgroud)
有人可以帮忙吗?
PS.我已经读过MERGE查询具有类似的功能,但我发现它的语法非常不同.
Sql*_*Zim 20
您基本上是在寻找插入或更新模式,有时也称为Upsert.
我推荐这个:为Sql Server插入或更新模式 - Sam Saffron
对于将处理单行的过程,这些事务都可以正常工作:
Sam Saffron的第一个解决方案(适用于此架构):
begin tran
if exists (
select *
from mytable with (updlock,serializable)
where col_a = @val_a
and col_b = @val_b
and col_c = @val_c
)
begin
update mytable
set col_d = @val_d
where col_a = @val_a
and col_b = @val_b
and col_c = @val_c;
end
else
begin
insert into mytable (col_a, col_b, col_c, col_d)
values (@val_a, @val_b, @val_c, @val_d);
end
commit tran
Run Code Online (Sandbox Code Playgroud)
Sam Saffron的第二个解决方案(适用于此架构):
begin tran
update mytable with (serializable)
set col_d = @val_d
where col_a = @val_a
and col_b = @val_b
and col_c = @val_c;
if @@rowcount = 0
begin
insert into mytable (col_a, col_b, col_c, col_d)
values (@val_a, @val_b, @val_c, @val_d);
end
commit tran
Run Code Online (Sandbox Code Playgroud)
即使有创造性的使用IGNORE_DUP_KEY,你仍然不得不使用插入/更新块或合并语句.
update mytable
set col_d = 'val_d'
where col_a = 'val_a'
and col_b = 'val_b'
and col_c = 'val_c';
insert into mytable (col_a, col_b, col_c, col_d)
select 'val_a','val_b', 'val_c', 'val_d'
where not exists (select *
from mytable with (serializable)
where col_a = 'val_a'
and col_b = 'val_b'
and col_c = 'val_c'
);
Run Code Online (Sandbox Code Playgroud)
Spock提供的Merge答案应该做你想要的.
不一定建议合并.我用它,但我永远不会承认@AaronBertrand.
试试这个...我已经添加了注释来尝试解释在SQL Merge语句中发生了什么.来源:MSDN:合并声明
Merge语句与ON DUPLICATE KEY UPDATE语句的不同之处在于,您可以告诉它使用哪些列进行合并.
CREATE TABLE #mytable(COL_A VARCHAR(10), COL_B VARCHAR(10), COL_C VARCHAR(10), COL_D VARCHAR(10))
INSERT INTO #mytable VALUES('1','0.1', '0.2', '0.3'); --<These are the values we'll be updating
SELECT * FROM #mytable --< Starting values (1 row)
MERGE #mytable AS target --< This is the target we want to merge into
USING ( --< This is the source of your merge. Can me any select statement
SELECT '1' AS VAL_A,'1.1' AS VAL_B, '1.2' AS VAL_C, '1.3' AS VAL_D --<These are the values we'll use for the update. (Assuming column COL_A = '1' = Primary Key)
UNION
SELECT '2' AS VAL_A,'2.1' AS VAL_B, '2.2' AS VAL_C, '2.3' AS VAL_D) --<These values will be inserted (cause no COL_A = '2' exists)
AS source (VAL_A, VAL_B, VAL_C, VAL_D) --< Column Names of our virtual "Source" table
ON (target.COL_A = source.VAL_A) --< This is what we'll use to find a match "JOIN source on Target" using the Primary Key
WHEN MATCHED THEN --< This is what we'll do WHEN we find a match, in your example, UPDATE COL_D = VALUES(COL_D);
UPDATE SET
target.COL_B = source.VAL_B,
target.COL_C = source.VAL_C,
target.COL_D = source.VAL_D
WHEN NOT MATCHED THEN --< This is what we'll do when we didn't find a match
INSERT (COL_A, COL_B, COL_C, COL_D)
VALUES (source.VAL_A, source.VAL_B, source.VAL_C, source.VAL_D)
--OUTPUT deleted.*, $action, inserted.* --< Uncomment this if you want a summary of what was inserted on updated.
--INTO #Output --< Uncomment this if you want the results to be stored in another table. NOTE* The table must exists
;
SELECT * FROM #mytable --< Ending values (2 row, 1 new, 1 updated)
Run Code Online (Sandbox Code Playgroud)
希望有所帮助
您可以使用 模拟几乎相同的行为INSTEAD OF TRIGGER:
CREATE TRIGGER tMyTable ON MyTable
INSTEAD OF INSERT
AS
BEGIN
SET NOCOUNT ON;
SELECT i.COL_A, i.COL_B, i.COL_C, i.COL_D,
CASE WHEN mt.COL_D IS NULL THEN 0 ELSE 1 END AS KeyExists
INTO #tmpMyTable
FROM INSERTED i
LEFT JOIN MyTable mt
ON i.COL_D = mt.COL_D;
INSERT INTO MyTable(COL_A, COL_B, COL_C, COL_D)
SELECT COL_A, COL_B, COL_C, COL_D
FROM #tmpMyTable
WHERE KeyExists = 0;
UPDATE mt
SET mt.COL_A = t.COL_A, mt.COL_B = t.COL_B, mt.COL_C = t.COL_C
FROM MyTable mt
INNER JOIN #tmpMyTable t
ON mt.COL_D = t.COL_D AND t.KeyExists = 1;
END;
Run Code Online (Sandbox Code Playgroud)
这个怎么运作
LEFT OUTER JOIN的键列上的a来注意哪些 ARE 已经在基础表中COL_D。INSERT通过插入那些不在表中的行来重复语句的实际工作(因为INSTEAD OF,我们已经从引擎中删除了插入的责任,需要自己做这件事)。要点
INSTEAD OF触发器已就位。COL_D在这种情况下,但它可能是一个复合键。(关键但不能IDENTITY出于明显的原因,因为客户端不会插入身份)NB
INSTEAD OF- 因为这可能导致 Sql Server 的可观察行为发生令人惊讶的变化,例如这样 - 即使是精心设计的INSTEAD OF触发器也会导致不知道的开发人员和 DBA 花费数小时的精力和沮丧他们出现在你的桌子上。| 归档时间: |
|
| 查看次数: |
23265 次 |
| 最近记录: |