T-SQL Tuesday #200: It’s Bad If I See

Words: 578
Time to read: ~3 minutes

I think that I shall never see
this developer’s query is blinding me

Joyce Kilmer (if she was a DBA)

A picture of the T-SQL Tuesday logo; a blue database with a github style commit banner in a different blue wrapped around it.

Welcome to T-SQL Tuesday, the monthly blog party started by Adam Machanic ( blog ) and maintained by Steve Jones (blog | social media).

Each month, a different host chooses a topic for discussion. This month, we have Brent Ozar ( blog | social media ) asking us “if [we’re] looking at a query, it’s bad if [we] see…

Musings

This post, inspired by a recent one by Hannah Vernon ( blog | social media ), is about WHILE loops and CURSORs.

Here’s my prejudiced take: if your query has WHILE loops and/or CURSORs, then I’m going to assume it’s bad.

Now, the astute among you will note what I just said with the blog post I linked to, and that’s a fair point. This is a knee-jerk reaction to opening up a piece of code and skimming its contents.

So far, in my relatively short stint as a DBA (I’m going to keep saying that no matter how long I am one, btw), I have only encountered 4 scenarios where these Row-By-Agonising-Row (RBAR) methods are acceptable.

  1. See Hannah’s post – and it has to be commented that it’s an informed decision.
  2. You need to call a stored procedure on the records – I don’t know how to get around that
  3. You’re doing batching on mass writes – it’s more set-based inside RBAR than RBAR instead of set-based then
  4. Temporal tables – I’m still salty about this…

The Feck It It’s Worth It Scenario

Read her blog post (I linked it again and everything.)

I’m normally an advocate for “write it anyway in case the way you say it gets through to someone”, but her blog posts have been on fire lately, and more people should be reading them.

Wrench and Sproc it

Apart from gutting the stored procedure and inserting its code in your set-based method, there’s no real way around this.

And if that stored procedure calls another stored procedure? Boy howdy, I ain’t touching that one with a ten-foot pole!

Turtles All the Way Down

Today is not Link to Other People’s Blog Day, but I’m going to pretend it is.

Here’s Micheal J Swart ( blog ) on batching.

I’m going to call this Set-By-Agonising-Set instead of Row-By-Agonising-Row.

Whatever name it goes by, whatever the reason for it, e.g. transaction log space, locking, etc., batching solves issues that come around at scale.

Saltier Than the Old Man and the Sea

Temporal tables… _deep breaths, Shane_

Do you know how to query temporal tables using the FOR SYSTEM_TIME syntax?

Well, you can do:

... FOR SYSTEM_TIME ALL ...
... FOR SYSTEM_TIME AS OF '<date time value> ...
... FOR SYSTEM_TIME AS OF @<date time variable>...

This is great…for uniformity. And all of our result sets are uniform, right?

However, if you have a table of results and you want a different FOR SYSTEM_TIME AS OF value for each record in the results table…

Granted, I have no idea how to implement this, or if it’s even possible, but I’d like it!

RBAR = Crowbar

If I’m looking at a query, it’s bad if I see WHILE loops, or CURSORs, or RBAR options without a documented or commented reason why.

If you’ve come across any other scenario, please let me know. The temporal table is the most recent one for me, and I’m relying on that saltiness to keep me young and preserved. Anything extra would be appreciated.

Author: Shane O'Neill

DBA, T-SQL and PowerShell admirer, Food, Coffee, Whiskey (not necessarily in that order)...

4 thoughts on “T-SQL Tuesday #200: It’s Bad If I See”

  1. Great post Shane and bless you for linking to other smart people like Hannah.
    I totally agree that Cursors are generally a bad idea.
    However I have a IIMHO valid example where I use them at scale (and generate CURSOR code by other Procedures šŸ˜‚): Error Handling in a Data Warehouse Load. Off course I did my homework and declared this cursors as “LOCAL FORWARD_ONLY STATIC READ_ONLY” to get a bit of more performance out of them.

    Most of the time all is fine and the set based SQL INSERT works fine into a Data Warehouse Target.
    But if there are some hickups I would not like to fail the INSERT for a whole table just because of a few erroneous rows. Therefore I built a fallback to RBAR in my generated load procedures. If an error occurs the cursor comes into play and handles the rest…of course this is not pretty and it takes longer but you have a detailed log of which rows ran into an error and typically are able to salvage most of them and move on.
    Michael Swart’s post on batching sounds interesting but would be too much of a hassle if you run into errors in batches I guess then to retry and so on.

Leave a Reply

Discover more from No Column Name

Subscribe now to keep reading and get access to the full archive.

Continue reading