@@ -150,50 +150,71 @@ Consider using [sp_CRUDGen](https://github.com/kevinmartintech/sp_CRUDGen) to ge
150
150
``` sql
151
151
SET NOCOUNT, XACT_ABORT ON ;
152
152
153
- BEGIN TRANSACTION;
153
+ BEGIN TRY
154
+ BEGIN TRANSACTION;
154
155
155
- UPDATE
156
- dbo .Person WITH (UPDLOCK, SERIALIZABLE)
157
- SET
158
- FirstName = ' Kevin'
159
- WHERE
160
- LastName = ' Martin' ;
156
+ UPDATE
157
+ dbo .Person WITH (UPDLOCK, SERIALIZABLE)
158
+ SET
159
+ FirstName = ' Kevin'
160
+ WHERE LastName = ' Martin' ;
161
161
162
- IF @@ROWCOUNT = 0
162
+ IF @@ROWCOUNT = 0
163
163
BEGIN
164
164
INSERT dbo .Person (FirstName, LastName) VALUES (' Kevin' , ' Martin' );
165
165
END;
166
166
167
- COMMIT TRANSACTION;
167
+ COMMIT TRANSACTION;
168
+ END TRY
169
+ BEGIN CATCH
170
+ IF @@TRANCOUNT > 0
171
+ BEGIN
172
+ ROLLBACK TRANSACTION;
173
+ END;
174
+
175
+ THROW;
176
+ END CATCH;
168
177
```
169
178
170
179
** Use this UPSERT pattern when a record insert is more likely:** Don't worry about checking for a records existence just perform the insert.
171
180
172
181
``` sql
173
182
SET NOCOUNT, XACT_ABORT ON ;
174
183
175
- BEGIN TRANSACTION;
184
+ BEGIN TRY
185
+ BEGIN TRANSACTION;
176
186
177
- INSERT dbo .Person (FirstName, LastName)
178
- SELECT
179
- ' Kevin'
180
- ,' Martin'
181
- WHERE
182
- NOT EXISTS (
187
+ INSERT dbo .Person
188
+ (
189
+ FirstName,
190
+ LastName
191
+ )
183
192
SELECT
184
- 1
185
- FROM
186
- dbo .Person WITH (UPDLOCK, SERIALIZABLE)
187
- WHERE
188
- LastName = ' Martin'
189
- );
193
+ ' Kevin' ,
194
+ ' Martin'
195
+ WHERE NOT EXISTS
196
+ (
197
+ SELECT
198
+ 1
199
+ FROM dbo .Person WITH (UPDLOCK, SERIALIZABLE)
200
+ WHERE LastName = ' Martin'
201
+ );
190
202
191
- IF @@ROWCOUNT = 0
203
+ IF @@ROWCOUNT = 0
192
204
BEGIN
193
205
UPDATE dbo .Person SET FirstName = ' Kevin' WHERE LastName = ' Martin' ;
194
206
END;
195
207
196
- COMMIT TRANSACTION;
208
+ COMMIT TRANSACTION;
209
+ END TRY
210
+ BEGIN CATCH
211
+ IF @@TRANCOUNT > 0
212
+ BEGIN
213
+ ROLLBACK TRANSACTION;
214
+ END;
215
+
216
+ THROW;
217
+ END CATCH;
197
218
```
198
219
199
220
** Use this UPSERT pattern to allow the client application to handle the exception:** Ensure you handle the exception in your code.
@@ -220,61 +241,77 @@ For JSON, XML or comma-separated list ensure you insert the records into a tempo
220
241
``` sql
221
242
SET NOCOUNT, XACT_ABORT ON ;
222
243
223
- BEGIN TRANSACTION;
224
-
225
- /* **************************************************************
226
- ** Create temp table to store the updates
227
- ****************************************************************/
228
- CREATE TABLE # Update (
229
- FirstName varchar (50 ) NOT NULL
230
- ,LastName varchar (50 ) NOT NULL
231
- );
232
-
233
- INSERT INTO # Update (FirstName, LastName)
234
- VALUES (' Kevin' , ' Martin' )
235
- ,(' Jean-Luc' , ' Picard' );
236
-
237
-
238
- /* **************************************************************
239
- ** Perform Updates (WHEN MATCHED)
240
- ****************************************************************/
241
- UPDATE
242
- P WITH (UPDLOCK, SERIALIZABLE)
243
- SET
244
- P .FirstName = U .FirstName
245
- FROM
246
- dbo .Person AS P
247
- INNER JOIN # Update AS U ON P.LastName = U.LastName;
248
-
249
-
250
- /* **************************************************************
251
- ** Perform Inserts (WHEN NOT MATCHED [BY TARGET])
252
- ****************************************************************/
253
- INSERT dbo .Person (FirstName, LastName)
254
- SELECT
255
- U .FirstName
256
- ,U .LastName
257
- FROM
258
- # Update AS U
259
- WHERE
260
- NOT EXISTS (
261
- SELECT * FROM dbo .Person AS P WHERE P .LastName = U .LastName
262
- );
263
-
244
+ BEGIN TRY
245
+ BEGIN TRANSACTION;
264
246
265
- /* **************************************************************
266
- ** Perform Deletes (WHEN NOT MATCHED BY SOURCE)
267
- ****************************************************************/
268
- DELETE
269
- P
270
- FROM
271
- dbo .Person AS P
272
- LEFT OUTER JOIN # Update AS U ON P.LastName = U.LastName
273
- WHERE
274
- U .LastName IS NULL ;
247
+ /* **************************************************************
248
+ ** Create temp table to store the updates
249
+ ****************************************************************/
250
+ CREATE TABLE # Update
251
+ (
252
+ FirstName varchar (50 ) NOT NULL ,
253
+ LastName varchar (50 ) NOT NULL
254
+ );
255
+
256
+ INSERT INTO # Update
257
+ (
258
+ FirstName,
259
+ LastName
260
+ )
261
+ VALUES
262
+ (' Kevin' , ' Martin' ),
263
+ (' Jean-Luc' , ' Picard' );
264
+
265
+
266
+ /* **************************************************************
267
+ ** Perform Updates (WHEN MATCHED)
268
+ ****************************************************************/
269
+ UPDATE
270
+ P WITH (UPDLOCK, SERIALIZABLE)
271
+ SET
272
+ P .FirstName = U .FirstName
273
+ FROM dbo .Person AS P
274
+ INNER JOIN # Update AS U
275
+ ON P .LastName = U .LastName ;
276
+
277
+
278
+ /* **************************************************************
279
+ ** Perform Inserts (WHEN NOT MATCHED [BY TARGET])
280
+ ****************************************************************/
281
+ INSERT dbo .Person
282
+ (
283
+ FirstName,
284
+ LastName
285
+ )
286
+ SELECT
287
+ U .FirstName ,
288
+ U .LastName
289
+ FROM # Update AS U
290
+ WHERE NOT EXISTS
291
+ (
292
+ SELECT * FROM dbo .Person AS P WHERE P .LastName = U .LastName
293
+ );
294
+
295
+
296
+ /* **************************************************************
297
+ ** Perform Deletes (WHEN NOT MATCHED BY SOURCE)
298
+ ****************************************************************/
299
+ DELETE P
300
+ FROM dbo .Person AS P
301
+ LEFT OUTER JOIN # Update AS U
302
+ ON P .LastName = U .LastName
303
+ WHERE U .LastName IS NULL ;
275
304
305
+ COMMIT TRANSACTION;
306
+ END TRY
307
+ BEGIN CATCH
308
+ IF @@TRANCOUNT > 0
309
+ BEGIN
310
+ ROLLBACK TRANSACTION;
311
+ END;
276
312
277
- COMMIT TRANSACTION;
313
+ THROW;
314
+ END CATCH;
278
315
```
279
316
280
317
** Do not use this UPSERT pattern:** It will produce primary key violations when run concurrently.
@@ -331,19 +368,28 @@ WHEN NOT MATCHED BY SOURCE THEN
331
368
This method will not prevent a race condition and the last update will win.
332
369
333
370
``` sql
334
- SET NOCOUNT, XACT_ABORT ON ;
335
- BEGIN TRANSACTION;
371
+ BEGIN TRY
372
+ BEGIN TRANSACTION;
336
373
337
- IF EXISTS (SELECT * FROM dbo .Person WITH (UPDLOCK, SERIALIZABLE) WHERE PersonId = @PersonId)
338
- BEGIN
339
- UPDATE dbo .Person SET FirstName = @FirstName WHERE PersonId = @PersonId;
340
- END;
341
- ELSE
374
+ IF EXISTS (SELECT * FROM dbo .Person WITH (UPDLOCK, SERIALIZABLE) WHERE PersonId = @PersonId)
375
+ BEGIN
376
+ UPDATE dbo .Person SET FirstName = @FirstName WHERE PersonId = @PersonId;
377
+ END;
378
+ ELSE
379
+ BEGIN
380
+ INSERT dbo .Person (PersonId, FirstName) VALUES (@PersonId, @FirstName);
381
+ END;
382
+
383
+ COMMIT TRANSACTION;
384
+ END TRY
385
+ BEGIN CATCH
386
+ IF @@TRANCOUNT > 0
342
387
BEGIN
343
- INSERT dbo . Person (PersonId, FirstName) VALUES (@PersonId, @FirstName) ;
388
+ ROLLBACK TRANSACTION ;
344
389
END;
345
390
346
- COMMIT TRANSACTION;
391
+ THROW;
392
+ END CATCH;
347
393
```
348
394
349
395
[ Back to top] ( #top )
0 commit comments