I am trying to write a stored procedure in MySQL which will perform a somewhat simple select query, and then loop over the results in order to decide whether to perform additional queries, data transformations, or discard the data altogether. Effectively, I want to implement this:
$result = mysql_query("SELECT something FROM somewhere WHERE some stuff"); while ($row = mysql_fetch_assoc($result)) { // check values of certain fields, decide to perform more queries, or not // tack it all into the returning result set }
Only, I want it only in MySQL, so it can be called as a procedure. I know that for triggers, there is the FOR EACH ROW ...
syntax, but I can't find mention of anything like this for use outside of the CREATE TRIGGER ...
syntax. I have read through some of the looping mechanisms in MySQL, but so far all I can imagine is that I would be implementing something like this:
SET @S = 1; LOOP SELECT * FROM somewhere WHERE some_conditions LIMIT @S, 1 -- IF NO RESULTS THEN LEAVE -- DO SOMETHING SET @S = @S + 1; END LOOP
Although even this is somewhat hazy in my mind.
For reference, though I don't think it's necessarily relevant, the initial query will be joining four tables together to form a model of hierarchal permissions, and then based on how high up the chain a specific permission is, it will retrieve additional information about the children to which that permission should be inherited.
Use CURSOR in a Stored Procedure to Loop Through All Rows of MySQL Table. We use a CURSOR to handle the result set in a stored procedure. It lets us loop through a set of records (rows) returned by a query and process every row individually. One must have the following properties of CURSOR while using it.
LOOP Statement The syntax for this statement is as follows: [ label :] LOOP statements END LOOP [ label ]; The statements between the LOOP and END LOOP statements will be repeated indefinitely, until the LOOP is terminated. You can terminate the LOOP using the LEAVE statement, which we will describe shortly.
The SQL Continue statement is very useful to control the flow of a While loop. Generally, we use this Continue statement inside the While loop. If the execution finds the SQL continue statement inside the While loop, it will stop executing the current loop iteration and starts the new iteration from the beginning.
Something like this should do the trick (However, read after the snippet for more info)
CREATE PROCEDURE GetFilteredData() BEGIN DECLARE bDone INT; DECLARE var1 CHAR(16); -- or approriate type DECLARE Var2 INT; DECLARE Var3 VARCHAR(50); DECLARE curs CURSOR FOR SELECT something FROM somewhere WHERE some stuff; DECLARE CONTINUE HANDLER FOR NOT FOUND SET bDone = 1; DROP TEMPORARY TABLE IF EXISTS tblResults; CREATE TEMPORARY TABLE IF NOT EXISTS tblResults ( --Fld1 type, --Fld2 type, --... ); OPEN curs; SET bDone = 0; REPEAT FETCH curs INTO var1,, b; IF whatever_filtering_desired -- here for whatever_transformation_may_be_desired INSERT INTO tblResults VALUES (var1, var2, var3 ...); END IF; UNTIL bDone END REPEAT; CLOSE curs; SELECT * FROM tblResults; END
A few things to consider...
Concerning the snippet above:
More generally: trying to avoid needing a cursor.
I purposely named the cursor variable curs[e], because cursors are a mixed blessing. They can help us implement complicated business rules that may be difficult to express in the declarative form of SQL, but it then brings us to use the procedural (imperative) form of SQL, which is a general feature of SQL which is neither very friendly/expressive, programming-wise, and often less efficient performance-wise.
Maybe you can look into expressing the transformation and filtering desired in the context of a "plain" (declarative) SQL query.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With