回答

收藏

在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
分享到:
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则