What is the purpose of OUT in MySQL stored procedures?
If I have a simple stored procedure which looks like this:
DELIMITER $$
CREATE DEFINER=`root`#`localhost` PROCEDURE `new_routine`(
IN iID int
)
BEGIN
select * from table1 where id = iID;
END
This would give me all the results I want by running:
call new_routine(7);
So why would I want/need to use OUT?
DELIMITER $$
CREATE DEFINER=`root`#`localhost` PROCEDURE `new_routine`(
IN iID int,
OUT vName varchar(100)
)
BEGIN
select name into vName from table1 where id = iID;
END
and call it like this
call new_routine(7, #name);
select #name;
Which will give me just the name instead of everything from the rows returned?
I've tried Googling, but clearly haven't asked Google the right question to get a clear answer.
As quoted from MySQL doc on PROCEDURE
For each OUT or INOUT parameter, pass a user-defined variable in the
CALL statement that invokes the procedure so that you can obtain its
value when the procedure returns. If you are calling the procedure
from within another stored procedure or function, you can also pass a
routine parameter or local routine variable as an IN or INOUT
parameter.
And later, an example:
mysql> CREATE PROCEDURE simpleproc (OUT param1 INT)
-> BEGIN
-> SELECT COUNT(*) INTO param1 FROM t;
-> END//
Query OK, 0 rows affected (0.00 sec)
mysql> delimiter ;
mysql> CALL simpleproc(#a);
Query OK, 0 rows affected (0.00 sec)
mysql> SELECT #a;
+------+
| #a |
+------+
| 3 |
+------+
1 row in set (0.00 sec)
Yeah, you're right, with that second call you will now only get the name itself.
Out-Parameters for many people are generally considered bad practice, but they can be handy if you want a value that you can work with after the call (which could also be calculated by a function obviously). And in most cases there is a better way to achieve what you want without using out-parameters.
However the only "advantage" if you will is that you have a value in a variable instead of a result set which might seem more handy if you decide to use only that value further in your sql or whereever you want to work with it.
So in most cases you should really not use out-parameters, use functions instead.
If you have procedures that return result sets AND out-parameters try to break them down into smaller functions/procedures to avoid out-parameters, because it's just not nice to read and maintain ;)
Some documentation: http://dev.mysql.com/doc/refman/5.0/en/call.html maybe it will help, quote:
To get back a value from a procedure using an OUT or INOUT parameter,
pass the parameter by means of a user variable, and then check the
value of the variable after the procedure returns. (If you are calling
the procedure from within another stored procedure or function, you
can also pass a routine parameter or local routine variable as an IN
or INOUT parameter.) For an INOUT parameter, initialize its value
before passing it to the procedure. The following procedure has an OUT
parameter that the procedure sets to the current server version, and
an INOUT value that the procedure increments by one from its current
value:
CREATE PROCEDURE p (OUT ver_param VARCHAR(25), INOUT incr_param INT)
BEGIN
# Set value of OUT parameter
SELECT VERSION() INTO ver_param;
# Increment value of INOUT parameter
SET incr_param = incr_param + 1;
END;
The use of the OUT keyword is stated in the following article
13.2.1. CALL Syntax
CALL can pass back values to its caller using parameters that are
declared as OUT or INOUT parameters.
Related
I have created a procedure which returns a single column of officeid
call officetree(15);
I need to get list of employee under officeid's return by officetree procedure
select * from master_employee where officeid in ( here i want put my officeids return from procedure)
Is this possible to achieve this if yes what is the syntax for that.
Inside the procedure
Below ofcid is parameter of procedure
select `ofc_id`
from (select * from master_office
order by `ofc_parent_id`, `ofc_id`) master_office,
(select #pv := ofcid) office
where (find_in_set(`ofc_parent_id`, #pv) > 0
and #pv := concat(#pv, ',', `ofc_id`)) or ofc_id=ofcid
No, AFAIK, you can not use a SP as sub query in MySQL.
Ref: Using a stored procedure as subquery
Ref: https://forums.mysql.com/read.php?10,556522,556538#msg-556538
Is it possible to call stored procs in MySQL 5.5 subqueries.
No.
And for a suggestion, use stored procedure as few as possible (my ten-year experience tells me)
I think there is no way to use a stored procedure result like a subquery.
Your alternatives:
Use the statement from the procedure as subquery.
Fetch the IDs from the SP in PHP and execute a second query with the fetched IDs. select * from master_employee where officeid in ( list of previously fetched IDs )
Use a more powerfull design for the tree structure like "materialized path" or "transitive closure table"
I need to update a table in SQL via php.
When i log in to my database and write:
UPDATE table1
SET whatiwant = whatiwant
it updates all. That what i want.
But when i write this in PHP, it is not working.
I need to give him a Where clause to execute it and i have to loop through all entries.
UPDATE table1
SET whatiwant = whatiwant
WHERE id = '1'
I need to update all the entries. Why is it not working?
Use:
WHERE 1 = 1
to match all records.
or if there needs to be an Id on the left side use something that's impossible to match, e.g.:
WHERE Id <> -1
if you have id only positive numbers.
If you want to run update all the time write your statement without where otherwise if you want this SQL statement do 2 different behavior, you have to write a Stored Procedure with a parameter #id :
If a value pass to the parameter #id, it works well
If you pass null to that, it updates all rows without any where clause
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE PROCEDURE SP
#id int =null
AS
BEGIN
UPDATE table1
SET whatiwant = whatiwant
WHERE (id = #id OR #id IS NULL)
END
GO
I am executing a PLSQL Block using OCI from my PHP site which is running some procedures inside. The final procedure is returning the inserted records rowid of a specific table.
BEGIN
proc1(1);
proc2(2, rowid_);
END;
What I want to do is, I want to get the primary key values of the record for this rowid?
Is there a way to run it somehow like below and get the select results out to PHP with oci_fetch_row or something?
BEGIN
proc1();
proc2(rowid_); -- out variable
SELECT column1, column2
FROM my_table
WHERE rowid = rowid_;
END;
There's a better way. Try something like:
DECLARE
nPK_col NUMBER;
nCol1 NUMBER := 1;
nCol2 NUMBER := 2;
BEGIN
INSERT INTO SOME_TABLE(COL1, COL2)
VALUES (nCol1, nCol2)
RETURNING PK_COL INTO nPK_col;
END;
This example assumes that the primary key column named PK_COL is populated in some way during the execution of the INSERT statement, e.g. by a trigger. The RETURNING clause of the INSERT statement specifies that the value of PK_COL from the inserted row should be put into the variable specified, in this case nPK_col. You can specify multiple columns and variables in the RETURNING clause - documentation here. You may need to put this into whatever procedure performs the actual INSERT and then add an OUT parameter to allow the value to be passed back to the caller - or use a FUNCTION instead of a PROCEDURE and have the primary key value be the return value of the FUNCTION.
Share and enjoy.
I am trying to implement a procedure within mysql that returns the age based on a calculation.
The date of birth (DATE) is passed in and then the calculation is done. Should be relatively straight forward but I cannot seem to get it to work. I am not sure if this is an appropriate situation for a "select statement" and
I apologize if this is extremely simple but this is my first run at procedures.
If somebody could please tell me what I am doing wrong, it would be much appreciated.
Thanks!
P.S. I have a table called "PERSON" that contains the field "age" (int) which is currently empty until the stored procedure is called.
DELIMITER $$
CREATE PROCEDURE determineAge(IN birthDate DATE)
BEGIN
DECLARE today TIMESTAMP;
SELECT DATEDIFF(today,birthdate)/365 AS ageInYears
FROM PERSON;
END $$
DELIMITER ;
call determineAge('June 25, 1981');
This works. No need to declare "today" - just use a NOW() function in your query.
Also, no need to select FROM anything... you're just querying a single value.
Your date was formatted wrong (MySQL requires 'YYYY-MM-DD', and you want to floor the difference to get a whole number of years.
DELIMITER $$
CREATE PROCEDURE determineAge(IN birthDate DATE)
BEGIN
SELECT FLOOR(DATEDIFF(NOW(), DATE(birthdate))/365);
END $$
DELIMITER ;
CALL determineAge('1981-06-25');
Finally, you could theoretically return the year value as an OUT param if you wanted to, though a query result is just fine.
DELIMITER $$
CREATE PROCEDURE determineAge(IN birthDate DATE, OUT age INT)
BEGIN
SELECT FLOOR(DATEDIFF(NOW(), DATE(birthdate))/365) INTO age;
END $$
DELIMITER ;
There you go!
I'm attempting to pull data from a stored procedure using PDO, and I'm having a really rough time nailing this down. I've searched around for the last few days and cannot seem to find a direct solution to my problem.
This is how I created the procedure:
DELIMITER $$
CREATE PROCEDURE sp_searchArticles(
IN tagList VARCHAR(255),
IN lastArticle INT(10),
OUT data INT(10))
BEGIN
CREATE TEMPORARY TABLE at_results (
id INTEGER(10) NOT NULL AUTO_INCREMENT PRIMARY KEY,
article_id INTEGER(10) NOT NULL,
datetime DATETIME NOT NULL,
common_tags INTEGER NOT NULL)
SELECT at.article_id, art.datetime, Count(at.article_id) AS common_tags
FROM article_tags AS at
INNER JOIN articles AS art ON at.article_id = art.article_id
WHERE at.tag_id IN (tagList)
GROUP BY at.article_id
ORDER BY common_tags DESC, art.datetime DESC;
CREATE TEMPORARY TABLE at_article
SELECT id
FROM at_results
WHERE article_id = lastArticle;
SELECT article_id
INTO data
FROM at_results, at_article
WHERE at_results.id > at_article.id;
END $$
DELIMITER ;
Then I call the SP using PDO:
$sql = "CALL sp_searchArticles(:tag_list, :last_article, #data)";
$tag_sth = $this->db->prepare($sql);
$tag_sth->bindParam(':tag_list', $tag_list);
$tag_sth->bindParam(':last_article', $last_article);
$tag_sth->execute();
$data = $this->db->query("select #data")->fetch(PDO::FETCH_ASSOC);
But it returns "#1436 - Thread stack overrun:"
I have tried calling the stored procedure without using #data out variables, but I get HY000 errors. I did not originally want this call to be a stored procedure, but PDO doesn't seem to like the face that I have multiple statements in a single execution. Also, I cannot seem to call the procedure correctly using static parameters through phpmyadmin. The sql statements work perfectly outside of the procedure, however.
I'm not the most proficient with PDO and mySQL, but I've read a whole lot about bugs within phpmyadmin, PDO, and PHP that pertain to stored procedures. Any help would be greatly appreciated.
You may be utilizing more memory than MySQL is configured to allow you to use.
See:
MySQL error 1436: Thread stack overrun, with simple query
Try changing your my.cnf file, if you have access to it.