MySQL: Why is my trigger never adding 7 days? - mysql

My table:
CREATE TABLE `files_processed` (
`filename` varchar(128) NOT NULL,
`uploaded_by` varchar(64) NOT NULL,
`domain` varchar(255) NOT NULL,
`session_id` varchar(64) NOT NULL,
`datetime_uploaded` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,
`insert_data` tinyint(1) NOT NULL DEFAULT '1',
`generate_positives` tinyint(1) DEFAULT '1',
`generate_negatives` tinyint(1) NOT NULL DEFAULT '0',
`custom_rules` tinyint(1) NOT NULL DEFAULT '0',
`processing_stage` enum('completed','underway','wait','') NOT NULL DEFAULT 'wait',
`scheduled_processing_datetime` datetime DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
My trigger:
DELIMITER $$
CREATE TRIGGER `setProcessingData` BEFORE INSERT ON `files_processed` FOR EACH ROW BEGIN
DECLARE vNextDtTime datetime;
DECLARE vDom varchar(255);
SET vDom = new.domain;
SET new.session_id=new.domain;
SELECT max(scheduled_processing_datetime)
INTO vNextDtTime
FROM files_processed
WHERE domain='#vDom';
IF (ISNULL(vNextDtTime))
THEN
SET vNextDtTime := now();
ELSE
SET vNextDtTime := DATE_ADD(vNextDtTime, interval 7 day);
END IF;
SET new.scheduled_processing_datetime := vNextDtTime;
END
$$
DELIMITER ;
My 2 inserts:
INSERT INTO files_processed (filename, uploaded_by, domain)
VALUES ('1.txt', 'hcs.dfc#gmail.com', 'gmail.com');
Above is inserting current timestamp which is as expected
INSERT INTO files_processed (filename, uploaded_by, domain)
VALUES ('2.txt', 'hcs.dfc#gmail.com', 'gmail.com');
Now for this above, I expect the trigger to add 7 days, but it is still treating as current timestamp.

vDom is not equal to #vdom
If you put in the variable it works
# variables are session variables, that can be set and beselected after your insert.
Another think it is better to name a variable _vDom so that you know even in bigger triggers that is a local variable
DROP TRIGGER IF EXISTS `setProcessingData`;
DELIMITER $$
CREATE TRIGGER `setProcessingData` BEFORE INSERT ON `files_processed` FOR EACH ROW BEGIN
DECLARE vNextDtTime datetime;
DECLARE vDom varchar(255);
SET vDom = new.domain;
SET new.session_id=new.domain;
SELECT max(scheduled_processing_datetime)
INTO vNextDtTime
FROM files_processed
WHERE domain= vDom;
IF (ISNULL(vNextDtTime))
THEN
SET vNextDtTime := now();
ELSE
SET vNextDtTime := DATE_ADD(vNextDtTime, interval 7 day);
END IF;
SET new.scheduled_processing_datetime := vNextDtTime;
END
$$
DELIMITER ;

Related

MySQL Trigger statement fails with variable assignment

Following is the definition for Patients table:
Patients table Columns:
PatientId int AI PK
FirstName longtext
LastName longtext
Email longtext
NIC longtext
Phone longtext
Address longtext
City longtext
Country longtext
DOB datetime(6)
Gender longtext
Reference longtext
SerialNumberYear smallint
SerialNumber int
DoctorId int
CreatedOn datetime(6)
UpdatedOn datetime(6)
CreatedBy longtext
SMS_Allowed tinyint(1)
Email_Allowed tinyint(1)
SpecialConcern1 longtext
SpecialConcern2 longtext
SpecialConcern3 longtext
SpecialConcern4 longtext
CustomYearlyId longtext
YearlyId int
I have the following trigger in MySQL on this table:
CREATE TRIGGER generate_yearly_id BEFORE INSERT ON clinic.patients
FOR EACH ROW
BEGIN
DECLARE last_id INTEGER default 10;
DECLARE current_year DATE;
DECLARE yearly_id INTEGER default 0;
IF NEW.CustomYearlyId IS NULL THEN
BEGIN
INSERT INTO DEBUG VALUES (null,"start trigger");
#SET #last_id := (SELECT max(yearlyid) FROM patients WHERE
# YEAR(createdon)=YEAR(CURDATE()));
IF last_id IS NOT NULL THEN
BEGIN
SET #yearly_id = 1;
INSERT INTO DEBUG VALUES (null, concat("in if lastid is not null ",#yearly_id));
END;
ELSE
BEGIN
#SET #yearly_id := 1;
END;
END IF;
SET NEW.yearlyid := #yearly_id;
END;
END IF;
END;//
delimiter ;
The statement SET #yearly_id = 1; works fine. But if I change it to SET #yearly_id = #last_id;, the trigger fails. What am I doing wrong in making this assignment? last_id has a default value, so do I need to initialize it?
The following code works perfectly. Differences are 1. Variables have been initialized before being used. Apparently default value is not enough. 1. Count has been used in the "if" condition instead of testing for "is null".
CREATE TRIGGER generate_yearly_id BEFORE INSERT ON clinic.patients
FOR EACH ROW
BEGIN
DECLARE last_id INTEGER default 0;
DECLARE current_year DATE;
DECLARE yearly_id INTEGER default 1;
declare count INTEGER default 0;
IF NEW.CustomYearlyId IS NULL THEN
BEGIN
#init last_id to some value before using
SET #last_id = 0;
SET #yearly_id = 0;
#INSERT INTO DEBUG VALUES (null,"start trigger");
set #count := (select count(*) from patients where
YEAR(CreatedOn)=YEAR(curdate()));
IF #count > 0 THEN
BEGIN
SET #last_id := (SELECT max(yearlyid) FROM patients WHERE
YEAR(createdon)=YEAR(CURDATE()));
SET #yearly_id = #last_id + 1;
SET NEW.yearlyid := #yearly_id;
#INSERT INTO DEBUG VALUES (null, concat("in if lastid is not null ",#yearly_id));
END;
ELSE
BEGIN
#INSERT INTO DEBUG VALUES (null, concat("in else ",#yearly_id));
#SET #yearly_id = 1;
SET NEW.yearlyid := 1;
END;
END IF;
#Set NEW.yearlyid := 1;
END;
END IF;
END;//
delimiter ;

Error code 1048 encountered during SP call

I'm experiencing a 'Column cannot be null' error for 2 columns, when I try to run a SP.
Source table A is defined as below:
CREATE TABLE `test_data`.`offer` (
`id` INT NOT NULL,
`hotel_id` INT NOT NULL,
`currency_id` INT NOT NULL,
`source_system_code` VARCHAR(64) NOT NULL,
`available_cnt` INT NOT NULL,
`sellings_price` FLOAT NOT NULL,
`checkin_date` DATE NOT NULL,
`checkout_date` DATE NOT NULL,
`valid_offer_flag` TINYINT(1) NOT NULL,
`offer_valid_from` DATETIME NOT NULL,
`offer_valid_to` DATETIME NOT NULL,
`breakfast_included_flag` TINYINT(1) NOT NULL,
`insert_datetime` DATETIME NOT NULL,
PRIMARY KEY (`id`));
Table B into which I am inserting the data:
CREATE TABLE `calculate_USD` (
`counter` int(11) NOT NULL AUTO_INCREMENT,
`dates` date DEFAULT NULL,
`id` int(11) NOT NULL,
`hotel_id` int(11) NOT NULL,
`original_price` int(11) NOT NULL,
`currency_id` int(11) NOT NULL,
PRIMARY KEY (`counter`)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8;
Here is the SP for the insertion:
CREATE PROCEDURE `test_procedure`()
BEGIN
DECLARE aid INT;
DECLARE avalid_from_date DATE;
DECLARE avalid_to_date DATE;
DECLARE hotel_id INT;
DECLARE original_price float;
DECLARE currency_id int;
DECLARE tempdt DATE;
DECLARE done INT DEFAULT FALSE;
DECLARE getdates CURSOR FOR
SELECT id,offer_valid_from,offer_valid_to,hotel_id,sellings_price,currency_id
from offer;
DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = TRUE;
OPEN getdates;
read_loop: LOOP
FETCH getdates
INTO aid,avalid_from_date,avalid_to_date,hotel_id,original_price,currency_id;
IF done THEN
LEAVE read_loop;
END IF;
set tempdt=date(avalid_from_date);
WHILE (tempdt <= date(avalid_to_date)) do
insert into calculate_USD(dates,id,hotel_id,original_price,currency_id)
values(tempdt,aid,hotel_id,original_price,currency_id);
set tempdt=tempdt+INTERVAL 1 DAY;
end while;
END LOOP;
CLOSE getdates;
END
//
When I call the SP,
hotel_id & currency_id columns are instigating the error code.
If I assign them both NULL default values, the SP runs however, the hotel_id & currency_id values being inserted are all NULL like so (rest are OK):
counter | dates | id | hotel_id | original_price | currency_id |
1 | 2015-4-30 | 342523| NULL | 200 | NULL |
2 | 2015-4-30 | 342524| NULL | 112 | NULL |
This is strange, because both have valid data in the source table.
Please advise.
One option that can solve is:
.
.
.
DECLARE `getdates` CURSOR FOR
SELECT
`id`,
`offer_valid_from`,
`offer_valid_to`,
-- `hotel_id`,
`offer`.`hotel_id`,
`sellings_price`,
-- `currency_id`
`offer`.`currency_id`
FROM
`offer`;
.
.
.
So I figured it out.
All I had to do was re-name the hotel_id & currency_id variables in the SP to something else and it worked.
Updated SP:
delimiter //
CREATE PROCEDURE `test_procedure`()
BEGIN
DECLARE aid INT;
DECLARE avalid_from_date DATE;
DECLARE avalid_to_date DATE;
DECLARE sp_hotel_id INT;
DECLARE original_price float;
DECLARE sp_currency_id int;
DECLARE tempdt DATE;
DECLARE done INT DEFAULT FALSE;
DECLARE getdates CURSOR FOR
SELECT id,offer_valid_from,offer_valid_to,hotel_id,sellings_price,currency_id
from offer;
DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = TRUE;
OPEN getdates;
read_loop: LOOP
FETCH getdates
INTO aid,avalid_from_date,avalid_to_date,sp_hotel_id,original_price,sp_currency_id;
IF done THEN
LEAVE read_loop;
END IF;
set tempdt=date(avalid_from_date);
WHILE (tempdt <= date(avalid_to_date)) do
insert into calculate_USD(dates,id,hotel_id,original_price,currency_id)
values(tempdt,aid,sp_hotel_id,original_price,sp_currency_id);
set tempdt=tempdt+INTERVAL 1 DAY;
end while;
END LOOP;
CLOSE getdates;
END
//
call test_procedure();

MySQL Trigger Insert Before Not Firing

I'm trying to add a trigger for auditing to initialize a datetime field on an insert. Does anyone see what might be causing this trigger to not fire???
USE example;
CREATE TABLE USERS (
ID INT UNSIGNED NOT NULL AUTO_INCREMENT,
FULLNAME VARCHAR(128) NOT NULL,
`PASSWORD` CHAR(88) NOT NULL,
EMAIL VARCHAR(128) NOT NULL,
FLAGS TINYINT UNSIGNED DEFAULT 0,
CREATED DATETIME,
UPDATED TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
UNIQUE INDEX(EMAIL),
PRIMARY KEY( ID )
);
DELIMITER $$;
CREATE TRIGGER USER_T BEFORE INSERT ON USERS FOR EACH ROW
BEGIN
SET NEW.CREATED = CURRENT_TIMESTAMP();
END;$$
DELIMITER ;
INSERT INTO USERS(FULLNAME, `PASSWORD`, EMAIL) VALUES('Admin', 'sQnzu7wkTrgkQZF+0G1hi5AI3Qmzvv0bXgc5THBqi7mAsdd4Xll27ASbRt9fEyavWi6m0QP9B8lThf+rDKy8hg==', 'root#localhost');
It looks like you are using the ; as a delimiter here
SET NEW.CREATED = CURRENT_TIMESTAMP();
END;$$
DELIMITER ;
Try this:
DELIMITER $$;
CREATE TRIGGER USER_T BEFORE INSERT ON USERS FOR EACH ROW
BEGIN
SET NEW.CREATED = CURRENT_TIMESTAMP();
END $$
DELIMITER ;

Error Code: 1062 Duplicate entry for key 'PRIMARY'

I am constantly getting a Error code 1062: Duplicate Entry.
The first row insert, but then it fails on the same ID.
So everytime I hit execute it will increment: 1466, 1467, 1468, 1469.
And each time there is the same record entered, so I am assuming the autoincrement is only working for the first iteration.
Table:
'entity':
CREATE TABLE `entity` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(255) NOT NULL,
`reg_num` varchar(45) NOT NULL,
`enterprise_id` int(11) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=1474 DEFAULT CHARSET=latin1 COMMENT=\'Comment'
Stored procedure:
DELIMITER $$
CREATE DEFINER=`root`#`localhost` PROCEDURE `tp_to_entityPROC`()
DETERMINISTIC
COMMENT 'stored'
BEGIN
DECLARE done BOOLEAN DEFAULT 0;
DECLARE Tid INT;
DECLARE Tt_name TEXT;
DECLARE allt CURSOR FOR
SELECT training_provider_id, training_provider_name
FROM training_providers;
DECLARE CONTINUE HANDLER FOR NOT FOUND SET done=1;
OPEN allt;
read_loop: LOOP
IF done THEN
LEAVE read_loop;
END IF;
FETCH allt INTO Tid, Tt_name;
SET #id = 0;
SET #t_name = 0;
SET #id = Tid;
SET #t_name = Tt_name;
SET #empty = '';
if (#id != 0) THEN
INSERT INTO entity (name)
VALUES (#t_name);
SET #my_id = LAST_INSERT_ID();
IF #my_id != 0 THEN
UPDATE training_awarded_providers
SET training_awarded_provider_id = #my_id
WHERE training_awarded_provider_id = #id;
END IF;
END IF;
END LOOP;
CLOSE allt;
END
Not sure about the exact error of duplicate entry but your posted code is not going to work.
Your Table schema
CREATE TABLE `entity` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(255) NOT NULL,
`reg_num` varchar(45) NOT NULL <-- Here it's non null column
In your store procedure you are trying to insert null to reg_num column which will never succeed
if (#id != 0) THEN
INSERT INTO entity (name)
VALUES (#t_name);

Mysql use LAST_INSERT_ID in stored procedure

I need to create a table based on the last id inserted into another main table, for this I created the following stored procedure:
CREATE PROCEDURE `sp_create_campaign`
(
IN p_vName VARCHAR(70),
IN p_iIdOper INT(11),
IN p_iIdCount INT(11),
IN p_iIdMoney INT(11),
IN p_cPrefix CHAR(2),
IN p_tComment TINYTEXT,
IN p_iIdUser VARCHAR(32),
OUT p_return_code TINYINT UNSIGNED
)
BEGIN
DECLARE p_campaign INT(11);
DECLARE exit handler for sqlexception
BEGIN
-- ERROR
set p_return_code = 1;
rollback;
END;
DECLARE exit handler for sqlwarning
BEGIN
-- WARNING
set p_return_code = 2;
rollback;
END;
START TRANSACTION;
-- Campaign
INSERT INTO `db_campaign`
(`vName`, `iIdOper`, `iIdCount`, `iIdMoney`, `cPrefix`, `tComment`, `iIdUser`, `dRegister`)
VALUES
(p_vName, p_iIdOper, p_iIdCount, p_iIdMoney, p_cPrefix, p_tComment, p_iIdUser, NOW());
SET p_campaign := LAST_INSERT_ID();
-- Sales
SET #s = CONCAT('DROP TABLE IF EXISTS ', 'db_sale_', p_campaign);
PREPARE stm FROM #s;
EXECUTE stm;
SET #x = CONCAT(
'CREATE TABLE ',
'db_sale_', p_campaign,
"(
`iIdSale` INT(11) UNSIGNED NOT NULL AUTO_INCREMENT,
`dDate` DATETIME NOT NULL DEFAULT '0000-00-00 00:00:00',
`dSubtotal` DECIMAL(7,2) UNSIGNED NOT NULL DEFAULT '00.00',
`dTax` DECIMAL(7,2) UNSIGNED NOT NULL DEFAULT '00.00',
`dTotal` DECIMAL(7,2) UNSIGNED NOT NULL DEFAULT '00.00',
`iIdMoney` INT(11) UNSIGNED NOT NULL,
`iIdOper` INT(11) UNSIGNED NOT NULL,
`iIdBankCount` INT(11) UNSIGNED NOT NULL,
`iIdGroup` INT(11) UNSIGNED NOT NULL,
`iIdUser` INT(11) UNSIGNED NOT NULL,
`iIdUserReg` VARCHAR(32) NOT NULL,
`dRegister` DATETIME NOT NULL DEFAULT '0000-00-00 00:00:00',
PRIMARY KEY (`iIdSale`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;");
PREPARE stm FROM #x;
EXECUTE stm;
COMMIT;
-- SUCCESS
set p_return_code = 0;
END
But the problem is that only inserts the first record and fails to create the table. Where am I failing?
Replace this line: SET p_campaign := LAST_INSERT_ID();
With this one: SELECT LAST_INSERT_ID() INTO p_campaign ;
if you use SET you need = instead of :=
Two things:
Executing DROP will implicitly COMMIT your transaction.
Try adding
DEALLOCATE PREPARE stm;
after each EXECUTE statement.
According to MySQL documentation of last_insert_id()
If a stored procedure executes statements that change the value of LAST_INSERT_ID(), the changed value is seen by statements that follow the procedure call.
Use something like:
SELECT id INTO p_campaign FROM db_campaign ORDER BY id DESC LIMIT 1;
Or:
SELECT max(id) INTO p_campaign FROM db_campaign;