Process Multiple Row by a MYSQL Store Procedure - mysql

I am facing some trouble inserting data into a table by Store Procedure. Please allow me to explain in details.
I have a Three tables
CREATE TABLE `table_1` (
`id` INT(11) NOT NULL AUTO_INCREMENT,
`s_id` INT(11) NOT NULL,
`created` DATE NOT NULL,
`val` VARCHAR(255) NOT NULL,
PRIMARY KEY (`id`)
)
COLLATE='latin1_swedish_ci'
ENGINE=InnoDB
AUTO_INCREMENT=1;
CREATE TABLE `table_2` (
`s_id` INT(11) NOT NULL AUTO_INCREMENT,
`t_id` INT(11) NOT NULL,
`p_id` INT(11) NOT NULL,
`d_id` INT(11) NOT NULL,
`created` DATE NOT NULL,
PRIMARY KEY (`id`)
)
COLLATE='latin1_swedish_ci'
ENGINE=InnoDB
AUTO_INCREMENT=1;
CREATE TABLE `table_3` (
`id` INT(11) NOT NULL AUTO_INCREMENT,
`count` INT(11) NOT NULL,
`created` DATE NOT NULL,
`s_id` VARCHAR(255) NOT NULL,
`t_id` VARCHAR(255) NOT NULL,
`p_id` VARCHAR(255) NOT NULL,
PRIMARY KEY (`id`)
)
Is there any way to insert into 2nd table by store procedure using select statement. There will be multiple data as Select * from table_1; Then there will be a process like if(table_1.s_id == table_3.s_id) THEN UPDATE table_3 set count = count +1 ELSE INSERT into table_3 (s_id,t_id.....
Though I have tried using Cursor but its inserting only one record.
Here are the example of my usage of Cursor
DECLARE done INT DEFAULT FALSE;
DECLARE curs_count INT(11) DEFAULT 0;
DECLARE v_s_id BIGINT(20) DEFAULT 0;
DECLARE v_t_id BIGINT(20) DEFAULT 0;
DECLARE v_p_id BIGINT(20) DEFAULT 0;
DECLARE v_t_date BIGINT(20) DEFAULT 0;
DECLARE co_s_id BIGINT(20) DEFAULT 0;
DECLARE curs CURSOR FOR
SELECT
a.id,b.s_id,b.t_id,b.created
FROM
table_1 a
INNER JOIN table_2 b ON a.s_id = b.s_id
WHERE
a.val <> '';
DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = TRUE;
DECLARE curs_id INT(11) DEFAULT 0;
OPEN curs;
SELECT FOUND_ROWS() INTO curs_count;
start_loop: loop
FETCH curs INTO curs_id,v_s_id,v_t_id,v_c_date;
IF done THEN
LEAVE start_loop;
END IF;
SELECT s_id INTO co_s_id FROM table_3;
IF co_s_id>0
THEN
update table_3 SET count = count+1 where s_id = co_s_id;
ELSE
INSERT INTO table_3 (support_id,track_id,track_date,count) VALUES (v_s_id,v_t_id,v_c_date,1);
END IF;
end loop;
CLOSE curs;
Can anyone help me out with this?

This code is running properly. The issue was infinite loop made the tables corrupted so no data were inserting.

Related

Call another Store Procedure from select statement query in a Stored Procedure

I am very new to MYSQL and Store Procedure. I am trying to find out a way if I can call a store procedure inside of a loop by fetching data from a table in a Store Procedure. Here are the example code for better understanding.
`CREATE TABLE `students` (
`student_id` INT(11) NOT NULL AUTO_INCREMENT,
`name` INT(11) NOT NULL,
`age` INT(11) NOT NULL,
`school` VARCHAR(255) NOT NULL,
PRIMARY KEY (`student_id`)
)
COLLATE='latin1_swedish_ci'
ENGINE=InnoDB
AUTO_INCREMENT=1;
CREATE TABLE `marks` (
`id` INT(11) NOT NULL AUTO_INCREMENT,
`student_id` INT(11) NOT NULL,
`subject` INT(11) NOT NULL,
`marks` INT(11) NOT NULL,
`grade` DATE NOT NULL,
PRIMARY KEY (`id`)
)
COLLATE='latin1_swedish_ci'
ENGINE=InnoDB
AUTO_INCREMENT=1;
Procedure
BEGIN
DECLARE if_finish INT(1) DEFAULT 0;
DECLARE cur_c INT(11) DEFAULT 0;
DECLARE s_sub VARCHAR(100) DEFAULT 0;
DECLARE s_mark INT(11) DEFAULT 0;
DECLARE s_id INT(11) DEFAULT 0;
DECLARE cur CURSOR FOR
SELECT
a.student_id,a.marks,a.subject
FROM
markstable a
INNER JOIN studentstable b ON a.student_id = b.student_id
WHERE
a.s_id> 0;
DECLARE CONTINUE HANDLER FOR NOT FOUND SET if_finish = 1;
OPEN curs;
SELECT FOUND_ROWS() INTO cur_c;
IF cur_c>0 THEN
FETCH cur INTO s_id ,s_mark,s_sub;
call sp_calculatemarks(s_id,s_mark,s_sub);
ELSE
SET s_sub = '';
END IF;
CLOSE cur;
END
The above code is mostly running ok but the problem is its processing only one record whereas I have 48 Records in Marks table. But I don't know how to fetch all data in SP and call each by each to another Procedure. I think Cursor doesn't work in that way. Is there any concept like fetchrow?
I need some help with this method.

How to create trigger for broken cars using IF statement

I want to create a trigger that will not allow to rent a car if it is currently being repaired. Im quite new in triggers... could anyone shed some light on this aspect of triggers? My assumptions would be that it would something like...
DELIMITER $$
CREATE TRIGGER `inspections_const` BEFORE UPDATE ON `inspections` FOR EACH ROW BEGIN
SET NEW.booking_id = IF.repair_complete = 'No'
THEN 'Allow booking'
ELSE 'Do not allow'
END;
END
$$
DELIMITER ;
Table is
CREATE TABLE `inspections` (
`inspection_id` int(10) NOT NULL,
`inspection_date` date NOT NULL,
`vehicle_id` int(10) NOT NULL,
`problem` varchar(50) NOT NULL,
`repair_complete` enum('Yes','No') NOT NULL,
`mechanic_id` int(10) NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
CREATE TABLE `bookings` (
`booking_id` int(50) NOT NULL,
`booking_date` date NOT NULL,
`start_date` date NOT NULL,
`end_date` date NOT NULL,
`invoice_no` int(10) NOT NULL,
`chauffeur_id` int(10) DEFAULT NULL,
`vehicle_id` int(10) NOT NULL,
`customer_id` int(50) NOT NULL,
`chauffeur_req` enum('Yes','No') NOT NULL,
`special_instructions` varchar(255) NOT NULL,
`TheDuration` varchar(10) NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
I didn't tested it so it might have a missing condition or something like that. But it should help you on the correct path
Query
DELIMITER $$
CREATE TRIGGER `check_repair` BEFORE INSERT ON `bookings` FOR EACH ROW BEGIN
# We need to save the "count"
DECLARE inspections_count INT DEFAULT 0;
# Check if where is a repair going which matches the vehicle_id
SELECT
1 INTO inspections_count # store the "count" into the variable.
FROM inspections
WHERE
inspections.vehicle_id = NEW.vehicle_id
AND
repair_complete = 'No'
ORDER BY
inspections.start_date DESC
LIMIT 1;
# if there is a "count" stop the insert.
IF inspections_count = 0 THEN
SIGNAL SQLSTATE '45000'
SET MESSAGE_TEXT = 'vehicle is in repair';
END IF;
END
$$
DELIMITER ;

MYSQL Trigger when a order is inserted a notification inserted into another table

I have a table called Order and when a order gets inserted into it i want it to insert the sellerID(userID in the notifications) and productName combined with a message to be stored in Notification.Message.
CREATE TABLE `Order` (
`OrderID` int(11) NOT NULL AUTO_INCREMENT,
`productID` int(11) NOT NULL,
`productName` varchar(255) DEFAULT NULL,
`productPrice` int(11) DEFAULT NULL,
`SellerID` int(11) DEFAULT NULL,
`BuyerID` int(11) DEFAULT NULL,
`DateSold` varchar(45) DEFAULT NULL,
PRIMARY KEY (`OrderID`),
);
CREATE TABLE `Notifications` (
`NotificationID` int(11) NOT NULL AUTO_INCREMENT,
`userID` int(10) NOT NULL,
`Message` varchar(255) DEFAULT NULL,
`Viewed` varchar(255) DEFAULT NULL,
PRIMARY KEY (`NotificationID`);
They are my two tables
This is what i tried:
DELIMITER $$
CREATE TRIGGER productTrigger
AFTER INSERT
ON Order FOR EACH ROW
BEGIN
DECLARE ui,pn VARCHAR(50);
SELECT productName INTO pn FROM Order;
SELECT userID INTO ui FROM Product;
INSERT INTO Notifications(userID,Message) VALUES(ui,pn);
end $$
DELIMITER ;
Try:
DELIMITER $$
CREATE TRIGGER `productTrigger` AFTER INSERT ON `Order`
FOR EACH ROW
BEGIN
/*DECLARE ui,pn VARCHAR(50);
SELECT productName INTO pn FROM Order;
SELECT userID INTO ui FROM Product;
INSERT INTO Notifications(userID,Message) VALUES(ui,pn);*/
INSERT INTO `Notifications`
(`userID`, `Message`)
VALUES
(NEW.`SellerID`, NEW.`productName`);
END$$
DELIMITER ;

Mysql Trigger Loop for query result with many rows

hi i have a database with many tables and foreign keys like this
CREATE TABLE IF NOT EXISTS `articulos` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`nombre` varchar(63) NOT NULL,
`contenido` text NOT NULL,
`normas_id` int(11) NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=138 ;
CREATE TABLE IF NOT EXISTS `aspectosambientales` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`nombre` varchar(63) NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=28 ;
CREATE TABLE IF NOT EXISTS `aspectosambientales_articulos` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`aspectosambientales_id` int(11) NOT NULL,
`articulos_id` int(11) NOT NULL,
PRIMARY KEY (`id`),
KEY `fk_aspaspectosambientales1` (`aspectosambientales_id`),
KEY `fk_aspee` (`articulos_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 UTO_INCREMENT=225 ;
CREATE TABLE IF NOT EXISTS `empresas` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`razonsocial` varchar(127) DEFAULT NULL,
`nit` varchar(63) DEFAULT NULL,
`direccion` varchar(127) DEFAULT NULL,
`telefono` varchar(15) DEFAULT NULL,
`web` varchar(63) DEFAULT NULL,
`auth_user_id` int(11) NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=2 ;
CREATE TABLE IF NOT EXISTS `articulos_empresas` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`empresas_id` int(11) NOT NULL,
`articulo_id` int(11) NOT NULL,
`acciones` text,
`responsable` varchar(255) DEFAULT NULL,
`plazo` date DEFAULT NULL,
`cumplido` tinyint(1) DEFAULT NULL,
PRIMARY KEY (`id`),
KEY `fk_normas_empresas_empresas1` (`empresas_id`),
KEY `fk_normas_empresas_normas1` (`normas_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=1 ;
and i need to create a trigger to fill the 'articulos_empresas' after insert in 'empresas' for all rows in 'articulos' that match with 'aspectosambientals' that the new 'empresas' selected.
I get all 'articulos' with this query
SELECT articulos_id FROM aspectosambientales_articulos
WHERE aspectosambientales_id = ID
-- ID is the aspectosambientales_id selected when the 'empresas' row is created
-- maybe something like NEW.aspectosambientales_id
but i dont know how create a loop like ' for loop' in trigger for every result in the query
some like this:
CREATE TRIGGER 'filltableae' AFTER INSERT ON 'empresas'
FOR EACH ROW
BEGIN
DECLARE arrayresult = (SELECT articulos_id FROM aspectosambientales_articulos
WHERE aspectosambientales_id = NEW.aspectosambientales_id)
--- here is when i have to do the loop for all the results
--- for ids in arrayresults
--- insert into articulos_empresas ('',NEW.id, ids, '', '' ,'','')
--- endfor
END
thanks!!!
Based on #Razvan answer i left here the code for the trigger, so maybe can help somebody
DROP TRIGGER IF EXISTS AEINST;
DELIMITER //
CREATE TRIGGER AEINST AFTER INSERT ON procesos_aspectos
FOR EACH ROW
BEGIN
DECLARE done INT DEFAULT FALSE;
DECLARE ids INT;
DECLARE cur CURSOR FOR SELECT articulos_id FROM aspectosambientales_articulos WHERE aspectosambientales_id = NEW.aspectosambientales_id;
DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = TRUE;
OPEN cur;
ins_loop: LOOP
FETCH cur INTO ids;
IF done THEN
LEAVE ins_loop;
END IF;
INSERT INTO articulos_empresas VALUES (null,ids, NEW.empresas_id,null,null,null,null);
END LOOP;
CLOSE cur;
END; //
DELIMITER ;
thanks again!
As far as I know you can iterate through the result of a SELECT query using cursors.
See here : http://dev.mysql.com/doc/refman/5.0/en/cursors.html

Writing a trigger to update a value with a value from its own row

I have the following table..
CREATE TABLE `community_data_1` (
`id` BIGINT(20) UNSIGNED NOT NULL AUTO_INCREMENT,
`type` VARCHAR(1) NOT NULL,
`reply_to_id` BIGINT(20) UNSIGNED NULL DEFAULT NULL,
`subject` TEXT NOT NULL,
`post` MEDIUMTEXT NOT NULL,
`html` VARCHAR(1) NOT NULL DEFAULT '0',
`time_stamp` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
`author_id` BIGINT(20) UNSIGNED NOT NULL,
`d_id` BIGINT(20) UNSIGNED NOT NULL,
PRIMARY KEY (`id`)
)
ENGINE=MyISAM
ROW_FORMAT=DEFAULT
Now whenever an insert is done, after the insert I need to check if the d_id value is set to zero, if it is then I need to update it to the same value as that of the id of that row. How do I do this?
delimiter |
CREATE TRIGGER fixValue BEFORE INSERT ON community_data_1
FOR EACH ROW BEGIN
IF NEW.d_id = 0 THEN
SET #NewId= (SELECT MAX(id)+1 FROM community_data_1);
SET NEW.d_id = NewId;
END IF;
END;
|
delimiter ;