Please start any new threads on our new site at https://forums.sqlteam.com. We've got lots of great SQL Server experts to answer whatever question you can come up with.

 All Forums
 SQL Server 2000 Forums
 SQL Server Development (2000)
 Complex Query Kills Cursor Declaration in Stored Procedure

Author  Topic 

AskSQLTeam
Ask SQLTeam Question

0 Posts

Posted - 2001-12-18 : 09:23:26
Frederick writes "I have the following stored procedure for iterating through a SELECT result set and returning records based on a 'limit' and offset'. Here is the SP code:

-------------------------

CREATE PROCEDURE LimitSelect
@query CHAR (128), -- SQL query, it'd better be a SELECT!
@limit INT, -- limit the result set of the query
@offset INT -- start result set from offset
AS
-- Execute call to declare a global cursor (node_cursor) for the query passed to the SP
EXEC ('DECLARE node_cursor CURSOR GLOBAL SCROLL READ_ONLY FOR ' + @query)

-- open the global cursor declared above
OPEN node_cursor

-- tweak the starting values of limit and offset for use in the loop
SET @offset = @offset + 1
SET @limit = @limit - 1

-- advanced the cursor to the offset in the result set
FETCH ABSOLUTE @offset FROM node_cursor

-- counter i
DECLARE @i INTEGER
SET @i = 0

-- loop until limit reached by counter i
WHILE (@i < @limit)
BEGIN
-- fetch the next row in the result set and advance counter i
FETCH NEXT FROM node_cursor
SET @i = @i + 1
END

-- clean finish
CLOSE node_cursor
DEALLOCATE node_cursor


-------------------------

This stored procedure works fine in most cases, but if the WHERE clause of the SELECT query passed to the SP becomes too complex, the cursor declaration in the SP tends to fail without explanation. I was wondering if you know why it is failing and how to prevent it from doing so.

Here is an example that creates a curor declaration failure:

LimitSelect '
SELECT * FROM news
WHERE
cat_id in(10, 11) AND
is_disabled=0 AND
(news_date BETWEEN 978328800 AND 1009864799 )
ORDER BY news_date DESC
', 5, 1


However, removing one WHERE condition will enable the procedure to execute properly:

LimitSelect '
SELECT * FROM news
WHERE
cat_id in(10, 11) AND
(news_date BETWEEN 978328800 AND 1009864799 )
ORDER BY news_date DESC
', 5, 1


Any thoughts on why this is? I'm working with SQL Server 7.0, BTW."

nr
SQLTeam MVY

12543 Posts

Posted - 2001-12-18 : 09:50:27
Well there's a thing.

Sorry to not be very helpful but the signature says it all.

Which service pack do you have - cursors tend to be complicated structures and get a lot of fixes.
What happens when you run the selects on there own - do they get a very different query plan? Try an index hint if an index is not being used in the failure. Always worth setting maxdop = 1 if you have multi processors.



==========================================
Cursors are useful if you don't know sql.
Beer is not cold and it isn't fizzy.
Go to Top of Page

robvolk
Most Valuable Yak

15732 Posts

Posted - 2001-12-18 : 10:07:23
While I don't share Nigel's passionate, virulent hatred for cursors (I just dislike them intensely!), I agree with him here. And I also have to ask what exactly the procedure is doing, besides looping through the cursor from start point to finish? Why can't this data be put into a table, temp or permanent, or simply queried? Nothing in your code suggests that a cursor is needed at all.

Go to Top of Page

nr
SQLTeam MVY

12543 Posts

Posted - 2001-12-18 : 10:15:09
Saying that though - finding out more about the error might be interesting.
I would guess (hope) that there is more code that is not relevent to the error.

==========================================
Cursors are useful if you don't know sql.
Beer is not cold and it isn't fizzy.
Go to Top of Page

Teroman
Posting Yak Master

115 Posts

Posted - 2001-12-18 : 11:28:19
i think it might be quite simple, the char(128) is truncating the select SQL to give bad syntax, hence it falls over

try select ing the @query variable at the start to see if im right, i didnt bother counting the characters, call me lazy ;)

change the variable to varchar(4000) or something to save hassle

col


<edit>
i just copied and pasted it and did a len() on the one that failed, seems like its about 190 characters.
Ain't I good to you.
</edit>


Edited by - teroman on 12/18/2001 11:31:04
Go to Top of Page

nr
SQLTeam MVY

12543 Posts

Posted - 2001-12-18 : 12:07:21


==========================================
Cursors are useful if you don't know sql.
Beer is not cold and it isn't fizzy.
Go to Top of Page

vector
Starting Member

1 Post

Posted - 2001-12-19 : 00:18:57

D'oh! Good call, Teroman. That appears to be the problem. I changed it to 'char(1024)' and it seems to work fine. Pardon me, I'm something of a putz.

Nothing like a good ol' doltish variable type bug in an SP to make an entire application foobar!

Thanks for the help. The LimitSelect stored procedure works really well for creating a pagescrolling interface to a table. Please feel free to use it or distribute it. The procedure seems to run quite speedily on my tables but none of my tables are more than 50000 records long. I'm not sure how well performance would be on really large tables.

-Frederick D. Whitlark



Go to Top of Page

robvolk
Most Valuable Yak

15732 Posts

Posted - 2001-12-19 : 09:40:08
quote:
The LimitSelect stored procedure works really well for creating a pagescrolling interface to a table.


Duhhhhhhhhhhhhh! Man I hate it when I don't pay attention!

You could declare @query as varchar(8000), just in case you use much more complex SQL statements in the future. That way you won't have to worry about chasing the same problem months or years from now.

Go to Top of Page
   

- Advertisement -