MYSQL stored procedure, if statement, ifnull - mysql

I'm trying to create a stored procedure with mysql. The idea is not check if the first request is empty or not, and do it if it's not, or do the second one if the first is empty.
My code, symplified version.
DELIMITER //
CREATE PROCEDURE HFTester(idTest INT)
BEGIN
IF (SELECT * FROM `foo` WHERE id = idTest) != NULL
THEN (SELECT * FROM `foo` WHERE id = idTest;)
ELSE (SELECT * FROM `bar` WHERE id = idTest;)
END IF;
END //
DELIMITER;
The procedure is saved, but when I execute it, i get an empty result.
So I searched the Internet, and I found ifnull .
I then tried to apply it to my case:
DELIMITER //
CREATE PROCEDURE HFTester(idFiche INT)
BEGIN
SELECT IFNULL(
(SELECT * FROM `foo` WHERE id = idTest;),
(SELECT * FROM `bar` WHERE id = idTest;)
);
END //
DELIMITER;
I'm pretty sure the IFNULL can't work, but is there a way to do this if statement in MySQL, or am I force to do it in php?
Victor.

Related

Insert each row of stored procedure into a table

I have two stored procedures in MySql. One of them does the calculation and returns everything in groups. With another stored procedure, I have a WHILE statement that runs for each month and calls the first stored procedure. I want to get the result of each group and save them in a table.
The code is something like:
CREATE PROCEDURE `first`(IN `start` date, **it should be list of items** )
begin
SET result = 0;
SELECT
item.name,
sum(amount) *INTO result*
FROM
FOO
INNER JOIN
BAR ON id = id
WHERE
date(someDate) < date(start)
group by something;
end
And the runner is something like:
CREATE PROCEDURE `runner`(IN `from` date, IN `to` date)
BEGIN
set dateTo = date(to);
set dateFrom = date(from);
WHILE DATE(dateFrom) <= DATE(dateTo) DO
call first(dateFrom, #res);
// here I need another loop through all results of the first procedure to insert each one of them in the following line.
insert into table_x (**some values which have been returned**);
SET dateFrom = DATE_ADD(dateFrom, INTERVAL 1 month);
END WHILE;
END
I don-' think that the loop and the second procedure ist really necessary
MySQL can't return table arrays or something of that kind, but you can use temporary tables
DELIMITER $$
CREATE PROCEDURE `first`(IN `start` date )
begin
DROP TEMPORARY TABLE IF EXISTS myTable;
CREATE TEMPORARY TABLE myTABLE
SELECT
item.name,
sum(amount)
FROM
FOO
INNER JOIN
BAR ON id = id
WHERE
date(someDate) < date(start)
group by something;
end$$
DELIMITER ;
Outer procdudre
DELIMITER $$
CREATE PROCEDURE `runner`(IN `_from` date, IN `_to` date)
BEGIN
set dateTo = date(_to);
set dateFrom = date(_from);
WHILE DATE(dateFrom) <= DATE(dateTo) DO
call first(dateFrom, #res);
insert into table_x (SELECT * FROM myTable);
SET dateFrom = DATE_ADD(dateFrom, INTERVAL 1 month);
END WHILE;
END$$
DELIMITER ;
You ca make dynamic sql work with different variables
DELIMITER $$
CREATE PROCEDURE `first`(IN `_start` date , IN _group varchar(100))
begin
DROP TEMPORARY TABLE IF EXISTS myTable;
SET #sql := CONCAT("
CREATE TEMPORARY TABLE myTABLE
SELECT
item.name,
sum(amount)
FROM
FOO
INNER JOIN
BAR ON id = id
WHERE
date(someDate) < date(",_gRoup,")
group by",_goup,";");
PREPARE stmt FROM #sql;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
end$$
DELIMITER ;
This might work, if all ** some values ** are replaced.
Minimal version of MySQL needed is 8.0 (or an equivalent MariaDB version).
The two variables #from and #to are set to let this script know from which data to which date is needed.
This code is untested, because OP wrote "I have two stored procedures in MySql", but he uses things like "** some values **", which make the two stored procedures invalid (sigh).
Final remark: It is, of course, possible to wrap this complete statement into a stored procedure. (If above corrections are made)
set #from = '2021-05-01';
SET #to = '2021-06-13';
insert into table_x (** some values **)
WITH recursive dates AS (
SELECT #from as d
UNION ALL
SELECT date_add(d, INTERVAL 1 DAY)
FROM dates
WHERE d<#to
)
SELECT d, **some values which have been returned**
FROM dates
CROSS JOIN (
SELECT
item.name,
sum(amount)
FROM
FOO
INNER JOIN
BAR ON id = id
WHERE
date(someDate) < date(d)
group by something) sq

Wrong result while declaring a variable inside Stored procedure

Following is a simple stored procedure to calculate male count from a table , I have declared a variable total_count inside the proc where i'm storing my result.
DELIMITER //
CREATE PROCEDURE GetMaleCount()
BEGIN
DECLARE total_count INT DEFAULT 0 ;
SELECT COUNT(STUDENT_ID) INTO total_count
FROM [table1]
where STUDENT_GENDER = 'M' ;
END //
DELIMITER ;
call GetMaleCount();
select #total_count as tc;
When i executed this procedure i'm getting NULL as the answer, but when i seperately executed just the inner sql query i got the right answer 1852. have i declared the variable in the wrong way ?
total_count that you've declared is visible only in procedure. That is why it is NULL outside of it. You need to use OUT parameter when defining procedure:
DELIMITER //
CREATE PROCEDURE GetMaleCount(OUT total_count INT)
BEGIN
SELECT COUNT(STUDENT_ID) INTO total_count
FROM [table1]
where STUDENT_GENDER = 'M' ;
END //
DELIMITER ;
call GetMaleCount(#total_count);
select #total_count as tc;
You need to use OUT parameter.
DELIMITER //
CREATE PROCEDURE GetMaleCount(OUT total_count INT)
BEGIN
SELECT COUNT(STUDENT_ID) INTO total_count
FROM [table1]
where STUDENT_GENDER = 'M' ;
END //
DELIMITER ;
call GetMaleCount(#total_count);
select #total_count as tc;

MySQL Stored Procedure - IF EXISTS ... THEN returning unexpected result

The below is my Stored Procedure(Routine) to check whether or not a user with Username(input) exists in the database.
Inside the database, I already have a user with Username - 'dev'.
However, when I ran the below routine, it returned me with res = 1, which I expected it to be -1.
I called the routine this way. Please correct me too if I am calling it the wrong way. I am really new to MySQL Routines.
CALL usp_GetUserValidation ('dev', #ErrorCode)
Can any MySQL Routine pros here enlighten me on this? Thank you in advance guys :)
DELIMITER $$
CREATE PROCEDURE usp_GetUserValidation(IN `#Username` VARCHAR(255), OUT `#ErrorCode` INT)
LANGUAGE SQL
NOT DETERMINISTIC
CONTAINS SQL
SQL SECURITY DEFINER
COMMENT 'To validate user login'
BEGIN
IF EXISTS
(SELECT UserID
FROM mt_User
WHERE UserName = #Username)
THEN
SET #ErrorCode = -1;
ELSE
SET #ErrorCode = 1;
END IF;
SELECT #ErrorCode AS res;
END$$
DELIMITER ;
It was simply your naming conventions for the parameters. It is finicky and does not like User Variable # signs in them.
You are just testing I can see, as you are returning both a resultset with the info and the OUT variable.
drop procedure if exists usp_GetUserValidation;
DELIMITER $$
CREATE PROCEDURE usp_GetUserValidation(IN pUsername VARCHAR(255), OUT pErrorCode INT)
LANGUAGE SQL
NOT DETERMINISTIC
CONTAINS SQL
SQL SECURITY DEFINER
COMMENT 'To validate user login'
BEGIN
IF EXISTS
(SELECT UserID
FROM mt_User
WHERE UserName = pUsername)
THEN
SET pErrorCode = -1;
ELSE
SET pErrorCode = 1;
END IF;
SELECT pErrorCode AS res;
END$$
DELIMITER ;
Schema:
-- drop table if exists mt_user;
create table mt_User
( UserID int auto_increment primary key,
UserName varchar(100) not null,
unique key(UserName)
);
insert mt_User(UserName) values ('dev');
select * from mt_User;
Test:
set #var1:=-4;
call usp_GetUserValidation('dev',#var1);
-- returns (-1) ---- Yea, we like that
select #var1;
-- (-1)
set #var1:=-4;
call usp_GetUserValidation('dev222',#var1);
-- returns 1 ---- Yea, we like that
select #var1;
-- 1

mysql stored procedure select and update selected

i am trying to write a stored procedure for mysql, and basicly, it will select one id, and update selected id's operationdate.
DELIMITER //
CREATE PROCEDURE getID(
IN proc_intervaldate datetime
)
BEGIN
DECLARE RUserID BIGINT;
SELECT
UserID
INTO RUserID
FROM Tasks
WHERE OperationDate < proc_intervaldate
LIMIT 1 ;
UPDATE Tasks SET OperationDate = now() WHERE UserID = RUserID;
SELECT RUserID ;
END //
DELIMITER ;
but when i use this, procedure, it will return UserID but not update, if i comment
SELECT RUserID
then, it updates, but no data returns.
when I use this, procedure, it will return UserID but not update, if I comment 'SELECT RUserID;' then, it updates, but no data returns.
You can change definition of stored procedure to use an OUT parameter rather than just IN. With that, you can just capture the OUT value on the same OUT parameter, in your scripting language. Meaning you need not execute:
SELECT RUserID ;
in your stored procedure.
Change your SP definition as below:
DELIMITER //
CREATE PROCEDURE getID( IN proc_intervaldate datetime, OUT RUserID bigint )
BEGIN
SELECT
UserID INTO RUserID
FROM Tasks
WHERE
OperationDate < proc_intervaldate
LIMIT 1 ;
UPDATE Tasks SET OperationDate = now() WHERE UserID = RUserID;
END;
//
DELIMITER ;
You can call this stored procedure like, for example, at MySQL console:
SET #RUserID := 0;
CALL getID( now(), #RUserID );
SELECT #RUserID;
Refer to:
MySQL: CALL procedure syntax
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.

Why won't simple If ELSE Statement work in mySql

I'm trying to create a simple stored procedure with an if else statement in SQLYog against a mySql db. I'm not overly familiar with mySql syntax so i'm hoping it's something simple but I just can't see why this isn't working
CREATE PROCEDURE p(IN Number INT)
IF NUMBER = 1 THEN
SELECT * FROM tblProduct WHERE ProductID = Number
ELSE SELECT * FROM tblProduct WHERE ProductId = 2
END IF
I'd appreciate if anyone can help me with this and tell me where i'm going wrong.
Thanks for reading.
I get the following when I try to execute:
Error Code : 1064
You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'ELSE SELECT * FROM tblProduct where intProductId = 2
END IF' at line 5
Statements in MySQL are delimited by semicolons. To create procedures with them, you do a little trick like so:
DELIMITER //
CREATE PROCEDURE p(IN Number INT)
BEGIN
IF NUMBER = 1 THEN
SELECT * FROM tblProduct WHERE ProductID = Number;
ELSE
SELECT * FROM tblProduct WHERE ProductId = 2;
END IF;
END //
DELIMITER ;
Check out the documentation for if/else for more info.
Remember the IF ELSE statement is always used in stored procedure, triggers not in simple select query. And ELSE OR IF keyword always write in new line not in front of query.Like below
Correct syntax:
DELIMITER //
CREATE PROCEDURE NAME(IN Number INT)
BEGIN
IF roll= 1 THEN
SELECT * FROM table1 WHERE id = roll;
ELSE
SELECT * FROM table2 WHERE id = 2;
END IF;
END //
DELIMITER ;
Wrong syntax:
DELIMITER //
CREATE PROCEDURE NAME(IN Number INT)
BEGIN
IF roll= 1 THEN SELECT * FROM table1 WHERE id = roll;
ELSE SELECT * FROM table2 WHERE id = 2;
END IF;
END //
DELIMITER ;
You need a ; after your select statements. You also need BEGIN and END around your procedure body. See the manual for lots of examples about the exact syntax for procedures.