mysql loop error in syntax - mysql

I am trying to use simple loop in mysql using Heidisql using the following syntax.
BEGIN
loop_label: LOOP
IF #number_title > #max THEN
**LEAVE loop_label;**
END IF;
select #number_title as number_distinct_title,count(*) as total from (
select count(distinct ctitle), customer_id
FROM table
GROUP BY customer_id
HAVING count(distinct ctitle)=#number_title
ORDER BY customer_id) as total ;
SET #number_title = #number_title + 1;
END LOOP
END
I get a syntax error at LEAVE loop_label;
Can someone please help?
Thanks

In MySQL when you define a trigger or procedure, you usually have to change the delimiter temporarily, because statements within the trigger/procedure must be terminated with ';'.
Just enclose the complete block in "--/" and "/" and you should be good
--/
BEGIN
loop_label: LOOP
IF #number_title > #max THEN
**LEAVE loop_label;**
END IF;
select #number_title as number_distinct_title,count(*) as total from (
select count(distinct ctitle), customer_id
FROM table
GROUP BY customer_id
HAVING count(distinct ctitle)=#number_title
ORDER BY customer_id) as total ;
SET #number_title = #number_title + 1;
END LOOP
END
/
Found from Here

Related

What is the error in it and it is very simple, error is showing in the last 'end' statement. What is the error

There is an error in this code. How can I find it out?
CREATE DEFINER=`root`#`localhost` TRIGGER `check` BEFORE INSERT ON `whatstore` FOR EACH ROW
BEGIN
declare last_insert_time datetime;
declare new_insert_time datetime;
set #last_insert_time=(select insert_time from whatstore order by id desc limit 1);
select datediff(new.insert_time,#last_inserted_time) into new_insert_time;
case
when last_insert_time-new.insert_time>1 then insert into `delete`.table3(time_diff) values(new_inserted_time);
end
END
Your code has a CASE statement, not a CASE expression.
I would advise you to just use IF, but you can adjust your code with END CASE:
begin
declare last_insert_time datetime;
declare new_insert_time datetime;
set #last_insert_time = (select insert_time from whatstore order by id desc limit 1);
select datediff(new.insert_time, #last_inserted_time) into new_insert_time;
case when last_insert_time - new.insert_time > 1
then insert into `delete`.table3 (time_diff)
values (new_inserted_time);
end case;
end;
It seems simpler to write this with no conditional logic:
insert into `delete`.table3 (time_diff)
select w.last_insert_time
from (select insert_time
from whatstore
order by id desc
limit 1
) w
where w.last_insert_time > new.insert_time;

Why stored procedure takes more time to execute compared to stored function for same code?

I have created stored-procedure with OUT parameter to handle automate INSERT operations based on values of other tables. I also made stored-function for the same operation. I am facing a problem with execution time for both is heavily different which makes me worried and I don't know why is that.
Following table values in summary:
2016 rows in emp_personal
I am using MariaDB 10.3.14. I am testing with HeidiSQL 10.1.0.5577.
I also tried calling it from Node.JS using MariaDB Node.js Connector. But in both cases, I had almost the same result.
This is Stored Procedure
CREATE DEFINER=`root`#`localhost` PROCEDURE `sp_auto_attendance`(
OUT `result` INT
)
LANGUAGE SQL
NOT DETERMINISTIC
CONTAINS SQL
SQL SECURITY DEFINER
COMMENT ''
BEGIN
DECLARE empId,done,isHoliday,isEmpHoliday,isWeekOff,isApprovedLeave,insertedRows INT DEFAULT 0;
DECLARE attendance VARCHAR(20) DEFAULT 'Present';
DECLARE empIds VARCHAR(500) DEFAULT '';
-- declare cursor with all employee Ids who are active
DECLARE empIds_cursor CURSOR FOR
SELECT id from emp_personal where isActive=1;
-- declare NOT FOUND handler
DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = 1;
-- Check if today is holiday
SELECT COUNT(id) INTO isHoliday
FROM apexa_portal.public_holiday_dates
WHERE dateOfHoliday= CURDATE();
OPEN empIds_cursor;
get_id: LOOP
SET attendance = 'Present';
FETCH empIds_cursor INTO empId;
-- Following check if NOT FOUND handler has called, if yes exit loop else continue. NOTE: If you don't write this, it will be infinite loop.
IF done = 1 THEN
LEAVE get_id;
END IF;
-- Check if public holiday for employee
IF isHoliday > 0 THEN
SELECT COUNT(phtd.isActive) INTO isEmpHoliday FROM public_holiday_template_days as phtd
LEFT JOIN emp_office_details as eod ON eod.publicHolidayTemplate=phtd.templateId
LEFT JOIN public_holiday_dates as phd ON phd.pub_holiday_id=phtd.holidayId
WHERE eod.empID=empId AND phd.dateOfHoliday=CURDATE() AND phtd.isActive=1;
IF isEmpHoliday > 0 THEN
SET attendance = 'Public Holiday';
END IF;
END IF;
-- if not public holiday, Check if week off
IF attendance <> 'Public Holiday' THEN
SELECT COUNT(eowd.id) INTO isWeekOff FROM emp_office_working_days as eowd
WHERE DAY=DAYOFWEEK(CURDATE()) AND eowd.empId=empId AND eowd.isActive=0;
IF isWeekOff > 0 THEN
SET attendance = 'Week Off';
END IF;
END IF;
-- if not week off, Check if approved leave
IF attendance <> 'Week Off' THEN
SELECT COUNT(la.id) INTO isApprovedLeave FROM leave_application as la
WHERE la.fromDate <= CURDATE() AND la.toDate >= CURDATE() AND la.empID=empId AND la.leaveStatus='Approved';
IF isApprovedLeave > 0 THEN
SET attendance = 'Approved Leave';
END IF;
END IF;
-- insert attendance
INSERT INTO attendance_master(empID,dateOfAttendance,attendance) VALUES(empId,CURDATE(),attendance);
SET insertedRows = insertedRows + 1;
END LOOP get_id;
CLOSE empIds_cursor;
SET result = insertedRows;
END
This is Stored Function
CREATE DEFINER=`root`#`localhost` FUNCTION `test_auto_att_func`()
RETURNS int(11)
LANGUAGE SQL
NOT DETERMINISTIC
CONTAINS SQL
SQL SECURITY DEFINER
COMMENT ''
BEGIN
DECLARE empId,done,isHoliday,isEmpHoliday,isWeekOff,isApprovedLeave,insertedRows INT DEFAULT 0;
DECLARE attendance VARCHAR(20) DEFAULT 'Present';
DECLARE empIds VARCHAR(500) DEFAULT '';
-- declare cursor with all employee Ids who are active
DECLARE empIds_cursor CURSOR FOR
SELECT id from emp_personal where isActive=1;
-- declare NOT FOUND handler
DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = 1;
-- Check if today is holiday
SELECT COUNT(id) INTO isHoliday
FROM apexa_portal.public_holiday_dates
WHERE dateOfHoliday= CURDATE();
OPEN empIds_cursor;
get_id: LOOP
SET attendance = 'Present';
FETCH empIds_cursor INTO empId;
-- Following check if NOT FOUND handler has called, if yes exit loop else continue. NOTE: If you don't write this, it will be infinite loop.
IF done = 1 THEN
LEAVE get_id;
END IF;
-- Check if public holiday for employee
IF isHoliday > 0 THEN
SELECT COUNT(phtd.isActive) INTO isEmpHoliday FROM public_holiday_template_days as phtd
LEFT JOIN emp_office_details as eod ON eod.publicHolidayTemplate=phtd.templateId
LEFT JOIN public_holiday_dates as phd ON phd.pub_holiday_id=phtd.holidayId
WHERE eod.empID=empId AND phd.dateOfHoliday=CURDATE() AND phtd.isActive=1;
IF isEmpHoliday > 0 THEN
SET attendance = 'Public Holiday';
END IF;
END IF;
-- if not public holiday, Check if week off
IF attendance <> 'Public Holiday' THEN
SELECT COUNT(eowd.id) INTO isWeekOff FROM emp_office_working_days as eowd
WHERE DAY=DAYOFWEEK(CURDATE()) AND eowd.empId=empId AND eowd.isActive=0;
IF isWeekOff > 0 THEN
SET attendance = 'Week Off';
END IF;
END IF;
-- if not week off, Check if approved leave
IF attendance <> 'Week Off' THEN
SELECT COUNT(la.id) INTO isApprovedLeave FROM leave_application as la
WHERE la.fromDate <= CURDATE() AND la.toDate >= CURDATE() AND la.empID=empId AND la.leaveStatus='Approved';
IF isApprovedLeave > 0 THEN
SET attendance = 'Approved Leave';
END IF;
END IF;
-- insert attendance
INSERT INTO attendance_master(empID,dateOfAttendance,attendance) VALUES(empId,CURDATE(),attendance);
SET insertedRows = insertedRows + 1;
END LOOP get_id;
CLOSE empIds_cursor;
RETURN insertedRows;
END
Time to execute Stored Function
SELECT `test_auto_att_func`();
/* Affected rows: 0 Found rows: 1 Warnings: 0 Duration for 1 query: 0.328 sec. */
Time to execute Stored Procedure
CALL `sp_auto_attendance`(#res);
SELECT #res;
/* Affected rows: 6,049 Found rows: 1 Warnings: 0 Duration for 2 queries: 00:01:21.6 */
Stored Function Output and Stored Procedure Output
Can anyone please explain why this is happening? And if I am doing anything wrong, please let me know how should I correct it?
Thank You.
There should be no difference on performance on similar code when you run the code as a procedure vs as a function.
Most likely explanation (see Affected rows) is that at the the time of the function run, the cursor did not find any active persons whereas in the procedure run did, hence running the loop queries.

Update Whole Table adding value from previous row

Table acc
If I Edit "A" Amount to 100 then Total amount change
whole table need to update...
So What Will be the mysql query for updating whole table by adding (credit) or subtracting (debit) from previous total amount...
As commented by #Gordon Linoff, you can archive your goal using AFTER UPDATE trigger and a loop. I wrote up the idea as below for example.
DELIMITER //
CREATE TRIGGER acc_after_update
AFTER UPDATE
ON acc FOR EACH ROW
BEGIN
DECLARE done INT DEFAULT FALSE;
DECLARE type varchar(10);
DECLARE total_amount DEFAULT 0;
DECLARE name varchar(10)
DECLARE amount INT;
DECLARE cur1 CURSOR FOR SELECT name, type, amount FROM acc;
DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = TRUE;
OPEN cur1;
REPEAT
FETCH cur1 INTO name, type, amount;
IF NOT done THEN
CASE type
WHEN 'credit' THEN = total_amount + amount;
WHEN 'debit' THEN total_amount = total_amount - amount
END CASE
UPDATE acc
SET amount = total_amount
WHERE name = #name --not sure about this syntax
END IF;
UNTIL done END REPEAT;
CLOSE cur1;
END; //
DELIMITER ;
Hope this helps.
CREATE VIEW [dbo].[vSales]
AS
SELECT ROW_NUMBER() OVER(ORDER BY s.[Name] ) AS 'RowNo',
s.*
, CASE WHEN Type = 'Credit' THEN Amount ELSE - 1 * Amount END As NewAmount
FROM dbo.Sales AS s
GO
SELECT a.[RowNo],
a.[Name],
SUM(b.[NewAmount])
FROM dbo.vSales AS a INNER JOIN dbo.vSales AS b ON a.[RowNo] >= b.[RowNo]
GROUP BY a.[RowNo], a.[Name]
dbo.Sales is the table that holds all the values

How to call stored procedure in event in mysql

I have created a stored procedure and trying to call it in an event, as I want to execute the stored procedure for every 1 min.
But I couldn't find any result.
This is the stored procedure insert_update_supplier that I wrote
DELIMITER $$
USE `eegpap`$$
DROP PROCEDURE IF EXISTS `insert_update_supplier`$$
CREATE DEFINER=`eegpap`#`%` PROCEDURE `insert_update_supplier`()
BEGIN
SELECT COUNT(*) AS col_no1, Invoice_Date AS invoicedate, No_of_Cases AS d_ncases, No_of_Bottles AS d_nbottles, Product_Code AS d_pcode FROM depot_sales__c WHERE Supplier_Code IN (SELECT Supplier FROM advance_payment_request__c);
SELECT From_Date AS s_fromdate FROM supplier_payment__c;
IF col_no1>0 THEN
IF(CURDATE()-invoicedate>=45) THEN
IF(s_fromdate>invoicedate) THEN
UPDATE supplier_payment__c SET From_Date=invoicedate;
END IF;
IF(d_nbottles!=NULL AND d_nbottles>0) THEN
UPDATE supplier_payment__c SET No_of_Loose_Cases=(No_of_Loose_Cases+1) AND No_of_Loose_Bottles=(No_of_Loose_Bottles+d_nbottles);
END IF;
UPDATE supplier_payment__c SET No_of_Loose_Cases=(No_of_Loose_Cases+1) AND No_of_Cases=(No_of_Cases+d_ncases) AND Cost_Value=(d_ncases*(SELECT Landed_Cost FROM product2 WHERE Supplier_Code=d_pcode));
END IF;
END IF;
END$$
DELIMITER ;
This is the event supplier_event
CREATE EVENT supplier_event
ON SCHEDULE EVERY 5 SECOND
DO
CALL insert_update_supplier();
I don't understand where I made the mistake or where the issue is. Or if there is any other alternative for this other than stored procedure please suggest.
Please some help me out. Thanks in advance
This statement:
SELECT COUNT(*) AS col_no1, Invoice_Date AS invoicedate, No_of_Cases AS d_ncases, No_of_Bottles AS d_nbottles, Product_Code AS d_pcode
FROM depot_sales__c
WHERE Supplier_Code IN (SELECT Supplier FROM advance_payment_request__c);
is not doing what you expect. I think you intend something like:
SELECT col_no1 := COUNT(*),
invoicedate := Invoice_Date,
d_ncases := No_of_Case,
d_nbottles := No_of_Bottles,
d_pcode := Product_Code
FROM depot_sales__c
WHERE Supplier_Code IN (SELECT Supplier FROM advance_payment_request__c);
You should also declare the variables you are using in the code block.

stored proc: if else statement inside case when

BEGIN
CASE x
WHEN 0 THEN (
IF thisIsAVariable = 'viewAll' THEN
SELECT id, fname FROM Persons WHERE 1
ELSE
SELECT id, fname FROM Persons WHERE id = '1111'
END IF
);
END CASE;
END
What is the correct syntax for ifelse statments inside casewhen statements?
we can use if inside the if to make code easy like below:
BEGIN
IF x = 0 THEN
IF thisIsAVariable = 'viewAll' THEN
SELECT id, fname FROM Persons WHERE 1;
ELSE
SELECT id, fname FROM Persons WHERE id = '1111';
END IF;
END IF;
END
just use IF-ELSE,
DELIMITER $$
CREATE PROCEDURE procName
BEGIN
IF x = 0 THEN
IF thisIsAVariable = 'viewAll' THEN
SELECT id, fname FROM Persons WHERE 1;
ELSE
SELECT id, fname FROM Persons WHERE id = '1111';
END IF;
ELSE
-- other codes if you have
END IF;
END $$
DELIMITER ;
I think when using CASE, the select statement should return only one value.
just try this one
BEGIN
CASE x
WHEN 0 THEN (
SELECT id, fname FROM Persons WHERE id = IF(thisIsAVariable = 'viewAll',1,'1111')
);
END CASE;
END