on 2012 Jul 08 4:24 PM
There isn't any purpose, is there? 'cause if there WAS, then the following code wouldn't work (which it does)...
FOR f_pointless AS c_meaningless INSENSITIVE CURSOR FOR SELECT row_num AS @row_num FROM RowGenerator WHERE row_num IN ( 1, 2 ) ORDER BY row_num FOR READ ONLY DO MESSAGE STRING ( 'RowGenerator.row_num = ', @row_num ) TO CONSOLE; END FOR; FOR f_pointless AS c_meaningless INSENSITIVE CURSOR FOR SELECT row_num AS @row_num FROM RowGenerator WHERE row_num IN ( 1, 2 ) ORDER BY row_num FOR READ ONLY DO MESSAGE STRING ( 'RowGenerator.row_num = ', @row_num ) TO CONSOLE; END FOR; FOR f_pointless AS c_meaningless INSENSITIVE CURSOR FOR SELECT row_num AS @row_num FROM RowGenerator WHERE row_num IN ( 1, 2 ) ORDER BY row_num FOR READ ONLY DO MESSAGE STRING ( 'RowGenerator.row_num = ', @row_num ) TO CONSOLE; END FOR; RowGenerator.row_num = 1 RowGenerator.row_num = 2 RowGenerator.row_num = 1 RowGenerator.row_num = 2 RowGenerator.row_num = 1 RowGenerator.row_num = 2
Can anyone say "COBOL"? 🙂
A little bird said, "Be careful trying to prove something using dbisql!"
...but I rarely pay attention to little birds, so I missed the fact that dbisql processes each statement (compound or otherwise) as a separate batch.
Watch what happens when dbisql is forced to send all the FOR statements to the server as one batch (which mimics how a stored procedure works with its own BEGIN END block):
BEGIN -- put all the FOR statements inside one block FOR f_pointless AS c_meaningless INSENSITIVE CURSOR FOR SELECT row_num AS @row_num FROM RowGenerator WHERE row_num IN ( 1, 2 ) ORDER BY row_num FOR READ ONLY DO MESSAGE STRING ( 'RowGenerator.row_num = ', @row_num ) TO CONSOLE; END FOR; FOR f_pointless AS c_meaningless INSENSITIVE CURSOR FOR SELECT row_num AS @row_num FROM RowGenerator WHERE row_num IN ( 1, 2 ) ORDER BY row_num FOR READ ONLY DO MESSAGE STRING ( 'RowGenerator.row_num = ', @row_num ) TO CONSOLE; END FOR; FOR f_pointless AS c_meaningless INSENSITIVE CURSOR FOR SELECT row_num AS @row_num FROM RowGenerator WHERE row_num IN ( 1, 2 ) ORDER BY row_num FOR READ ONLY DO MESSAGE STRING ( 'RowGenerator.row_num = ', @row_num ) TO CONSOLE; END FOR; END; Could not execute statement. Item 'c_meaningless' already exists SQLCODE=-110, ODBC 3 State="42S01" Line 1, column 1
BEGIN -- put all the FOR statements inside one block FOR w AS x INSENSITIVE CURSOR FOR SELECT row_num AS @row_num FROM RowGenerator WHERE row_num IN ( 1, 2 ) ORDER BY row_num FOR READ ONLY DO MESSAGE STRING ( 'RowGenerator.row_num = ', @row_num ) TO CONSOLE; END FOR; FOR w AS y INSENSITIVE CURSOR FOR SELECT row_num AS @row_num FROM RowGenerator WHERE row_num IN ( 1, 2 ) ORDER BY row_num FOR READ ONLY DO MESSAGE STRING ( 'RowGenerator.row_num = ', @row_num ) TO CONSOLE; END FOR; FOR w AS z INSENSITIVE CURSOR FOR SELECT row_num AS @row_num FROM RowGenerator WHERE row_num IN ( 1, 2 ) ORDER BY row_num FOR READ ONLY DO MESSAGE STRING ( 'RowGenerator.row_num = ', @row_num ) TO CONSOLE; END FOR; END; RowGenerator.row_num = 1 RowGenerator.row_num = 2 RowGenerator.row_num = 1 RowGenerator.row_num = 2 RowGenerator.row_num = 1 RowGenerator.row_num = 2
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
Did I say *"Breck, thanks for raising the question...":)
Yes, obviously I've stumbled again over a "test with dbisql" anti-pattern:(
So cursor names do not truly fit in my understanding of scope, as the docs on DECLARE CURSOR clearly state:
In SQL Anywhere, all cursors in a given scope must have unique names.
If I put the different FOR statements from your new sample in their own begin/end blocks (which would mean they should have "extra block scope), I still get that error message. That should not happen, as the docs also tell:
If a cursor is declared inside a compound statement, it exists only for the duration of that compound statement (whether it is declared in a Watcom SQL or Transact-SQL compound statement).
Or is that another pitfall of testing with dbisql?
I can't tell for the loop name, however, there is a usage for the cursor name, as it can be used for positioned updates/deletes, i.e. for
UPDATE foo SET bar = 1 WHERE CURRENT OF c_not_so_meaningless;
EDIT based on Breck's comment: The cursor name is required, the sample is irritating as it does use "SCROLL" as cursor name - "SCROLLY" would work, too. I've dropped a DCX note:)
Besides that, I share your impression: I'm used to name the loop and the cursor rather mechanically (say, with some kind of dummy names)...
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
I guess you've answered my real question, "I don't have to sweat the FOR loop and cursor names, do I? I can just use 'x' for both of them and be done with it, since they don't have scope outside the FOR loop itself."
For years I've worried about this, possibly confusing FOR with the rules for old-school DECLARE CRAPPY CURSOR.
"WHERE CURRENT OF"... doh!
Since I almost always code that as "WHERE CURRENT OF CURSOR" and have to go back and put in the name, it should be burned into my brain 🙂
OTOH some folks remember pain, others not, and I'm one of the "nots".
As to your underlying question: "Can I re-use loop names and cursor names for subsequent FOR statements?" - the docs do answer that - cf. that excerpt from the "Remarks" section:
The FOR statement is equivalent to a compound statement with a DECLARE for the cursor and a DECLARE of a variable for each column in the result set of the cursor followed by a loop that fetches one row from the cursor into the local variables and executes statement-list once for each row in the cursor.
So each FOR statement is a compound statement in itself and has its own block scope, and names won't conflict with each other.
That handling does it permit to use
If you've got the impression the docs could be more elaborate here, I'd second that:)
And no, I wasn't aware of that particular feature of the beloved FOR statement, either - thanks for raising the question, Breck!
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
FWIW, Ivan has documented the required uniqueness of cursor names (independent of their scope) within one single processed statement in DCX:
User | Count |
---|---|
73 | |
10 | |
8 | |
7 | |
7 | |
6 | |
6 | |
6 | |
6 | |
6 |
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.