I'm fuzzy on when I need you use # to reference vars in mySQL. I'm coming from MS SQL where you always use it, but apparently that's not correct in mySQL.
So the below stored procedure is always executing the first IF block, even if the session value is expired - in that it's always executing the update statement. Apparently the only debug tool I could find for mySQL stored procs runs on Windows and Linux. I'm on a Mac. Wamp wamp wamp.
So yeah. Can anyone see what's wrong here? Thanks!
DELIMITER $$
CREATE DEFINER=`xxx`#`localhost` PROCEDURE `validate_session`(uid INT, token VARCHAR(256))
BEGIN
DECLARE sessId INT DEFAULT NULL;
SELECT sessId = id FROM UserSessions
WHERE userId = uid
AND sessionToken = token
AND expires > INTERVAL 2 MINUTE + NOW() ORDER BY expires DESC LIMIT 1;
IF sessId IS NOT NULL THEN
UPDATE UserSessions
SET expires = INTERVAL 2 HOUR + NOW()
WHERE id = sessId;
ELSE
DELETE FROM UserSessions
WHERE userId = uid
AND sessionToken = token;
SET #sessId = 0;
END IF;
SELECT sessId;
END
For the record what it's supposed to do in pseudo code:
if we have a session for this user, with a matching token which has not expired {
update the expiration time to 2 hours from now
return the session id;
}
else {
delete the (now stale) session
return 0;
}
Thanks in advance.
You're not setting the value of sessId... you're making a comparisson in your query.
I think what you need is something like this:
CREATE DEFINER=`xxx`#`localhost` PROCEDURE `validate_session`(uid INT, token VARCHAR(256))
BEGIN
DECLARE sessId INT DEFAULT NULL;
SELECT id
INTO sessId -- Here is the assignment
FROM UserSessions
WHERE userId = uid
AND sessionToken = token
AND expires > INTERVAL 2 MINUTE + NOW()
ORDER BY expires DESC
LIMIT 1;
IF sessId IS NOT NULL THEN
UPDATE UserSessions
SET expires = INTERVAL 2 HOUR + NOW()
WHERE id = sessId;
ELSE
DELETE FROM UserSessions
WHERE userId = uid
AND sessionToken = token;
SET sessId = 0;
END IF;
SELECT sessId;
END
Reference:
MySQL Reference: SELECT ... INTO syntax
MySQL Reference: Local variable scope and resolution
Related
I need to check that VIP exist in DB and his time not expired. Everything would be fine if not this problem: how to create Boolean function that will store this functionality?
CREATE DEFINER=`root`#`localhost` FUNCTION `IsVip`(steamId VARCHAR(17)) RETURNS tinyint(1)
BEGIN
RETURN EXISTS (SELECT SteamId, Expired FROM Vips WHERE SteamId=steamId AND Expired >= NOW());
END
This is my solution, but is this coed efficient well - I mean SELECT statement?
CREATE DEFINER=`root`#`localhost` FUNCTION `IsVip`(steamId VARCHAR(17)) RETURNS tinyint(1)
BEGIN
IF (SELECT VipId FROM Vips WHERE SteamId = steamId AND Expired >= NOW())
THEN
RETURN TRUE;
ELSE
RETURN FALSE;
END IF;
END
Assuming that there is only one line per SteamID in the Vips table, I would just do :
SELECT 1 FROM Vips WHERE SteamId = ? AND Expired >= NOW();
This will return a single row with a value of 1 when the user is valid (ie exists and is not expired), and an empty recordset if it does not.
Another option :
SELECT COUNT(*) FROM Vips WHERE SteamId = ? AND Expired >= NOW()
Will always return a resultset, with a single record containing either 1 if the user is valid, or 0 if not.
Good day, I have a problem regarding MySQL queries. I want to create a daily time record output but my problem is on making queries. What I want is that when a record have the same id and date it must be updated otherwise it will insert a new record. These are some of screenshots of table properties
CREATE PROCEDURE dbo.EditGrade
#Id int
,#TimeIn datetime
,#TimeOut datetime
,#Existing bit OUTPUT
AS
BEGIN
SET NOCOUNT ON;
DECLARE #CurrentTimeIn as datetime
DECLARE #CurrentId as int
SELECT #CurrentId = Id
FROM tblAttendance
WHERE TimeIn = #TimeIn
IF (#CurrentId <> #Id)
BEGIN
IF (SELECT COUNT(ISNULL(Id,0))
FROM tblAttendance
WHERE TimeIn = #TimeIn
SET #Existing = 0
ELSE
SET #Existing = 1
END
ELSE
BEGIN
SET #Existing = 0
END
IF #Name = ''
SET #Name = null
IF (#Existing = 0)
UPDATE tblAttendance
SET TimeIn = #TimeIn
--other column values here
WHERE Id = #Id
ELSE
--INSERT FROM tblAttendance query here
END
GO
this is from stored procedure of ms sql, you can just convert it into mysql version.
take note, datetime types also checks the seconds, so don't include the seconds as much as possible or it will render as NOT THE SAME (e.g time in = 10:00:01 and time out is 10:00:02 will be rendered as NOT THE SAME)
I used a stored procedure that uses a cursor to loop through and process an attendance data table on Mariadb 10.1 database after calling the procedure the first time all the tables on the database lost the ability to perform INSERT INTO or UPDATE statements unless the targeted table is truncated first, can any one tell me what went wrong and how to fix it
the procedure that caused the problem:
DELIMITER $$
CREATE DEFINER=`root`#`localhost` PROCEDURE `settle_attendance`()
MODIFIES SQL DATA
BEGIN
DECLARE trans_done BOOLEAN DEFAULT FALSE;
DECLARE punchid BIGINT(20);
DECLARE timein DATETIME;
DECLARE utctimein DATETIME;
DECLARE timeout DATETIME;
DECLARE utctimeout DATETIME;
DECLARE inday DATE;
DECLARE outday DATE;
DECLARE todaysdate DATE;
DECLARE attendcur CURSOR FOR
SELECT id, punch_in_utc_time, punch_in_user_time,
punch_out_utc_time, punch_out_user_time
FROM ohrm_attendance_record
ORDER BY id ASC;
DECLARE CONTINUE HANDLER FOR NOT FOUND SET trans_done = TRUE;
OPEN attendcur;
edit_loop: LOOP
SET todaysdate = CURRENT_DATE();
FETCH attendcur INTO punchid, utctimein, timein, utctimeout, timeout;
IF trans_done THEN
CLOSE attendcur;
LEAVE edit_loop;
END IF;
SET inday = DATE(timein);
SET outday = DATE(timeout);
SET todaysdate = CURRENT_DATE();
IF (inday < todaysdate) OR (outday < todaysdate) THEN
CASE
WHEN (timein IS NULL OR timein = '')
OR (utctimein IS NULL OR utctimein = '') THEN
UPDATE ohrm_attendance_record
SET punch_in_utc_time = utctimeout,
punch_in_user_time = timeout,
state = 'PUNCHED OUT'
WHERE punchid = id;
ELSE BEGIN END;
END CASE;
CASE
WHEN (timeout IS NULL OR timeout = '')
OR (utctimeout IS NULL OR utctimeout = '') THEN
UPDATE ohrm_attendance_record
SET punch_out_utc_time = utctimein,
punch_out_user_time = timein,
state = 'PUNCHED OUT'
WHERE punchid = id;
ELSE BEGIN END;
END CASE;
END IF;
END LOOP edit_loop;
END $$
DELIMITER ;
I choose to avoid the question you asked. Instead, let's try to do the query 10 times as fast by getting rid of the pesky CURSOR. The entire Stored Procedure can be done in 2 UPDATEs, no loop:
UPDATE ohrm_attendance_record
SET punch_in_utc_time = utctimeout,
punch_in_user_time = timeout,
state = 'PUNCHED OUT'
WHERE ( timein < CURDATE() OR timeout < CURDATE() )
AND ( ( timein IS NULL OR timein = '' )
OR ( utctimein IS NULL OR utctimein = '' )
);
UPDATE ohrm_attendance_record
SET punch_out_utc_time = utctimein,
punch_out_user_time = timein,
state = 'PUNCHED OUT'
WHERE ( timein < CURDATE() OR timeout < CURDATE() )
AND ( ( timeout IS NULL OR timeout = '' )
OR ( utctimeout IS NULL OR utctimeout = '' )
);
I am, however, suspicious of your tests against timein and timeout.
The queries would be easier to read if you settled on either NULL or '' for missing times.
If you store only UTC values in a TIMESTAMP, you can let the user's timezone take care of coverting to local time -- this would eliminate quite a few columns and simplify the UPDATEs.
I'll make a stab at the question... Do SHOW CREATE PROCEDURE settle_attendance;, you may find that the CHARACTER SET or COLLATION is inconsistent with what you think it should be.
I have a problem on MySQL stored procedure, already did another logic with IF THEN ELSE, but I still have problems which I cant understand...
The procedure consists on two user inputs: user_id and meet_id. The procedure define a variable called 'ue' which stores result of a bunch of validation (if user exists, if event exists, if event date is still valid, etc.).
After that, it does INSERT and UPDATE some data on multiple tables in IF THEN ELSE selector, and SELECT 1 (or 0) AS result depending of validation.
But my problem is: it always return me 0 as 'result', as if my validation variable was 0 when I do INSERT... And there is where things get weird, if I remove the INSERT [...]; line of the code, it returns me the value of validation correctly (1 or 0).
The code of the procedure is this one:
CREATE DEFINER=`nwouserf`#`localhost`
PROCEDURE `join_event`(IN `user_id` BIGINT(64), IN `event_id` INT)
NOT DETERMINISTIC MODIFIES SQL DATA SQL SECURITY DEFINER
begin
DECLARE ue INT;
SET ue = EXISTS(SELECT 1 FROM users WHERE fb_uid=user_id)
AND EXISTS(SELECT 1 FROM meetup WHERE meet_id=event_id)
AND EXISTS(SELECT 1 FROM meetup WHERE date > NOW() AND meet_id = event_id)
AND EXISTS(SELECT 1 FROM meetup WHERE meet_id = event_id AND participants <= max_participants)
AND NOT EXISTS(SELECT 1 FROM meetup_participation WHERE fb_uid = user_id AND meet_id = event_id);
IF ue = 1 THEN
INSERT INTO meetup_participation (fb_uid, meet_id) VALUES (user_id, event_id);
UPDATE users SET events_participated = events_participated + 1 WHERE fb_uid=user_id;
UPDATE meetup SET participants = participants + 1 WHERE meet_id=event_id;
SELECT 1 AS result;
ELSEIF ue = 0 THEN
SELECT 0 AS result;
ELSE
SELECT null AS result;
END IF;
end
Thanks in advance!
I have been stuck on this for a while now, and can not figure out why.
You should define OUT parameter. Add
", OUT result INT"
immediately after the last IN parameter.
Having a few issues with running the below procedure over PHPMyAdmin, receiving the error;
"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 '' at line 6"
The problem seems to be with the IF, the update syntax works on its own, the select within the if statement works on its own.
Any ideas??
CREATE PROCEDURE Get_SessionCookie(
sessionID varchar(50),
cookieID varchar(50)
)
IF (SELECT 1 = 1 FROM `SessionCookie` WHERE SessionID = sessionID AND CookieID = cookieID AND SessionExpiry < NOW())
UPDATE SessionCookie
SET SessionExpiry = NOW() + INTERVAL 60 MINUTE
WHERE SessionID = sessionID AND CookieID = cookieID;
SELECT 'True' FROM SessionCookie;
ELSE
SELECT 'False' FROM SessionCookie;
One major problem is that parameters to the stored procedure have the same names as columns. You should always prefix variable names with something. Your specific problem, I think, is that you want an exists in the if and a delimeter statement. I think this is closer to what you want:
delimiter $$
CREATE PROCEDURE Get_SessionCookie (
var_sessionID varchar(50),
var_cookieID varchar(50)
)
BEGIN
IF exists (SELECT 1
FROM `SessionCookie`
WHERE SessionID = var_sessionID AND
CookieID = var_cookieID AND
SessionExpiry < NOW()
)
UPDATE SessionCookie
SET SessionExpiry = NOW() + INTERVAL 60 MINUTE
WHERE SessionID = var_sessionID AND CookieID = var_cookieID;
SELECT 'True' FROM SessionCookie;
ELSE SELECT 'False' FROM SessionCookie;
END IF
END$$