generated column with condition sql - mysql

mysql command to generate a column from other column according to condition
loan_amount | installment | start_date | status
------------------------------------------------------------------
500 | 100 | 2018-1-1 |
if (loan_amount % installment != 0) then month_required to pay = loan_amount / installment + 1
else month_required = loan_amount / installment;
then i want to check by adding month_required to start_date if it has crossed current date. If not then status would generate "incomplete" else "complete" .
delimiter //
set #month = "0";
create trigger `status_check` before insert on `loan`
for each row
begin
if NEW.loan_amount% NEW.installment != 0
then set #month NEW.loan_amount/ NEW.installment +1;
else set #month = NEW.loan_amount/NEW.installment;
end if ;
if NOW() <= dateadd(NEW.start_date,INTERVAL #month MONTH)
then set NEW.status = "incomplete";
else set NEW.status = "complete";
end if;
end;
//
DELIMITER ;
what is the error here? please help.

I Can't make the real answer as you don't provide all your database field nor a data sample, but some BEFORE INSERT and BEFORE UPDATE Trigger will probably do the job.
This is the base for the BEFORE INSERT :
DELIMITER //
DROP TRIGGER IF EXISTS `trg_test_insert`;
//
CREATE TRIGGER `trg_test_insert`
BEFORE INSERT ON `table`
FOR EACH ROW
BEGIN
IF NEW.loan_amount % NEW.installment != 0 THEN
SET NEW.month_required = NEW.loan_amount / NEW.installment + 1;
ELSE
SET NEW.month_required = NEW.loan_amount / NEW.installment;
END IF;
END;
//
DELIMITER ;
Take a look at MySQL 5.7 Reference Manual / ... / Trigger Syntax and Examples
And at :
MYSQL Triggers - how to store the result of a calculated field

Related

Update Data When Trigger Execute in Mysql?

I want WaterRateMeterStart with WaterRateMeterEnd have same value sequentially if data updated.
This is my table
And This is my table structure
This my code and
I do not know how mistakes can occur.
DELIMITER $$
CREATE TRIGGER after_update_rates_water_again AFTER UPDATE ON waterrates FOR EACH ROW
BEGIN
IF
new.WaterRateMeterStart <> old.WaterRateMeterStart THEN
UPDATE waterrates
SET WaterRateMeterEnd = new.WaterRateMeterStart
WHERE
WaterRateId = ( new.WaterRateId - 1 );
ELSEIF new.WaterRateMeterEnd <> old.WaterRateMeterEnd THEN
UPDATE waterrates
SET WaterRateMeterStart = new.WaterRateMeterEnd
WHERE
WaterRateId = ( new.WaterRateId + 1 );
END IF;
END $$
DELIMITER ;
And error if I updated the data
UPDATE `waterrates` SET `WaterRateMeterStart` = '9' WHERE `waterrates`.`WaterRateId` = 2

Return value from DATE_SUB/DATE_ADD in stored function

I am trying to write a stored function that takes a string in proper ISO format (yyyy-mm-dd) and subract a certain number of weekdays from it. Based off of this question here I have tried both the accepted answer as well as one a few answers down that does things differently, however, both of them are just saying how to write the pure sql, and don't have an example of a function.
What I currently have is this:
delimiter //
CREATE DEFINER=`root`#`localhost` FUNCTION `WEEKDATE_SUB` (days TINYINT, date_val VARCHAR(16))
RETURNS DATE DETERMINISTIC
BEGIN
DECLARE SUBVAL INT;
DECLARE dow INT;
CASE
WHEN dow=1 THEN SET SUBVAL = (days +(FLOOR((days-0.5)/5)+1)*2 - 1);
WHEN dow=2 THEN SET SUBVAL = (days +(FLOOR((days-0.5)/5)+1)*2);
WHEN dow=3 THEN SET SUBVAL = (days-1 +(FLOOR(((days-1)-0.5)/5)+1)*2 + 1);
WHEN dow=4 THEN SET SUBVAL = (days-2 +(FLOOR(((days-2)-0.5)/5)+1)*2 + 2);
WHEN dow=5 THEN SET SUBVAL = (days-3 +(FLOOR(((days-3)-0.5)/5)+1)*2 + 3);
WHEN dow=6 THEN SET SUBVAL = (days-4 +(FLOOR(((days-4)-0.5)/5)+1)*2 + 4);
WHEN dow=7 THEN SET SUBVAL = (days-5 +(FLOOR(((days-5)-0.5)/5)+1)*2 + 5);
END CASE
RETURN DATE_SUB(date_val, INTERVAL SUBVAL DAY);
END;//
When I try to add it, I get a vague error (as mysql is fond of offering):
You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'RETURN DATE_SUB(date_val, INTERVAL SUBVAL DAY);
END' at line 14
I have tried several variations on returning including trying to define a variable for Date sub and return that, but it's pretty much the same error.
Outside of a function, I know this works, so it seems like I should just be able to return that.
SELECT DATE_SUB("2016-01-01", INTERVAL 4 DAY);
The docs suggest you need to have END CASE, instead of END
Additionally, the stored function will probably execute a little faster if you use the CASE expr WHEN value2 THEN .... WHEN value2 THEN ... END CASE version, since it will not have to repeat the DAYOFWEEK function calls potentially 7 times.
you can also use something like this
delimiter //
CREATE DEFINER=`root`#`localhost` FUNCTION `WEEKDATE_SUB` (date_val VARCHAR(10), days TINYINT)
RETURNS VARCHAR(10) DETERMINISTIC
BEGIN
RETURN date_val - INTERVAL
FLOOR(days/5)*7 +
IF(DAYOFWEEK(date_val)-1 <= days - FLOOR(days/5)*5
, (days - FLOOR(days/5)*5)+2
, days - FLOOR(days/5)*5
) DAY;
END;//
samples
mysql> SELECT WEEKDATE_SUB('2017-02-06',1);
+------------------------------+
| WEEKDATE_SUB('2017-02-06',1) |
+------------------------------+
| 2017-02-03 |
+------------------------------+
1 row in set (0,00 sec)
mysql> SELECT WEEKDATE_SUB('2017-02-07',1);
+------------------------------+
| WEEKDATE_SUB('2017-02-07',1) |
+------------------------------+
| 2017-02-06 |
+------------------------------+
1 row in set (0,00 sec)
mysql> SELECT WEEKDATE_SUB('2017-02-07',2);
+------------------------------+
| WEEKDATE_SUB('2017-02-07',2) |
+------------------------------+
| 2017-02-03 |
+------------------------------+
1 row in set (0,00 sec)
mysql>
This is what I finally needed to get this working. Notice, the ; and the change to how I am using the CASE statement.
delimiter //
CREATE DEFINER=`root`#`localhost` FUNCTION `WEEKDATE_SUB` (date_val VARCHAR(10), days TINYINT)
RETURNS VARCHAR(10) DETERMINISTIC
BEGIN
DECLARE SUBVAL INT;
DECLARE dow INT;
SET dow = DAYOFWEEK(date_val);
CASE dow
WHEN 1 THEN SET SUBVAL = (days +(FLOOR((days-0.5)/5)+1)*2 - 1);
WHEN 2 THEN SET SUBVAL = (days +(FLOOR((days-0.5)/5)+1)*2);
WHEN 3 THEN SET SUBVAL = (days-1 +(FLOOR(((days-1)-0.5)/5)+1)*2 + 1);
WHEN 4 THEN SET SUBVAL = (days-2 +(FLOOR(((days-2)-0.5)/5)+1)*2 + 2);
WHEN 5 THEN SET SUBVAL = (days-3 +(FLOOR(((days-3)-0.5)/5)+1)*2 + 3);
WHEN 6 THEN SET SUBVAL = (days-4 +(FLOOR(((days-4)-0.5)/5)+1)*2 + 4);
WHEN 7 THEN SET SUBVAL = (days-5 +(FLOOR(((days-5)-0.5)/5)+1)*2 + 5);
ELSE SET SUBVAL = days;
END CASE;
RETURN DATE_SUB(date_val, INTERVAL SUBVAL DAY);
END;//

How to update mysql data with event and remove the event after

I have a mysql table that looks like this
| begintime | endtime | begindate | enddate | state |
+------------+----------+------------+----------+-------+
| TIME | TIME | DATE | DATE | string|
+------------+----------+------------+----------+-------+
I have this code
CREATE EVENT Update
ON SCHEDULE
EVERY 1 SECOND
DO
UPDATE tablename SET tablename.state = CASE
WHEN (SELECT CURRENT_TIME() FROM DUAL)>=tablename.begintime AND (SELECT CURDATE()>= tablename.begindate) THEN "Available"
WHEN (SELECT CURRENT_TIME() FROM DUAL)>tablename.endtime AND (SELECT CURDATE()= tablename.enddate) THEN "Finished"
ELSE "Not Available"
END
I want the server to be always checking if any of those statements is true, and I dont know how to remove the event when:
WHEN (SELECT CURRENT_TIME() FROM DUAL)>tablename.endtime AND (SELECT CURDATE()= tablename.enddate) THEN "Finished
Thanks for your help.
please try this one.
SET GLOBAL event_scheduler = ON;
DROP EVENT IF EXISTS Update1;
CREATE EVENT Update1
ON SCHEDULE
EVERY 1 SECOND
DO
UPDATE tablename SET tablename.state =
CASE
WHEN NOW() BETWEEN CONCAT(tablename.begindate,' ',tablename.begintime) AND CONCAT(tablename.enddate,' ',tablename.endtime) THEN "Available"
WHEN NOW() > CONCAT(tablename.enddate,' ',tablename.endtime) THEN "Finished"
ELSE "Not Available"
END;
To drop the event after setting to "Finished" try using something like this
SET GLOBAL event_scheduler = ON;
DROP EVENT IF EXISTS Update1;
DELIMITER //
CREATE EVENT Update1
ON SCHEDULE
EVERY 1 SECOND
DO BEGIN
SELECT #begindate := begindate,
#begintime:= begintime,
#enddate := enddate,
#endtime := endtime FROM tablename;
IF (NOW() BETWEEN CONCAT(#begindate,' ',#begintime) AND CONCAT(#enddate,' ',#endtime)) THEN
UPDATE tablename SET state = 'Available';
ELSEIF (NOW() < CONCAT(#begindate,' ',#begintime)) THEN
UPDATE tablename SET state = 'Not Available';
ELSEIF (NOW() > CONCAT(#enddate,' ',#endtime)) THEN
UPDATE tablename SET state = 'Finished';
DROP EVENT IF EXISTS Update1;
END IF;
END//
DELIMITER ;

Trigger in mysql updating in another database

is there something wrong with this trigger ? It suppose to update a datefield on a table in another database. Can anyone give me a hand ? thanks
DROP TRIGGER IF EXISTS depoisDeInserir_invoice;
DELIMITER $$
CREATE TRIGGER depoisDeInserir_invoice AFTER INSERT ON pag_invoice
FOR EACH ROW
BEGIN
DECLARE trial datetime;
SET trial = (select dataTrial
from networkcen_1.companyproductuser
where (CompanyKey = NEW.companyKey)
and (ProductKey = NEW.productKey)
and (UserKey = NEW.productKey));
IF (trial < CURDATE()) THEN
UPDATE networkcen_1.companyproductuser
SET dataVencimento = DATE_ADD(CURDATE(),INTERVAL NEW.dias DAY)
where (CompanyKey = NEW.companyKey)
and (ProductKey = NEW.productKey)
and (UserKey = NEW.productKey);
ELSE
UPDATE networkcen_1.companyproductuser
SET dataVencimento = DATE_ADD(trial,INTERVAL NEW.dias DAY)
where (CompanyKey = NEW.companyKey)
and (ProductKey = NEW.productKey)
and (UserKey = NEW.productKey);
END IF;
END;
$$
DELIMITER ;

How to update multiple tables and fields in a Trigger?

I have the following schema : SQL Fiddle.
The trigger is updating the articles.votes field. I also need it to update the members.points field and the members lifetime_points fields with the same formula as updates the articles.votes field. How do I do that?
Are you looking for this?
DELIMITER $$
CREATE TRIGGER tg_ai_article_votes
AFTER INSERT ON article_votes
FOR EACH ROW
BEGIN
UPDATE articles
SET votes = COALESCE(votes, 0) + 1
WHERE id = NEW.article_id;
UPDATE members
SET points = COALESCE(points, 0) + 1,
lifetime_points = COALESCE(lifetime_points, 0) + 1
WHERE id = NEW.member_id;
END$$
CREATE TRIGGER tg_ad_article_votes
AFTER DELETE ON article_votes
FOR EACH ROW
BEGIN
UPDATE articles
SET votes = COALESCE(votes, 0) - 1
WHERE id = OLD.article_id;
UPDATE members
SET points = COALESCE(points, 0) - 1,
lifetime_points = COALESCE(lifetime_points, 0) - 1
WHERE id = OLD.member_id;
END$$
DELIMITER ;
Here is SQLFiddle demo