Trigger not working: - mysql

I created trigger on table PENDING. Pending table has 3 columns - uniqueId , duration and maxDuration. I have another table COUNT with 2 columns - req_id, total
Here is my trigger--
CREATE TRIGGER plus3second BEFORE INSERT
ON PENDING
FOR EACH ROW
BEGIN
DECLARE req_id varchar(25);
DECLARE total int(11);
DECLARE duration int(2);
SET req_id = SUBSTR(new.uniqueId, 1, 14);
Select total into total from COUNT where req_id = 'req_id';
IF total > 100 THEN
SET duration = new.duration + 3;
IF duration < new.maxDuration Then
SET new.duration = duration;
END IF;
END IF;
END
Trigger created successfully. I fired these queries on COUNT and PENDING-
insert into COUNT values ('77711422099653',200);
insert into PENDING (uniqueId, duration, maxDuration) values ('77711422099653919893277163', 3, 20);
But trigger not working ...Where is the problem ?

Check with this trigger definition(with less conflicting names):
CREATE TRIGGER plus3second
BEFORE INSERT
ON PENDING
FOR EACH ROW
BEGIN
DECLARE tReqID varchar(25);
DECLARE tTotal int(11);
DECLARE tDuration int(2);
SET tReqID = SUBSTR(new.uniqueId, 1, 14);
SELECT total
INTO tTotal
FROM COUNT
WHERE req_id = tReqID;
IF tTotal > 100
THEN
SET tDuration = new.duration + 3;
IF tDuration < new.maxDuration
THEN
SET new.duration = tDuration;
END IF;
END IF;
END

Related

How do I fetch the data using multiple cursors and multiple loops in MySQL Stored Procedure?

As per the use case, this procedure should return 30 rows with 15 unique lead id's corresponding to all 15 in activity=1; randomly 10 participate in activity = 2; and from those 10, 5 leads randomly correspond to activity=3.
When I run the stored procedure, it goes on until populating 25 records; which correspond to uniquely getting 15 id's for activity=1 and 10 out of them for activity=2; but, I am unable to fetch the records right after.
If you check down in the code; I have mentioned a SELECT statement just before closing cur2 (SELECT COUNT(*) FROM task2), which should return Count=25; but it's not. So, apparently, the program isn't even going further into the cur3 which I have declared for activity=3.
I have tried using Continue Handler with cursor, too; but it didn't seem to work!
Can anyone help resolve this issue?
BEGIN
DROP TABLE IF EXISTS task2;
CREATE TABLE task2 (
ID int(11) NOT NULL AUTO_INCREMENT,
type_id int(11) DEFAULT NULL,
url varchar(100) DEFAULT NULL,
lead_id int(11) DEFAULT NULL,
createdDate datetime DEFAULT NULL,
month varchar(20) DEFAULT NULL,
year int(11) DEFAULT NULL,
month_year varchar(20) DEFAULT NULL,
PRIMARY KEY (ID)
)
BEGIN
-- INSERTING DATA FOR ACTIVITY = 1
DECLARE nurl VARCHAR(100);
DECLARE nleadid INTEGER;
DECLARE ncreateddate DATETIME;
DECLARE l_count INTEGER;
DECLARE loop_count INTEGER;
-- LOOP COUNT = 15
SET l_count = 15;
SET loop_count = 1;
read_loop:LOOP
IF loop_count > l_count THEN
LEAVE read_loop;
END IF;
IF loop_count = 1
THEN
SET nleadid = 100;
SET ncreateddate = ('2012-09-08 01:09:30');
ELSE
SET nleadid = 100 + loop_count - 1;
SET ncreateddate = (SELECT MAX(createdDate) FROM task2);
SET ncreateddate = DATE_ADD(ncreateddate, INTERVAL ELT(0.5 + RAND() * 6, '3', '5', '45', '34', '23', '68') MINUTE);
END IF;
SET nurl = ELT(0.5 + RAND() * 3, 'g.com', 'y.com', 'm.com');
INSERT INTO task2 (type_id, url, lead_id, createdDate)
VALUES ('1', nurl, nleadid, ncreateddate);
UPDATE task2
SET month = MONTHNAME(createddate), year = YEAR(createddate), month_year = CONCAT(MONTHNAME(createddate),'-', YEAR(createddate));
SET loop_count = loop_count + 1;
END LOOP read_loop;
END;
-- INSERTING THE DATA FOR ACTIVITY = 2
BEGIN
DECLARE nurl VARCHAR(100);
DECLARE nleadid INTEGER;
DECLARE ncreateddate DATETIME;
DECLARE l_count INTEGER;
DECLARE loop_count INTEGER;
-- CURSOR DECLARATION TO FETCH 10 RANDOM RECORDS FROM ACTIVITY=1
DECLARE cur2 CURSOR FOR
SELECT DISTINCT lead_id FROM task2 WHERE type_id = 1 ORDER BY RAND() LIMIT 10;
SET l_count = 10;
SET loop_count = 1;
OPEN cur2;
read_loop:LOOP
FETCH cur2 INTO nleadid;
IF loop_count > l_count THEN
SELECT loop_count_2, l_count_2;
LEAVE read_loop;
END IF;
SET nurl = ELT(0.5 + RAND() * 3, 'g.com', 'y.com', 'm.com');
SET ncreateddate = (SELECT MAX(createdDate) FROM task2 WHERE lead_id = nleadid);
SET ncreateddate = DATE_ADD(ncreateddate, INTERVAL ELT(0.5 + RAND() * 6, '3', '5', '45', '34', '23', '68') MINUTE);
INSERT INTO task2 (type_id, url, lead_id, createdDate)
VALUES ('2', nurl, nleadid, ncreateddate);
UPDATE task2
SET month = MONTHNAME(createddate), year = YEAR(createddate), month_year = CONCAT(MONTHNAME(createddate),'-', YEAR(createddate));
SET loop_count = loop_count + 1;
SELECT COUNT(*) FROM task2;
END LOOP read_loop;
SELECT COUNT(*) FROM task2;
CLOSE cur2;
END;
-- INSERTING DATA FOR ACTIVITY = 3
BEGIN
DECLARE nurl VARCHAR(100);
DECLARE nleadid INTEGER;
DECLARE ncreateddate DATETIME;
DECLARE l_count INTEGER;
DECLARE loop_count INTEGER;
-- CURSOR DECLARATION FOR SELECTING 5 RANDOM LEADS FROM ACTIVITY=2
DECLARE cur3 CURSOR FOR
SELECT DISTINCT lead_id FROM task2 WHERE type_id = 2 ORDER BY RAND() LIMIT 5;
SET l_count = 5;
SET loop_count = 1;
OPEN cur3;
read_loop:LOOP
IF loop_count > l_count THEN
LEAVE read_loop;
END IF;
FETCH cur3 INTO nleadid;
SET nurl = CONCAT(ELT(0.5 + RAND() * 3, 'g.com', 'y.com', 'm.com'), ELT(0.5 + RAND() * 3, '/home.html', '/index.html', '/about.html'));
SELECT nurl;
SET ncreateddate = (SELECT MAX(createdDate) FROM task2 WHERE lead_id = nleadid);
SET ncreateddate = DATE_ADD(ncreateddate, INTERVAL ELT(0.5 + RAND() * 6, '3', '5', '45', '34', '23', '68') MINUTE);
SELECT ncreateddate;
INSERT INTO task2 (type_id, url, lead_id, createdDate)
VALUES ('3', nurl, nleadid, ncreateddate);
UPDATE task2
SET month = MONTHNAME(createddate), year = YEAR(createddate), month_year = CONCAT(MONTHNAME(createddate),'-',YEAR(createddate));
SET loop_count =loop_count + 1;
END LOOP read_loop;
CLOSE cur3;
END;
SELECT * FROM task2;
END

MySql Trigger if insert

Currently I've a cron job which runs each 5 minutes and always populates: record_id, timestamp and heating status (1 and 0) in 'data' table.
I want to create a trigger which on insert to 'data' table will be capturing first occurrence of heating status '1' (heating on) and inserts data to 'heating_data' table (record_id_on, timestamp and heating_on , it needs to stay dormant until heating is set to '0' (heating off), then it should trigger update to last row and insert timestamp_off and heating_off.
DELIMITER //
create TRIGGER heating_data_insert
AFTER INSERT ON nest_stats.data
FOR EACH ROW
BEGIN
DECLARE id_exists Boolean;
select 1
into #id_exists
from nest_stats.data
where record_id= new.record_id
and heating = 1
;
if #id_exists = 1
then
insert nest_stats.heating_data
SET record_id_on= (select max(record_id) from nest_stats.data),
device_serial_number=new.device_serial_number,
user_id=new.user_id,
timestamp_on=new.timestamp,
heating_on=new.heating;
END IF;
select 2
into #id_exists
from nest_stats.data
where record_id= new.record_id
and heating = 0 ;
if #id_exists = 2
then
update nest_stats.heating_data
SET record_id_off= new.record_id,
timestamp_off=new.timestamp,
heating_off=new.heating
where record_id_on =(select max(record_id_on) from nest_stats.data);
END IF;
END;
//
DELIMITER ;
<code>
I did the following changes and worked for me.
DECLARE id_exists Boolean;
SELECT EXISTS(select record_id from nest_stats.data
where record_id= new.record_id
and heating = 1) into #id_exists;
IF #id_exists THEN

IF ELSE STATEMENT for the Differnce of two columns in MYSQL

I have 3 tables : badge_master, match_result_updation and team_badges.
The badge_master is the master table where I manually insert the data acc to the excel. On match_result_updation I have some columns, if sum(goal_column1) - sum(goal_column2) = 10, then the value column1 will get the badge and it will be inserted in team_badges table. I am handling it through trigger but unable to proceed after certain time.
The trigger which I tried :
CREATE TRIGGER `afterinsert_teamgoals` AFTER INSERT ON `match_result_updation` FOR EACH ROW
BEGIN
DECLARE goalCount1 INT(10);
DECLARE goalCount2 INT(10);
DECLARE badgeId BIGINT(20);
DECLARE teamId bigint(20) default 0 ;
SELECT team1_goal INTO goalCount1 FROM match_result_updation WHERE team1_id = NEW.team1_id ;
SELECT team2_goal INTO goalCount2 FROM match_result_updation WHERE team2_id = NEW.team2_id ;
IF (goalCount1 - goalCount2 >= 10)
Then
Insert into team_badges(team_id,badge_id,match_id,timestamp)
SELECT teamId , badgeId , match_id FROM match_result_updation limit 1;
END IF;
Please Assist.

Stock Backtesting

I'm fairly new to MYSQL but I have experience programming in VBA. I'm trying to create a stored procedure which will backtest a strategy against a table of historical stock price data.The procedure will calculate the 20 Day moving average of closing stock price then if the selected day CLOSE has a price that his higher than the moving average a "buy" is initiated. If a trade is currently on, no new "buys" can be placed and if the selected day CLOSE is below the 20 day moving average a "sell" is initiated. Every time a buy or sell is placed the data is recorded in a table created called backtest results. The data I'm using is from http://finance.yahoo.com/q/hp?s=AAPL+Historical+Prices and I placed it into a table. As you can see the the data is in descending order so in order for me to back test I have to start at the earliest date which happens to be at the bottom. The problem I'm having is that no data is being inputted into this newly created table (Buy Date, Buy Price, Sell Date, Sell Price) . Can anyone spot why this is? Also is mysql suited for row-by-row processing? Thanks!
`Begin
DECLARE total_count int;
DECLARE moving_average decimal;
DECLARE move_up int;
DECLARE current_price decimal;
DECLARE count_var int;
DECLARE buy_price decimal;
DECLARE sell_price decimal;
DECLARE trade_on tinyint;
DECLARE account_balance decimal;
DECLARE start_row int;
DECLARE trade_date date;
SET #trade_on = 0;
SELECT #trade_on;
DROP TABLE IF EXISTS backtestresults;
CREATE TABLE backtestresults (buydate date,buyprice decimal, selldate date, sellprice decimal, accountbalance decimal);
SELECT COUNT(*) INTO #total_count FROM AAPL_Prices;
SELECT * FROM AAPL_Prices WHERE Special_ID = #total_count;
SET #start_row = #total_count -19;
SET #account_balance = 100000;
Loop1: WHILE (start_row > 1) DO
SELECT FORMAT(AVG(SClose),2) FROM AAPL_Prices WHERE Special_ID < #start_row + 19 AND Special_ID > #start_row INTO #moving_average;
SELECT SClose FROM AAPL_Prices WHERE Special_ID = #start_row -19 INTO #current_price;
SELECT TradeDate FROM AAPL_Prices WHERE special_ID = #start_row -19 INTO #trade_date;
IF #trade_on = 0 THEN
IF #current_price > #moving_average THEN
SET #buy_price = #current_price;
SET #trade_on = 1;
SET #account_balance = #account_balance - #buy_price;
INSERT INTO backtestresults (buyprice) values (#buy_price);
INSERT INTO backtestresults (buydate) values (#trade_date);
INSERT INTO backtestresults (balance) values (#account_balance);
End If;
END IF;
IF trade_on = 1 THEN
IF #current_price < #moving_average THEN
SET #sell_price = #current_price;
SET #trade_on = 0;
SET #account_balance = #account_balance + #buy_price;
INSERT INTO backtestresults(sellprice) values (#sell_price);
INSERT INTO backtestresults(selldate) values (#trade_date);
INSERT INTO backtestresults(balance) values (#account_balance);
END IF;
END IF;
SET #start_row = #start_row - 1;
END WHILE Loop1;
SELECT #account_balance;
DESCRIBE backtestresults;
SELECT #start_row;
End`

MYSQL - function not returning expected results

I'm building a site for property rentals. I'm doing the search bit now and I'm trying to setup a function I can call for each property. The function needs to grab all rows from the rental_periods table attached to a given property then work out the best (cheapest) weekly price.
I have the following tables setup already.
properties - One line for each property
rental_periods - Multiple lines for each property, tied with id.
Each line is selfcatered or catered.
If selfcatered the price needs to be worked out from prices given in:
WeekDayPerDay - wdpd
WeekEndPerNight - wepn
Monthly price - monthly
Week price - wk
If catered the prices can be given in:
PerPersonPerNight - pppn
PerNight - pn
PerPersonPerWeek - pppw
I need a function that takes a property id and then grabs all periods that apply, then depending on selfcatered/catered works out the price per week that's best.
What I've got so far doesn't seem to be working. It either returns NULL or returns 100000.00 (my upper limit default price).
Here's the code
DELIMITER $$
CREATE FUNCTION get_price(myid INT)
RETURNS VARCHAR(20)
BEGIN
DECLARE done INT DEFAULT 0;
DECLARE price decimal(30,3) default 100000.000;
DECLARE id INT;
DECLARE prop_id INT;
DECLARE type enum('catered','selfcatered');
DECLARE name varchar(45);
DECLARE `from` date;
DECLARE `to` date;
DECLARE currency varchar(45);
DECLARE so tinyint;
DECLARE wk decimal(30,3);
DECLARE wepn decimal(30,3);
DECLARE wdpd decimal(30,3);
DECLARE monthly decimal(30,3);
DECLARE extra decimal(30,3);
DECLARE pppn decimal(30,3);
DECLARE pn decimal(30,3);
DECLARE pppw decimal(30,3);
DECLARE minstay int;
DECLARE maxstay int;
DECLARE breakfast varchar(45);
DECLARE annual TINYINT;
DECLARE cur1 CURSOR FOR SELECT * FROM rental_periods WHERE prop_id = myid;
DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = 1;
OPEN cur1;
REPEAT
FETCH cur1 INTO id, prop_id, type, name, `from`, `to`, currency, so, wk, wepn, wdpd, minstay, maxstay, monthly, extra, pppn, pn, pppw, breakfast, annual;
IF NOT done THEN
IF (#type = "selfcatered") THEN
IF (#wdpd > 0 AND (#wdpd * 7) < #price) THEN
SET price = #wdpd * 7;
END IF;
IF (#wepn > 0 AND (#wepn * 7) < #price) THEN
SET price = #wepn * 7;
END IF;
IF ((#wdpd > 0 AND #wepn > 0) AND
(#wdpd * 5 + #wepn * 2) < #price) THEN
SET price = #wdpd * 5 + #wepn * 2;
END IF;
IF (#monthly > 0 AND (#monthly / (52 / 12)) < #price) THEN
SET price = #monthly / (52 / 12);
END IF;
IF (#wk > 0 AND #wk < #price) THEN
SET price = #wk;
END IF;
ELSE
IF (#pppn > 0 AND (#pppn * 7) < #price) THEN
SET price = #pppn * 7;
END IF;
IF (#pn > 0 AND (#pn * 7) < #price) THEN
SET price = #pn * 7;
END IF;
IF (#pppw > 0 AND (#pppw) < #price) THEN
SET price = #pppw;
END IF;
END IF;
END IF;
UNTIL done END REPEAT;
CLOSE cur1;
RETURN price;
END $$
i'm hoping/not thats it's something stupid with how I've arranged it, or my lack of pure MySQL.
ANY help would be very helpful.
EDIT:
Here's an example row from rental_periods:
INSERT INTO `rental_periods` (`id`, `prop_id`, `type`, `name`, `from`, `to`, `currency`, `so`, `wk`, `wepn`, `wdpd`, `minstay`, `maxstay`, `monthly`, `extra`, `pppn`, `pn`, `pppw`, `breakfast`, `annual`)
VALUES (64732, 32, 'selfcatered', 'Summer', '2012-06-01', '2012-08-31', NULL, 1, '350', '60', '100', '', '', '', '', NULL, NULL, NULL, NULL, 0);
I'd expect the function to return 350 picked from the per week column. However if the wepn was 30, not 60, I'd expect 210 to come back (worked out from 7 * wepn prices).
The code im testing in SP:
DELIMITER $$
CREATE procedure tmp_get_price(myid INT)
BEGIN
DECLARE done INT DEFAULT 0;
DECLARE price decimal(30,3) default 100000.000;
DECLARE id INT;
DECLARE prop_id INT;
DECLARE type enum('catered','selfcatered');
DECLARE name varchar(45);
DECLARE `from` date;
DECLARE `to` date;
DECLARE currency varchar(45);
DECLARE so tinyint;
DECLARE wk decimal(30,3);
DECLARE wepn decimal(30,3);
DECLARE wdpd decimal(30,3);
DECLARE monthly decimal(30,3);
DECLARE extra decimal(30,3);
DECLARE pppn decimal(30,3);
DECLARE pn decimal(30,3);
DECLARE pppw decimal(30,3);
DECLARE minstay int;
DECLARE maxstay int;
DECLARE breakfast varchar(45);
DECLARE annual TINYINT;
DECLARE cur1 CURSOR FOR SELECT id, prop_id, type, name, `from`, `to`, currency, so, wk, wepn, wdpd, minstay, maxstay, monthly, extra, pppn, pn, pppw, breakfast, annual FROM rental_periods WHERE prop_id = myid;
DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = 1;
OPEN cur1;
REPEAT
FETCH cur1 INTO id, prop_id, type, name, `from`, `to`, currency, so, wk, wepn, wdpd, minstay, maxstay, monthly, extra, pppn, pn, pppw, breakfast, annual;
IF NOT done THEN
IF (type = "selfcatered") THEN
IF (wdpd > 0 AND (wdpd * 7) < price) THEN
SET price = wdpd * 7;
END IF;
IF (wepn > 0 AND (wepn * 7) < price) THEN
SET price = wepn * 7;
END IF;
IF ((wdpd > 0 AND wepn > 0) AND
(wdpd * 5 + wepn * 2) < price) THEN
SET price = wdpd * 5 + wepn * 2;
END IF;
IF (monthly > 0 AND (monthly / (52 / 12)) < price) THEN
SET price = monthly / (52 / 12);
END IF;
IF (wk > 0 AND wk < price) THEN
SET price = wk;
END IF;
ELSE
IF (pppn > 0 AND (pppn * 7) < price) THEN
SET price = pppn * 7;
END IF;
IF (pn > 0 AND (pn * 7) < price) THEN
SET price = pn * 7;
END IF;
IF (pppw > 0 AND (pppw) < price) THEN
SET price = pppw;
END IF;
END IF;
END IF;
UNTIL done END REPEAT;
CLOSE cur1;
select price;
END $$
still doesnt work... :( am i being stupid... cant see why this wont work..?!?
gets the periods...
goes throught each one...
if the price is less set it....
select price....?!?
if i put multiple selects in... for example inside the cursor.
only the very bottom one fires and returns 100000.000
i've setup all the value fields as decimals and not allowing NULL...
any thoughts when im going wrong...? also tried debug by inserting in to log table... never fires..?!
Need to read more on cursors this seams a good place to start...
http://www.kbedell.com/2009/03/02/a-simple-example-of-a-mysql-stored-procedure-that-uses-a-cursor/