The goal here is to make it busy for 'n' seconds and then exit.
This is latest version of code. I tried direct date1 < date2 in while, etc
delimiter $$
CREATE FUNCTION `DelayResponse`(pSeconds int) RETURNS varchar(1)
BEGIN
DECLARE x int;
DECLARE EndDateTime datetime ;
DECLARE CurrDateTime datetime ;
Set x = 0;
set EndDateTime = DATE_ADD(now(), INTERVAL pSeconds second);
set CurrDateTime = now();
WHILE x = 0 DO
-- expecting to set x to 1 in pSeconds but nope
if CurrDateTime > EndDateTime then
set x = 1;
end if;
SET CurrDateTime = now();
END WHILE;
RETURN 'X';
END$$
delimiter ;
select DelayResponse(5) X
I can't get out the loop here. What am I missing?
Another version that does not work. Just spins running... not ending
delimiter $$
CREATE FUNCTION `DelayResponse`(pSeconds int) RETURNS varchar(1)
BEGIN
DECLARE x int;
DECLARE EndDateTime datetime ;
Set x = 0;
set EndDateTime = DATE_ADD(now(), INTERVAL pSeconds second);
WHILE x <= 0 DO
set x = now() - EndDateTime;
END WHILE;
RETURN 'X';
END$$
delimiter ;
This behaviour is a result of a documented, but less-known feature of now(). So, this is not a bug!
NOW() returns a constant time that indicates the time at which the statement began to execute. (Within a stored function or trigger, NOW() returns the time at which the function or triggering statement began to execute.) This differs from the behavior for SYSDATE(), which returns the exact time at which it executes.
So, while #Barmar is correct in suggesting the use of sleep(), you can make your original code work with sysdate() instead of now().
You can use the built-in SLEEP() function instead of your own loop.
delimiter $$
CREATE FUNCTION `DelayResponse`(pSeconds int) RETURNS varchar(1)
BEGIN
DO SLEEP(pSeconds);
RETURN 'X';
END$$
delimiter ;
select DelayResponse(5) X
Related
I need this procedure to generate 10M random timestamps but it has to use the current date each time it is called, how do i do this? I know that there's a CURRENT_TIMESTAMP() function, but I'm not sure how to implement it.
DELIMITER $$
CREATE PROCEDURE producer()
BEGIN
DECLARE a INT DEFAULT 0;
WHILE a < 10000000 DO
INSERT INTO CaseLog (`TIMESTAMP_IN`)
VALUES (FROM_UNIXTIME(UNIX_TIMESTAMP('2021-09-22 00:00:00')+FLOOR(RAND()*86399))
);
SET a = a+1;
END WHILE;
END$$
DELIMITER ;
Use CURRENT_DATE() to get today's date, and use that instead of the hard-coded date.
DELIMITER $$
CREATE PROCEDURE producer()
BEGIN
DECLARE today_timestamp INT;
SET today_timestamp = UNIX_TIMESTAMP(CURRENT_DATE());
DECLARE a INT DEFAULT 0;
WHILE a < 10000000 DO
INSERT INTO CaseLog (`TIMESTAMP_IN`)
VALUES (FROM_UNIXTIME(today_timestamp+FLOOR(RAND()*86400)));
SET a = a+1;
END WHILE;
END$$
DELIMITER ;
Also, you should multiply RAND() by 86400, not 86399. The result of RAND() is always less than 1.0, so you don't have to worry that it will return 86400.
I have a table called USER. This table has 2 columns as end_date, access_date. access_date is empty right now but i want to populate it like:
if end_date exists : access_date = end_date + 1 year (anway i can make that operation) but my problem i could not construct the cursor i have not use cursor logic before.
i need something like:
DELIMITER $$
CREATE PROCEDURE user_procedure ()
BEGIN
DECLARE v_finished INTEGER DEFAULT 0;
DECLARE v_user varchar(100) DEFAULT "";
-- declare cursor for user
DEClARE user_cursor CURSOR FOR
SELECT * FROM USER;
-- declare NOT FOUND handler
DECLARE CONTINUE HANDLER
FOR NOT FOUND SET v_finished = 1;
OPEN user_cursor;
get_user: LOOP
FETCH user_cursor INTO v_user;
IF v_finished = 1 THEN
LEAVE get_user;
END IF;
-- operation
-- something like:
set #end_date = select from cursor
update expiry... etcs
END LOOP get_user;
CLOSE user_cursor;
END$$
DELIMITER ;
CALL user_procedure();
but the problem i do not know how to define the cursor because as you see in example:
DECLARE v_user varchar(100) DEFAULT "";
i am pretty sure it is wrong and i try to fetch it into
FETCH user_cursor INTO v_user;
So how can i properly define the cursor and fetch as a whole row and make change ?
Edit: some people did not understand and claimed i have asked same question again, ok i will edit the real code, now as below according to people's comment. This update must be applied to each individual row.
set #key = 'bla bla';
delimiter $$
create procedure select_or_insert()
begin
IF EXISTS (select USER_EXPIRY_DATE from USER) THEN
update USER set ACCESS_EXPIRY_DATE = DATE_ADD(USER_EXPIRY_DATE, INTERVAL 1 YEAR);
ELSE IF EXISTS (select USER_START_DATE from USER) THEN
SET #start_date = (select USER_START_DATE from USER);
SET #start_date_to_be_added = aes_decrypt(#start_date,#key)
update USER set ACCESS_EXPIRY_DATE = DATE_ADD(USER_EXPIRY_DATE, INTERVAL 1 YEAR);
END IF;
end $$
delimiter ;
but in here for example:
ELSE IF EXISTS (select USER_START_DATE from USER)
is returning more than 1 row.
You don't need a cursor for that, you can simply use an update statement:
UPDATE User
SET access_date = DATE_ADD(end_date, INTERVAL 1 YEAR)
WHERE end_date IS NOT NULL
DELIMITER $$
CREATE FUNCTION current_age (birthdate date)
RETURNS date
BEGIN
DECLARE age_return date;
DECLARE rightnow date;
SET rightnow = date(now());
SET age_return = timestampdiff(year, rightnow, date(birthdate));
RETURN age_return;
END $$
DELIMITER ;
select current_age(date('2017-06-30'));
I am trying to create a function which years the difference in years. I cant get it to work and I dont understand why, because the following works fine outside the function.
SET #birthdate = '2001-01-01';
SET #rightnow = date(now());
SELECT timestampdiff(year, #rightnow, date(#birthdate))
If we want to return a number of years, then the return type would be a numeric type like INT or DECIMAL. We wouldn't return a DATE datatype.
DELIMITER $$
CREATE FUNCTION current_age(birthdate DATE)
RETURNS INT
BEGIN
RETURN TIMESTAMPDIFF(YEAR,birthdate,DATE(NOW()));
END$$
DELIMITER ;
I want to call multiple procedures from within a procedure. In the following SQL, I create three procedures. upd_r_money and upd_r_fuel both work as expected when called individually from the command line. When I call upd_all, only the first call within upd_all is run; the second call to upd_r_money doesn't run.
I can't figure out why this happens - maybe something in my upd_r_fuel procedure causes my upd_all procedure to end early? I am a newby to writing procedures, and SQL in general.
There was another question here about this problem, but the answer is exactly what I'm already doing, and the answer's link was down.
drop procedure upd_r_money;
delimiter //
CREATE procedure upd_r_money(row_id int)
BEGIN
DECLARE money_rate INT DEFAULT 1;
DECLARE period INT DEFAULT 0;
SET period = (select timestampdiff(second, (select lastaccessed from gamerows where id = row_id), now()));
update gamerows
set money = money + period * money_rate,
lastaccessed = now()
where id = row_id;
END;
//
delimiter ;
drop procedure upd_r_fuel;
delimiter //
CREATE procedure upd_r_fuel(row_id int)
fuel: BEGIN
DECLARE fuel_rate INT DEFAULT 1;
DECLARE period INT DEFAULT 0;
SET period = (select timestampdiff(second, (select lastaccessed from gamerows where id = row_id), now()));
update gamerows
set fuel = fuel + period * fuel_rate,
lastaccessed = now()
where id = row_id;
END fuel;
//
delimiter ;
drop procedure upd_all;
delimiter //
CREATE PROCEDURE upd_all(row_id int)
BEGIN
call upd_r_fuel(row_id);
call upd_r_money(row_id);
END;
//
delimiter ;
If I copy and paste the above SQL commands, my procedures are created successfully with no errors and I can call all three of them. However as I wrote earlier, upd_all seems to stop after calling its first procedure within. If I switch upd_r_money with upd_r_fuel, the same behavior occurs - the first procedure is called and not the second.
I suspect that it doesn't work as expected because you update lastaccessed time and calculate difference with NOW. First work because there is significant difference. But with second stored procedure you have timestammpdiff between NOW() and NOW() - miliseconds.
Check if removing in first stored procedure lastaccessed from update helps.
drop procedure upd_r_money;
delimiter //
CREATE procedure upd_r_money(row_id int)
BEGIN
DECLARE money_rate INT DEFAULT 1;
DECLARE period INT DEFAULT 0;
SET period = (select timestampdiff(second, (select lastaccessed from gamerows where id = row_id), now()));
update gamerows
set money = money + period * money_rate
where id = row_id;
END;
//
delimiter ;
Warning: Now the order of execution matters.
Also your stored procedures are so similiar that I would combine them in one UPDATE:
update gamerows
set fuel = fuel + period * fuel_rate,
money = money + period * money_rate,
lastaccessed = now()
where id = row_id;
I have been sitting with a stored procedure for MySQL for days now, it just won't work, so I thought I'd go back to basic and do a very simple function that checks if an item exists or not.
The problem I had on the first one was that it said END IF is invalid syntax on one of my IF clauses, but not the other two. The second one won't even recognize BEGIN as valid syntax...
Is it I that got everything wrong, or have I stumbled upon a MYSQL Workbench bug? I have Workbench 5.2 (latest version when I'm writing this) and this is the code:
DELIMITER $$
CREATE FUNCTION `filmsidan`.`f_lateornot` (movie_id INT)
BEGIN
DECLARE check_val INT;
DECLARE return_val INT;
SELECT stockId
FROM orders
WHERE stockId = movie_id
INTO check_val;
IF check_val <= 0
THEN
SET return_val = 1;
ELSE
SET return_val = 0;
END IF;
RETURN return_val;
END
to fix the "begin" syntax error, you have to declare a return value, like this:
CREATE FUNCTION `filmsidan`.`f_lateornot` (movie_id INT) RETURNS INT(11)
after doing that, Workbench won't return an error anymore ;o)
You have to specify the return value in signature as well delimiter at the end is missing. So, your function should look like
DELIMITER $$
CREATE FUNCTION `filmsidan`.`f_lateornot` (movie_id INT) RETURNS INT
BEGIN
DECLARE check_val INT;
DECLARE return_val INT;
SELECT stockId
FROM orders
WHERE stockId = movie_id
INTO check_val;
IF check_val <= 0
THEN
SET return_val = 1;
ELSE
SET return_val = 0;
END IF;
RETURN return_val;
END
$$
DELIMITER $$
CREATE FUNCTION `filmsidan`.`f_lateornot` (movie_id INT)
BEGIN
DECLARE check_val INT;
DECLARE return_val INT;
SELECT stockId
FROM orders
WHERE stockId = movie_id
INTO check_val;
IF check_val <= 0
THEN
SET return_val = 1;
ELSE
SET return_val = 0;
END IF;
RETURN return_val;
END
$$
DELIMITER ;
Add this last thing it works :
$$
DELIMITER ;
it means you are using ( ; ) this in function so for that reason we use it..see
and see also
MySQL - Trouble with creating user defined function (UDF)