Cursors are usually not a disease, but a symptom of this: do not use a set-based approach (as mentioned in other answers).
Not understanding this problem and simply believing that avoiding the "evil" cursor will solve it can get worse.
For example, replacing a cursor iteration with another iterative code, such as moving data to temporary tables or table variables, iterate over rows in the following way:
SELECT * FROM @temptable WHERE Id=@counter
or
SELECT TOP 1 * FROM @temptable WHERE Id>@lastId
This approach, as shown in the code for another answer, makes things much worse and does not fix the original problem. This is an anti-pattern called cult worship programming: not knowing WHY something is bad and thus introducing something worse to avoid it! I recently changed this code (using #temptable and no index on identity / PK) back to the cursor, and updating just over 10,000 lines took only 1 second, and not almost 3 minutes. Still lacking a set-based approach (being a lesser evil), but best of all, I could make this point.
Another sign of this lack of understanding may be what I sometimes call the “single object disease”: database applications that process individual objects through data access levels or object-relational maps. Usually a code like:
var items = new List<Item>(); foreach(int oneId in itemIds) { items.Add(dataAccess.GetItemById(oneId); }
instead
var items = dataAccess.GetItemsByIds(itemIds);
The first, as a rule, floods the database with a multitude of SELECT, one round-the-world route for each, especially when trees / diagrams of objects come into play, and the notorious SELECT N + 1 problem.
This is the side of the application that does not understand relational databases and establishes an approach based on them, just like cursors are used when using database procedural code such as T-SQL or PL / SQL!
Erik Hart Jun 21 '15 at 12:54 2015-06-21 12:54
source share