Database Journal
MS SQL Oracle DB2 Access MySQL PostgreSQL Sybase PHP SQL Etc SQL Scripts & Samples Links Database Forum

» Database Journal Home
» Database Articles
» Database Tutorials
MS SQL
Oracle
DB2
MS Access
MySQL
» RESOURCES
Database Tools
SQL Scripts & Samples
Links
» Database Forum
» Sitemap
Free Newsletters:
DatabaseDaily  
News Via RSS Feed


follow us on Twitter
Database Journal |DBA Support |SQLCourse |SQLCourse2
 

Featured Database Articles

MySQL

Posted Oct 11, 2005

MySQL Stored Procedures: Part 3 - Page 2

By Ian Gilfillan



Cursors


Cursors are another of the frequently demanded features now supported by MySQL 5. For those familiar with other DBMS implementations, MySQL 5 does not yet support them completely. In fact, it has some quite severe restrictions. MySQL 5's cursors are asensitive (so you should not update the table while using a cursor, otherwise you will get unpredictable results), read-only (you cannot update using the cursor position) and non-scrolling (you can only move forward to the next record, not back and forth).


In general, cursors are used to access a resultset that can be retrieved one or more rows at a time. They are also used for positioning a pointer at a specific row, and can allow updates to rows based upon this current position; although as mentioned, MySQL does not support this. The term cursor is short for CUrrent Set Of Records. In our examples, we will use the same table, sp1, we used in part 1 of this series. When we left off, the table contained the following records:



mysql> SELECT * FROM sp1\G
*************************** 1. row ***************************
 id: 3
txt: 414243
*************************** 2. row ***************************
 id: 40
txt: 444546
2 rows in set (0.00 sec)

Here is a sample procedure containing a cursor.

mysql>
CREATE PROCEDURE sp9 (OUT rx INT, OUT ry INT)
 BEGIN
  DECLARE x,y INT;
  DECLARE sp1_cursor CURSOR FOR SELECT id,txt FROM sp1;
  OPEN sp1_cursor;
   FETCH sp1_cursor INTO x,y;
  CLOSE sp1_cursor;
  SET rx = x;
  SET ry = y;
 END |
 
mysql> CALL sp9(@x,@y)\G
Query OK, 0 rows affected (0.00 sec)
mysql> SELECT @x,@y\G
*************************** 1. row ***************************
@x: 3
@y: 414243
1 row in set (0.01 sec)

Here we declared variables (x and y and a cursor (sp1_cursor). The order of declarations is important - they must be in a particular order - variables and conditions, then cursors, then handlers.

Next is a new statement - OPEN sp1_cursor, which activates the cursor we declared earlier. The FETCH statement is the one that does all the magic, returning the next row of the actual resultset. Results must be placed somewhere, and the two variables x and y are the recipients of the two columns returned by the SELECT id,txt FROM sp1 query that makes up the cursor. The cursor is then closed (although MySQL will free the resources when it reaches the end of the compound statement block for you if you do not explicitly do so), and the results assigned to the two OUT variables. By calling the procedure, and then querying the two session variables that receive the results, we can see that they have been populated with the first row from the sp1 table, as expected.

However, returning just one row is not particularly useful. We need to loop through the entire resultset and return the results. We can achieve this using a simple REPEAT UNTIL loop, which we were introduced to in part 2.

mysql>
CREATE PROCEDURE sp10 (OUT rx INT, OUT ry INT)
 BEGIN
  DECLARE x,y,z INT;
  DECLARE sp1_cursor CURSOR FOR SELECT id,txt FROM sp1;
  DECLARE CONTINUE HANDLER FOR NOT FOUND SET z = 1;
  OPEN sp1_cursor;
  REPEAT
   FETCH sp1_cursor INTO x,y;
   UNTIL (z=1)
  END REPEAT;
  CLOSE sp1_cursor;
  SET rx = x;
  SET ry = y;
 END |
 
mysql> CALL sp10(@x,@y)|
Query OK, 0 rows affected (0.00 sec)
mysql> SELECT @x,@y\G
*************************** 1. row ***************************
@x: 40
@y: 444546
1 row in set (0.00 sec)

The handler is declared for the NOT FOUND condition. The handler sets the variable z to 1, and z=1 is the condition the REPEAT UNTIL loop tests for. As mentioned earlier, the NOT FOUND condition includes all errors with an SQLSTATE beginning with 02, one of which is the No data to FETCH error. This will apply when we have retrieved all the rows in the table. As expected, upon calling the procedure and querying the session variables, this time we see the last row of the sp1table, as in the procedure each row's data is assigned to rx and ry, overwriting the previous contents.

Conclusion

This month was the last of our series on stored procedures. MySQL developers will find them a great new tool in developing applications, and applications running on MySQL can now finally make use of the robustness and flexibility of stored procedures, removing unwanted logic from the application code. Next month, we look at the closely related stored functions feature.

Resources

» See All Articles by Columnist Ian Gilfillan



MySQL Archives

Comment and Contribute

 


(Maximum characters: 1200). You have characters left.

 

 




Latest Forum Threads
MySQL Forum
Topic By Replies Updated
MySQL in high availability and transction secure banking application klamor 1 August 28th, 10:24 AM
MySQL rollback UAL225 1 August 28th, 10:15 AM
Browsing a DB file that uses MySql finleytech 1 July 26th, 10:51 AM
php cookie won't pass variable to next page ITdevGirl 0 June 22nd, 12:13 PM