Whats wrong with this short procedure (MySQL) - mysql

Im trying to make a procedure, which will be checking if user is already logged (he got a session, and im checking if his last action was over 15 minutes ago). My procedure looks like this:
CREATE PROCEDURE `isLogged`(in p_sessid VARCHAR(32), out res INT(1))
BEGIN
DECLARE v_customer_id INT(9);
DECLARE v_date DATE;
SELECT customer_id INTO v_customer_id FROM Sessions WHERE sessid=p_sessid;
SELECT expiry_date INTO v_date FROM Sessions WHERE sessid=p_sessid;
SET res=3;
IF v_customer_id > 0 THEN
IF UNIX_TIMESTAMP(NOW()) > UNIX_TIMESTAMP(v_date) THEN
DELETE FROM Sessions WHERE sessid=p_sessid;
SET res=1;
ELSE
UPDATE Sessions SET expiry_date=DATE_ADD(NOW(), INTERVAL 15 MINUTE) WHERE customer_id=v_customer_id;
SET res=0;
END IF;
END IF;
END
Can anyone tell, why it always return 1, what means that user is not logged anymore? I were checking manually expression UNIX_TIMESTAMP(NOW()) > UNIX_TIMESTAMP(v_date), and it gives me 0 in response, so? Whats going on?
Thanks in advance,
Marcin

The first IF statement should read like this:
UNIX_TIMESTAMP(NOW()) > UNIX_TIMESTAMP(DATE_ADD(v_date, INTERVAL 15 MINUTE))
or else NOW will always be greater than the last login date.

You may rewrite/optimize your procedure to function. For example -
CREATE FUNCTION `isLogged`(IN p_sessid VARCHAR(32))
RETURNS INT
BEGIN
DELETE FROM Sessions WHERE sessid = p_sessid AND v_date <= NOW() - INTERVAL 15 MINUTE;
IF ROW_COUNT() > 0 THEN -- check how many rows were deleted
RETURN 1;
ELSE
UPDATE Sessions SET expiry_date = NOW() + INTERVAL 15 MINUTE WHERE customer_id = v_customer_id;
IF ROW_COUNT() > 0 THEN -- check how many rows were updated
RETURN 0;
END IF;
END IF;
RETURN 3;
END
Also, you can try to debug your code to understand the error.

Omg, that was very stupid.
There was a type mismatch. v_date type was a DATE, and this is just a day! Like 2011-12-14.
Solution:
change DATE -> DATETIME.
And now everything works good.
Anyway, thank you for answers.

Related

Create a loop based on date Mysql

I have a query :
insert into fookoo_business
select stat_date, sum(spend), sum(revenue)
from hooloo_business;
that i want to run for each date from '2017-01-20' until yesterday (it means the query will run 434 times if we're at 01/04/2018), for each date separately
(in a loop).
how can i create a loop in Mysql to do it for me?
I have tried:
creating procedure for the query select #stat_date, sum(spend), sum(revenue)
I called 'query'
then :
CREATE PROCEDURE loop_procedure()
BEGIN
SET #stat_date='2018-03-20';
CALL 'query';
REPEAT
SET #stat_date = #stat_date + INTERVAL 1 DAY;
UNTIL #stat_date = CURDATE() END REPEAT;
END
eventually i've used the following logic within a stored procedure to fetch the data:
PROCEDURE `x_monitoring_loop`()
BEGIN
DECLARE i INT;
DECLARE len INT;
SET len = 434;
SET i = 0;
WHILE (i < len) DO
SET #stat_date= CURDATE()-INTERVAL 1 DAY;
SET #stat_date= #stat_date- INTERVAL i DAY;
Insert query;
SET i = i +1;
END WHILE;
This way the query ran 434 times for each day, beginning at current date - 1 day.
I do not know why you want to use a procedure,I think we can just use a query sql to do it:
INSERT INTO fookoo_business
SELECT stat_date, SUM(spend), SUM(revenue)
FROM hooloo_business
WHERE stat_date BETWEEN STR_TO_DATE('2017-01-02', '%Y-%m-%d') -- start date
AND DATE_SUB(NOW(), INTERVAL 1 DAY) -- end date
GROUP BY stat_date;

MySQL fails to add days to a date when month is over

I am trying to get a final date when a number of days (pplazo input) has elapsed, starting on a date (pfecha input), and avoiding to count certain dates (feriado) that are listed on a table.
So far this is what i got to, using a Stored Procedure:
Input parameters:
pfecha -- DATE
pplazo -- INT (11)
PROC:BEGIN
DECLARE i INT(1);
START TRANSACTION;
SET i=1;
lazo:LOOP
IF NOT EXISTS (SELECT * FROM feriados WHERE feriado=pfecha+i)
THEN
SET pfecha=pfecha+1;
SET i=i+1;
END IF;
IF i=pplazo
THEN
LEAVE lazo;
END IF;
END LOOP lazo;
COMMIT;
SELECT pfecha as respuesta;
END
The thing is, when the days to count make the date go pass the end of the month, then the "respuesta" turns to 0000-00-00.
This shouldn't be happening, if I input 15 days starting on the 2016-04-20 then the resulting date should be something like 2016-05-5.
Can you spot my mistake? Could you point me in the right direction?
The correct way to add a number of days to a date is with the DATE_ADD or ADDATE functions, not the + operator. See
lazo:LOOP
IF NOT EXISTS (SELECT * FROM feriados WHERE feriado=DATE_ADD(pfecha, INTERVAL i DAY))
THEN
SET pfecha=DATE_ADD(pfecha, INTERVAL 1 DAY);
SET i=i+1;
END IF;
IF i=pplazo
THEN
LEAVE lazo;
END IF;
END LOOP lazo;

Mysql trigger no error message but code not working

I wrote this trigger in phpMyAdmin
BEGIN
DECLARE start DATETIME;
DECLARE now DATETIME;
DECLARE date DATETIME;
SELECT `starting` INTO start FROM events WHERE events.id = NEW.event_id;
SET now = NOW();
SET date = CURDATE();
IF start > now THEN
IF DATE(start) = date THEN
SET #hours = HOUR(start - now);
IF #hours <= 1 THEN
SET #text = 'in less than an hour';
ELSE
SET #text = CONCAT('in about ', #hours, ' hours');
END IF;
INSERT INTO notifications (user_id, subject, action_id, data, seen, activates)
VALUES (NEW.user_id, NEW.event_id, 2, CONCAT('{"period":"', #text, '"}'), 0, now);
ELSE
INSERT INTO notifications (user_id, subject, action_id, data, seen, activates)
VALUES
(NEW.user_id, NEW.event_id, 2, '{"period":"tomorrow"}', 0, DATE(start - INTERVAL 1 DAY)),
(NEW.user_id, NEW.event_id, 2, '{"period":"in one hour"}', 0, start - INTERVAL 1 HOUR);
END IF;
END IF;
END
The purpose of it is to create notifications about a starting event when a user submits that he is going to be attending an event. The trigger works if the event is not today, but if the event is today I get this message
Column data cannot be NULL
Column data is in table notifications. If the event is set to start today I get column data cannot be NULL, if the event is further in future, like tomorrow I get accurate message.
Any help is greatly appreciated!
There was something wrong with this bit of code
HOUR(start - now)
I replaced it with
HOUR(TIMEDIFF(start - now))
Now everything works as expected.
I got to solve the problem with Marc B's help for which I thank him and everyone else who commented!

Compare time values correctly

I am having trouble comparing MySQL Time fields, I have a NOEVENTS row starting from 09:00 to 10:00 and I am trying to insert a row into another table, but I need to compare the NOEVENTS time, to the incoming Time fields. example:
I want to insert a event from 09:15 to 09:30, and another from 10:00 to 11:00, so how can I compare that? im trying this:
select count(idNOEVENTS) into existNOEVENT from NOEVENTS b where eventInitialTime && eventFinalTime between b.initialTime and b.finalTime;
if existNOEVENT>0
SET MESSAGE_TEXT = 'Error! no events allowed at this time';
The problem is when I try to insert the 09:15 to 09:30, it throws the error message shown above. Thats fine, it works, but when I try to insert the 10:00 to 11:00 event it throw the msg, and it shouldnt, how can I fix it? or compare it better?
Thanks, and sorry for my poor english.
You can do it this way
SELECT *
FROM noevents
WHERE (? > initialTime AND ? < finalTime)
OR (? > initialTime AND ? < finalTime)
Now don't use COUNT(*) to check for existence of a row(s). Use EXIST() instead.
That being said to give an idea this how you procedure code might look like
DELIMITER $$
CREATE PROCEDURE add_event(IN _start TIME, IN _end TIME)
BEGIN
IF EXISTS(SELECT *
FROM noevents
WHERE (_start > initialTime AND _start < finalTime)
OR (_end > initialTime AND _end < finalTime)) THEN
SIGNAL sqlstate '45000'
SET message_text = 'Error! no events allowed at this time';
ELSE
-- Do whatever you have to do to insert an event
SELECT 'Success: event added';
END IF;
END$$
DELIMITER ;
Here is SQLFiddle demo

Scope of mysql while loop

I'm having some trouble with scope using mysql while loops.
DECLARE vdate DATETIME DEFAULT now();
DECLARE vday int default 0;
WHILE (vday < 7) DO
WHILE (vdate < DATE_ADD(NOW(),INTERVAL 1 DAY)) DO
//Here vday is always 0
END WHILE;
//Here vday is 0 -6
SELECT vday +1 INTO vday;
END WHILE;
Can anyone clarify for me what the scope of a while loop is in mysql? How to I create a variable i can use inside a nested loop?
Turns out I missed something obvious (late friday problem :) ). I wasn't setting vdate back to now() after each loop of vday. As a result it would only get into the sub loop when vday was 0.