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!
Related
SOLVED
I have this block of codes which will insert data to all unique email_address available on emp_leave_balance table. The problem is it doesn't work even though it didnt catch error. I tried this code in cmd and it works perfectly. I'm not sure if codeigniter accept this kind of query or not.
MODEL
public function insert_credit_points_data($email){
try{
$sql = "DELIMITER $$
CREATE EVENT ecp
ON SCHEDULE EVERY 1 MINUTE STARTS NOW() DO
BEGIN
INSERT INTO emp_leave_balance (balance, date_from, date_to, leave_type, earned, date_filed, action_taken,email_address)
SELECT (1.25+balance), NOW(), DATE_ADD(NOW(),INTERVAL 1 MINUTE), 'Vacation', 1.25, NOW(), 'CREDITED',".$email." FROM emp_leave_balance where email_address = ".$email." ORDER BY balance DESC LIMIT 1;
END$$
DELIMITER ;";
$this->db->query($sql);
}catch(Exception $e){
throw $e;
}
}
SQL ERROR
NEW PROBLEM
I'm trying to loop the insert query based on the number of distinct email address available in my table. The problem is my loop doesn't work.
$sql = "CREATE EVENT ecp ON SCHEDULE EVERY 1 MINUTE STARTS NOW() DO
BEGIN
DECLARE x INT DEFAULT 0;
DECLARE counter INT DEFAULT (SELECT COUNT(DISTINCT(email_address)) FROM emp_leave_balance);
simple_loop: LOOP
INSERT INTO emp_leave_balance (balance, date_from, date_to, leave_type, earned, date_filed, action_taken,email_address)
SELECT (1.25+balance), NOW(), DATE_ADD(NOW(),INTERVAL 1 MINUTE), 'Vacation', 1.25, NOW(), 'CREDITED','".$email."' FROM emp_leave_balance where email_address = '".$email."' ORDER BY balance DESC LIMIT 1;
SET x = x + 1;
IF x<counter THEN
LEAVE simple_loop;
END IF;
END LOOP simple_loop;
END";
Very few (if any) functions in CI throw exceptions, if they do it is usually due to a native php function. In your case query() will return boolean depending on whether or not it succeeded so the try catch block is superfluous.
With that being said, all the query() function does is execute a query so I don't see if having a problem handling anything phpmyadmin can't. I would suggest going into the database.php file and changing db_debug to true. This should help you find the exact cause of the error.
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;
I have a medium sized stored procedure going on here below. My problem is that it doesn't do anything and I have no idea why.
1.) First of all, the code:
DROP PROCEDURE IF EXISTS deleteabundant_fixshared_shiftResources;
DELIMITER //
CREATE PROCEDURE deleteabundant_fixshared_shiftResources ()
BEGIN
DECLARE finish_flag BOOLEAN DEFAULT FALSE;
DECLARE id INT(11);
DECLARE startTime DATETIME;
DECLARE endTime DATETIME;
DECLARE shid INT(11);
DECLARE resid INT(11);
DECLARE id_inner INT(11);
DECLARE startTime_inner DATETIME;
DECLARE endTime_inner DATETIME;
DECLARE shid_inner INT(11);
DECLARE resid_inner INT(11);
DECLARE cr130 CURSOR FOR SELECT shift_resource_id, start_date, end_date, shift_id, resource_id FROM temp_shift_resource;
DECLARE cr131 CURSOR FOR SELECT shift_resource_id, start_date, end_date, shift_id, resource_id FROM temp_shift_resource;
DECLARE CONTINUE HANDLER FOR NOT FOUND SET finish_flag = TRUE;
START TRANSACTION;
OPEN cr130;
OPEN cr131;
OUTERLOOP: LOOP
FETCH cr130 into id, startTime, endTime, shid, resid;
IF finish_flag THEN LEAVE OUTERLOOP; END IF;
INNERLOOP: LOOP
FETCH cr131 INTO id_inner, startTime_inner, endTime_inner, shid_inner, resid_inner;
IF finish_flag THEN LEAVE INNERLOOP; END IF;
IF (id!=id_inner) THEN
IF (resid=resid_inner AND shid_inner!=9) THEN
-- logic to determine if the dates are wrong:
IF (startTime<=startTime_inner AND endTime>=endTime_inner) THEN
INSERT INTO repairchange ( shift_resource_id, changetype, shift_id, resource_id, start_date, end_date )
VALUES ( id_inner, "FD", shid_inner, resid_inner, startTime_inner, endTime_inner );
DELETE FROM temp_shift_resource WHERE shift_resource_id = id_inner;
ELSEIF (endTime>=endTime_inner AND startTime<=endTime_inner) THEN
INSERT INTO repairchange ( shift_resource_id, changetype, shift_id, resource_id, start_date, end_date )
VALUES ( id_inner, "FU", shid_inner, resid_inner, startTime_inner, endTime_inner );
UPDATE temp_shift_resource set endTime_inner=(startTime - INTERVAL 1 DAY) where shift_resource_id = id_inner;
ELSEIF (startTime<=startTime_inner AND endTime>=startTime_inner) THEN
INSERT INTO repairchange ( shift_resource_id, changetype, shift_id, resource_id, start_date, end_date )
VALUES ( id_inner, "FU", shid_inner, resid_inner, startTime_inner, endTime_inner );
UPDATE temp_shift_resource set startTime_inner=(endTime + INTERVAL 1 DAY) where shift_resource_id = id_inner;
END IF;
END IF;
END IF;
END LOOP INNERLOOP;
SET finish_flag = FALSE;
END LOOP OUTERLOOP;
CLOSE cr130;
CLOSE cr131;
COMMIT;
END //
DELIMITER ;
call deleteabundant_fixshared_shiftResources();
2.) Description of what I want to do:
Basically, I have a table full of workshifts. Due to code bugs, some of these shifts have a wrong date assigned to them, and I have to fix the database.
I have to run through the whole table, and compare the rows that are assigned to the same resource_id, which represents a person. So if a person has two shifts that look like (2016-05-10 to 2016-05-20) and (2016-05-15 to 2016-05-23) for example, I have to fix it so that one of them will be trimmed to (2016-05-10 to 2016-05-14) and (2016-05-15 to 2016-05-23).
A shift that is a nightshift, marked as shift_id=9, must not be modified at all.
I insert rows into the repairchange table if a change or a deletion has been made
3.) The procedure runs, but does nothing. I have examples in the database for wrong rows, one example is the one I wrote above. I suspect it is the nested loop, because I want to loop and fetch through the same table, but I haven't found anything on that.
I got the message
0 row(s) affected, 1 warning(s): 1329 No data - zero rows fetched, selected, or processed
but I have seen this before and my stored procedures have worked even though they output this warning.
Any ideas or tips are welcome. Thank you for your time!
I figured it out, after quite some debugging:
I opened the cursors before both of the loops. This meant that after the first walk-through of the inner loop, the cursor was standing at +1 of the LAST row of the table, and when the new outer loop iteration started the second inner loop iteration, the cursor was still at the end position.
Thus it did not run. I replaced the inner-cursor opening and closing into the outer loop, and now it works properly.
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
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.