MySQL - use result of nested stored procedure - mysql

Is there any way to use the return value of a stored procedure in another stored procedure?
Just a very basic theoretical example:
CREATE PROCEDURE `user_read_name_and_email` (
IN `param_user_id` INT
)
BEGIN
DECLARE `current_user` SET;
SET `current_user` = CALL `user_read`(`param_user_id`);
SELECT `user_name`, `user_email` FROM `current_user`;
END
CREATE PROCEDURE `user_read` (
IN `param_user_id` INT
)
BEGIN
SELECT * FROM `user` WHERE `user_id` = `param_user_id`;
END

I think the one and only workaround is to use temporary tables.
Your example would be possible in MS SQL Server 2008 - there you can assing output of stored procedure to some variable.

Related

Mysql Procedure Syntax change to Firebird Procedure Syntax

I don't know what's different about the stored procedure of firebird syntax.
MySql Procedure:
ALTER PROCEDURE [dbo].[SP_CAL_SHIFTDTL]
(
#PSHIFTDTEFROM DATETIME,
#PSHIFTDTETO DATETIME
)
AS
BEGIN
SET NOCOUNT ON
DECLARE #GEN_EXCEPTION_FROM DATETIME,
#GEN_EXCEPTION_TO DATETIME
SELECT #GEN_EXCEPTION_FROM = #PSHIFTDTEFROM,
#GEN_EXCEPTION_TO = #PSHIFTDTETO
How can I change this one syntax for Firebird stored procedure?
SELECT #GEN_EXCEPTION_FROM = #PSHIFTDTEFROM,
#GEN_EXCEPTION_TO = #PSHIFTDTETO
The equivalent in Firebird PSQL syntax would be simple assignment, so GEN_EXCEPTION_FROM = PSHIFTDTEFROM; See also Assignment Statements in the Firebird Language Reference. The full equivalent of the fragment shown in your question would be:
RECREATE PROCEDURE SP_CAL_SHIFTDTL
(
PSHIFTDTEFROM TIMESTAMP,
PSHIFTDTETO TIMESTAMP
)
AS
DECLARE GEN_EXCEPTION_FROM TIMESTAMP;
DECLARE GEN_EXCEPTION_TO TIMESTAMP;
BEGIN
GEN_EXCEPTION_FROM = PSHIFTDTEFROM;
GEN_EXCEPTION_TO = PSHIFTDTETO;

MySql syntax error on procedure parameter

I am trying to write a simple procedure but am encountering a syntax error at the first parameter. As best I can tell I'm following the syntax of CREATE PROCEDURE correctly.
I am limited to accessing my database with phpMyAdmin. Here is the create script I'm trying to run:
DROP PROCEDURE IF EXISTS product_index_swap/
CREATE PROCEDURE product_index_swap (#id INT, #oldIndex INT, #newIndex INT)
BEGIN
DECLARE #swapID;
SET #swapID = (SELECT `id` FROM `product` WHERE `order_index` = #newIndex LIMIT 1);
UPDATE `products` SET `order_index` = (CASE WHEN `id` = #id THEN #newIndex
WHEN `id` = #swapID THEN #oldIndex END)
WHERE `id` IN (#id, #swapID);
END
I am using the option on phpMyAdmin to change the delimiter to /.
I receive a syntax error "near '#id INT, #oldIndex INT....". I thought I may encounter more delimiter errors since I'm not entirely clear on the scope of them. I believe if that was the problem the error would be on a new line in the procedure when it failed to understand a semicolon, not at the parameters declaration.
You're using the Microsoft SQL Server convention of putting # before all the parameters and local variables. MySQL doesn't do this.
In MySQL syntax, procedure parameters have no sigil.
Also parameters are typically declared IN or OUT or INOUT.
CREATE PROCEDURE product_index_swap (IN id INT, IN oldIndex INT, IN newIndex INT)
BEGIN
DECLARE swapID;
...
MySQL variables that have the # sigil are session variables.
See also:
https://dev.mysql.com/doc/refman/5.7/en/create-procedure.html
https://dev.mysql.com/doc/refman/5.7/en/declare-local-variable.html
https://dev.mysql.com/doc/refman/5.7/en/set-variable.html
In MySQL, the #var variables are session level variables.
Use normal variables without the # and make sure you do not have conflict with column names:
CREATE PROCEDURE product_index_swap (in_id INT, in_oldIndex INT, in_newIndex INT)
BEGIN
DECLARE v_swapID int;
SELECT id into v_swapID
FROM product
WHERE order_index = in_newIndex
LIMIT 1;
UPDATE products
SET order_index = CASE WHEN id = in_id THEN in_newIndex
WHEN id = v_swapID THEN in_oldIndex
END
WHERE id IN (in_id, v_swapID);
END

Mysql procedure, using parameter in where clause

I made this procedure from phpmyadmin, but it don't works, I replaced the last word from record_id to a specified string id and worked, but when I use the parameter not working.
DROP PROCEDURE `prcd_update_record`;
CREATE DEFINER=`root`#`localhost`
PROCEDURE `prcd_update_record`(
IN `talep_id` VARCHAR(24),
IN `vall` INT(10)
)
NOT DETERMINISTIC
MODIFIES SQL DATA SQL
SECURITY INVOKER
UPDATE `talep_malzeme`
SET `kalan_miktar` = vall
WHERE `talep_malzeme`.`id` = talep_id;
The I execute it like this:
SET #p0='33'; SET #p1='57fb7911ea91e9efa'; CALL `prcd_update_record`(#p0, #p1);
DROP PROCEDURE IF EXISTS `prcd_sevk_toplam`;
create procedure prcd_sevk_toplam(talep_id int, vall VARCHAR(255))
BEGIN
UPDATE `talep_malzeme` SET `kalan_miktar` = vall WHERE `talep_malzeme`.`id` = talep_id;
END;
Hope this will help you.
Looks like you has wrong parameter order, try
CALL `prcd_sevk_toplam`(#p1, #p0);
You should provide proper value to your parameter per your parameter definition. Your procedure accepts parameter as below
PROCEDURE `prcd_sevk_toplam`(
IN `talep_id` VARCHAR(24),
IN `vall` INT(10)
And you are setting both of them to varchar. That could be the issue here. You should set them as
SET #p0=33;
SET #p1='57fb7911ea91e9efa';
CALL `prcd_sevk_toplam`(#p1, #p0);

passing parameters to a stored procedure from a temp table

I have a senario where i have to pass parameters to a stored procedure from a temptable
#student(table)
StudentID Class
10008 A
10009 A
10010 C
The sproc accepts 2 parameters StudentID and Class.
Student_Fail #StudentID,#Class
I would like to execute this stored procedure for all the studentID(3 times).
How can this be done? using while loop?
Well ideally you should re-write the stored procedure so that it can just use the #temp table directly, or create a different stored procedure, or just replicate in this code what the stored procedure tries to do for a single row. (Set-based operations are almost always better than processing one row at a time.)
Short of that, you'd have to use a cursor or while loop (and no they aren't really different).
DECLARE #StudentID INT, #Class CHAR(1);
DECLARE c CURSOR LOCAL FAST_FORWARD
FOR SELECT StudentID, Class FROM #student;
OPEN c;
FETCH c INTO #StudentID, #Class;
WHILE ##FETCH_STATUS = 0
BEGIN
EXEC dbo.Student_Fail #StudentID, Class;
FETCH c INTO #StudentID, #Class;
END
CLOSE c;
DEALLOCATE c;
As you've indicated, a while loop will do:
declare #StudentID int
declare #Class char(1)
while exists (select 1 from #student)
begin
select top 1 #StudentID = StudentID
, #Class = Class
from #student
exec Student_Fail #StudentID, #Class
delete from #student where #StudentID = StudentID
end
Yes, this could be implemented as a WHILE loop, or as a CURSOR, since in this case they will do essentially the same thing, a row-by-row operation.
However, the ideal solution would be to re-implement the Student_Fail fail stored procedure to make it set-based instead of procedural.
For example, you can change your stored procedure to accept a table-valued parameter.
First, create the table type:
CREATE TYPE dbo.StudentClassTableType AS TABLE
( StudentID int, Class varchar(50) )
Next, alter the stored procedure (or create a new stored procedure) to accept the table type:
CREATE PROCEDURE dbo.usp_FailStudents
(#tvpStudentsToFail dbo.StudentClassTableType READONLY)
-- Perform set-based logic using your table parameter.
UPDATE sc
SET Fail = 1
FROM dbo.StudentClass sc
JOIN #tvpStudentsToFail fail
ON fail.StudentID = sc.StudentID
AND fail.Class = sc.Class

Calling a stored procedure within an IF statement MySQL

Does anybody know if this is allowed?
IF CALL GET_RIGHT_NODE(edge) = 15
THEN
SELECT "IT WORKS";
I'm getting an error on this syntax, is it possible any other way?
The return values from stored procedures should be captured in OUT paramters (whereas those from user defined functions can be captured as #returnValue = function()).
So, your GET_RIGHT_NODE should take an OUT parameter and set it to the return value.
CREATE PROCEDURE GET_RIGHT_NODE
(
#edge INT,
#returnValue INT OUTPUT
)
AS
-- Definition of the proc.
then you would call the procedure as follows:
DECLARE #returnValue INT
CALL GET_RIGHT_NODE(#edge, #returnValue)
IF (#returnValue = 15)
THEN
SELECT 'IT WORKS'