@variable
A solution of passing a result set between stored routines is frequently asked question on the official MySQL's Stored Procedures forum (see e.g. Calling PROCEDURE on SELECT output, Use resultset from sproc in select statement or in another sproc, and others).
Since MySQL does not support passing result sets in stored procedures, common practice is to use TEMPORARY TABLES when working with larger data sets.
01.
CREATE
PROCEDURE
`lib_Explode`(sSepar
VARCHAR
(255), saVal TEXT)
02.
body:
BEGIN
03.
04.
DROP
TEMPORARY
TABLE
IF EXISTS lib_Explode;
05.
CREATE
TEMPORARY
TABLE
lib_Explode(
06.
`pos`
int
unsigned
NOT
NULL
PRIMARY
KEY
auto_increment,
07.
`val`
VARCHAR
(255)
NOT
NULL
08.
) ENGINE=Memory COMMENT=
'Explode() results.'
;
09.
10.
SET
@saTail = saVal, @iSeparLen = LENGTH( sSepar );
11.
12.
create_layers:
13.
WHILE @saTail !=
''
DO
14.
# Get the
next
value
15.
SET
@sHead = SUBSTRING_INDEX(@saTail, sSepar, 1);
16.
SET
@saTail =
SUBSTRING
( @saTail, LENGTH(@sHead)+1+@iSeparLen );
17.
INSERT
INTO
lib_Explode
SET
val = @sHead;
18.
END
WHILE;
19.
20.
END
$$
Although, this approach introduces a drawback – you have to care about table names. There are three options:
(I personally prefer the last option.)
The much more ellegant solution would be if a variable could hold a result set. Let's see what would be possible with such feature.
@variable
First, let's create a 3 × 2 table:
1.
CREATE
TABLE
table1 ( a
INT
, b
INT
);
2.
INSERT
INTO
table1
VALUES
(1,2), (3,4), (5,6);
3.
SELECT
*
FROM
table1;
The table now looks like this:
a | b |
---|---|
1 | 2 |
3 | 4 |
5 | 6 |
Currently, we can select a single value into a variable:
1.
SELECT
a
FROM
table1
INTO
@var LIMIT 1;
But what much more cool would be if we could store a result set:
1.
##
Create
the result
set
and
store it
in
a variable.
2.
SELECT
*
FROM
table1
INTO
@resultset;
3.
-- or --
4.
SET
@resultset = (
SELECT
*
FROM
table1);
MySQL would recognize that we are assigning a result set. After executing,
@resultset
would be of special type RESULTSET
. Then,
we could pass it to a stored procedure.
1.
CREATE
PROCEDURE
StoredProcedure( rsData RESULTSET )
BEGIN
2.
SELECT
a + b
FROM
rsData;
3.
END
$$
4.
5.
## Pass the result
set
into
a stored
procedure
.
6.
CALL StoredProcedure( @resultset );
In the stored procedure, a RESULTSET
param could act exactly as
a TEMPORARY
table.
1.
## Retrieving a result
set
from
a stored
procedure
2.
CALL StoredProcedure()
INTO
@result;
3.
4.
-- or
5.
6.
SET
@result = (CALL StoredProcedure());
After executing, @result
would be of special type
RESULTSET
and contain the result of the first SELECT
performed in a procedure.
Multiple results from a CALL
could also be fetched:
1.
CREATE
PROCEDURE
StoredProcedure( rsData RESULTSET )
BEGIN
2.
SELECT
a + b
FROM
rsData;
3.
SELECT
a * b
FROM
rsData;
4.
END
$$
5.
6.
## Retrieving multiple result sets
from
a stored
procedure
7.
CALL StoredProcedure()
INTO
@result1, @result2;
So. This is my suggestion of how to deal with result sets in stored procedures. Hopefully I will see it in MySQL some day – it would reduce the code of my procedures near to half.