• Hugo Kornelis (7/4/2015)


    Jeff Moden (7/3/2015)


    andrew.norris 90251 (6/7/2015)


    Nothing wrong with cursors they have their place and are very useful.

    Do you have examples for something other hierarchies and bin stacking problems?

    A few examples I have run into during the last few years:

    A DB application that is designed to interact with an external system, using an interface to get information (e.g. current usage of an account) and change information (new accounts, usage caps, etc). The interface is API based - a single call for a single account. I needed a lot of cursors for that customer!

    A different DB application that had a list of procedure execution rules in a configuration table. At set times, it would analyse what events had taken place (setbased), determine which procedures had to run based on that (setbased), determine the proper execution order (setbased), and then call each of the procedures that, again in setbased fashion, would process the appropriate changes. The bit where the procedures were called was cursor-based.

    And then there are of course the many utility procedures used by DAs. Ever tried to create an index maintenance script that does not use a cursor or other form of iteration?

    Now all 3 of those are what I think cursors where brought into being for and are excellent examples of one great aspect of what cursors sometimes need to be used for... flow control and forced RBAR. Yes, things like index maintenance can be done without cursors or the nearly equivalent Temp Table/While Loop methods but they just make separate commands and concatenate them together. The end result is the same... one command per command row.

    To emphasize a bit on Hugo's good examples...

    Other examples might be when you need to do the same thing to multiple tables or multiple databases. An example of this can be found in the sys.sp_MSforeachdb and sys.sp_MSforeachtable system stored procedures that people sometimes use.

    Shifting gears a bit, there are two points that a lot of people bring up during discussions of cursors....

    One of the points that I'm slowly trying to build up to is like the hierarchy challenge I posted. The "best practice" (notice the quotes) is to do things set-based unless you absolutely have to use a cursor (which is what I also call While Loops, single-row-per-iteration Recursive CTEs, and certain types of UDFs). Unfortunately, a lot of people think that they absolutely have to use a cursor way too early in the game.

    That's a segue into the next problem that a lot of people have with cursors and other forms of RBAR. They'll frequently say that cursors are easier to write, understand, read, and troubleshoot and that set-based methods take more code and it's complex to troubleshoot. Yes, writing set-based code does require a different paradigm (see my signature line below) and you do actually need to know what you're doing, but that's not a justification for writing cursors or other forms of RBAR. Rather, it should be motivation to learn more about how to write effective database code. In most cases (there are exceptions to all rules and observations, "It Depends"), not only is set-based code frequently tens to thousands of times faster and more resource efficient, it's usually shorter and easier to understand once you've trained yourself to understand such things. People saying that set-based is confusing just means they haven't spent enough time learning it. It's the same problem that a lot of people had when OOPs appeared or using Knuth's famous quote to justify what is actually poor programming rather than what its original purpose was.

    The bottom line is that if people don't spend the time to learn how to effectively program against databases, then set-based code will never be in their comfort zone and they'll continue to fall back into their personal comfort zone and they'll continue to justify their use of cursors with the "best practice" of using a cursor if it "can't" be done using set-based code. So, learn some of the math (it's not that hard and I'm not talking about deep relational database concepts such as being able to define things like "relational division", although that will never hurt) that makes for really good set-based code and practice finding a set-based solution every chance you get and you'll be a much more valuable "hybrid" programmer. Yep... I understand getting stuff out the door but if you don't go back to find the set-based alternate for a RBAR solution, then you're not doing yourself or the company you work for any favors. It's part of your job to get better at what you do.

    --Jeff Moden


    RBAR is pronounced "ree-bar" and is a "Modenism" for Row-By-Agonizing-Row.
    First step towards the paradigm shift of writing Set Based code:
    ________Stop thinking about what you want to do to a ROW... think, instead, of what you want to do to a COLUMN.

    Change is inevitable... Change for the better is not.


    Helpful Links:
    How to post code problems
    How to Post Performance Problems
    Create a Tally Function (fnTally)