在SQL Server上执行INSERT或UPDATE的解决方案
技术问答
75 人阅读
|
0 人回复
|
2023-09-13
|
假设表结构为MyTable(KEY, datafield1, datafield2...)。
7 _4 b8 L8 q$ k9 E% [5 J我经常想更新现有记录,或者如果不存在则插入新记录。3 q2 u! M0 K8 m) }
本质上:
) H+ P: z# K' F2 ~) c5 L% CIF (key exists)
9 C9 \5 j5 g9 e% n1 p2 s run update command9 V0 E: r1 M0 S" ^' C5 d/ m
ELSE
0 O. S% m2 f+ E" J$ a& ]1 K run insert command0 {3 j. l8 C! k5 y% j9 C# A9 d9 {0 x
编写此代码的最佳方式是什么?" N& A+ f Q; v0 W5 w
) |- C: v; u* A5 i- s
解决方案:+ Q. A y% I) z' ~4 l# e
2 ~& ]3 h- y% q! w& h6 E4 D
) z0 Z8 m% k; e/ c
/ _! J& S; S* W4 J8 k
不要忘记交易。性能很好,但是简单的(IF EXISTS ..)方法非常危险。
z+ h# R h% A! I$ `当多个线程尝试执行插入或更新时,您很容易会遇到违反主键的情况。
k0 \$ S% c$ O! M$ r, `@Beau Crawford和@Esteban提供的解决方案显示了总体思路,但容易出错。
' S6 s; r0 n+ _- y为了避免死锁和PK违规,您可以使用以下方法:
% l" j8 E5 g5 K. E4 k% dbegin tran7 q+ M6 ?" D/ K; o: f6 o3 _
if exists (select * from table with (updlock,serializable) where key = @key)" M9 P; R$ `1 l5 X
begin0 Q p/ [; C) i6 S! O' l
update table set ...; Y% ^0 t8 P$ {
where key = @key$ p# o3 f7 l; O
end
% L, I: c# f% g- i9 \; _& D- celse
( v/ i# D$ H$ D7 ?begin
@6 I* V5 ]6 A6 c; o* p8 Y. { insert into table (key, ...)
2 @6 H( f) l( j values (@key, ...)& w, y% B: P0 f- }( c
end
6 z q0 S- R" ]$ b0 xcommit tran
5 U1 E3 f/ |( y3 B& Z9 N或者0 A/ ~* a& K6 w) L3 W9 T
begin tran3 u$ t# k# x: L! G* Z! x$ }; [+ N& W7 y
update table with (serializable) set ...
5 S/ D) X( i( Q2 R where key = @key4 n# _0 ] J h) h
if @@rowcount = 0
A) |& r" P9 K6 f( \( q begin+ u! f6 B$ y% q( [8 [
insert into table (key, ...) values (@key,..), a: Q( u1 @1 Z, I% y
end, {. X1 Y0 o9 _* ~: F9 \
commit tran |
|
|
|
|
|