I am trying to only execute a block of code if a variable exists. Here is a code snipit. Can you nest Begin...End statements in an IF block?
I've re-designed this several times. Suggestions?
delimiter //
drop trigger if exists example_trigger;//
create trigger example_trigger AFTER UPDATE on some_table for each row
BLOCK1: begin
-- check current status
DECLARE done BOOLEAN DEFAULT FALSE;
-- cap check
if (new.CURRENT_ALLOCATED >= new.TOTAL_ALLOWED_QTY) then
SET done = TRUE;
end if; -- cap check end
-- o
if (done != TRUE and new.O_KEY is not null and new.A_KEY is null) then
OBLOCK: begin
DECLARE done_o BOOLEAN DEFAULT FALSE;
DECLARE pd_nbr INT;
DECLARE no_more_rows BOOLEAN;
DECLARE cur_pd CURSOR FOR
select pd.STATUS_KEY
from PROD_DEL_V pd
join PROD_T p on pd.KEY_NBR = p.KEY_NBR
where pd.STATUS not in ('PU', 'EX')
and p.O_KEY = new.O_KEY;
DECLARE CONTINUE HANDLER FOR NOT FOUND
SET done_o = TRUE;
-- run updates
if (done_o != TRUE) then
-- open cursor
OPEN cur_pd;
-- loop start
loop_it: LOOP
FETCH cur_pd INTO pd_nbr;
-- exit loop if..
if no_more_rows = TRUE THEN
CLOSE cur_pd;
LEAVE loop_it;
end if;
INSERT INTO STATUS_TABLE (
STATUS_KEY
, STATUS
, NOTE_TXT
)
(
SELECT
PD.STATUS_KEY
, 'PU' AS STATUS
, concat('example_trigger - MAX has been reached or exceeded [TOTAL_ALLOWED_QTY = ',new.TOTAL_ALLOWED_QTY,' and CURRENT_ALLOCATED = ', new.CURRENT_ALLOCATED, ']') AS NOTE_TXT
FROM PROD_DEL_TABLE PD
WHERE PD.STATUS_KEY = pd_nbr
);
END LOOP loop_it;
end if; -- run updates end
end OBLOCK:; -- end block
end if; -- o
-- a
if (done != TRUE and new.O_KEY is null and new.A_KEY is not null) then
ABLOCK: begin
DECLARE done_a BOOLEAN DEFAULT FALSE;
DECLARE pd_nbr INT;
DECLARE no_more_rows BOOLEAN;
DECLARE cur_pd CURSOR FOR
select pd.STATUS_KEY
from PROD_DEL_V pd
join PROD_T p on pd.KEY_NBR = p.KEY_NBR
join A_O_T a on a.O_KEY = p.O_KEY
where pd.STATUS not in ('PU', 'EX')
and a.A_KEY = new.A_KEY;
DECLARE CONTINUE HANDLER FOR NOT FOUND
SET done_a = TRUE;
-- run updates
if (done_a != TRUE) then
-- open cursor
OPEN cur_pd;
-- loop start
loop_it: LOOP
FETCH cur_pd INTO pd_nbr;
-- exit loop if..
if no_more_rows = TRUE THEN
CLOSE cur_pd;
LEAVE loop_it;
end if;
INSERT INTO STATUS_TABLE (
STATUS_KEY
, STATUS
, NOTE_TXT
)
(
SELECT
PD.STATUS_KEY
, 'PU' AS STATUS
, concat('example_trigger - MAX has been reached or exceeded [TOTAL_ALLOWED_QTY = ',new.TOTAL_ALLOWED_QTY,' and CURRENT_ALLOCATED = ', new.CURRENT_ALLOCATED, ']' AS NOTE_TXT
FROM PROD_DEL_TABLE PD
WHERE PD.STATUS_KEY = pd_nbr
);
END LOOP loop_it;
end if; -- run updates end
end ABLOCK; -- end block
end if; -- a
end BLOCK1; -- end large block
//
delimiter ;
What is the problem with IF and BEGIN...END clause? Take a look at this simple example -
CREATE PROCEDURE procedure1(IN Param1 VARCHAR(255))
BEGIN
IF Param1 = 1 THEN
BEGIN
DECLARE i INT;
-- do something
END;
ELSE
BEGIN
DECLARE i INT;
-- do something
END;
END IF;
END
Related
Hello I have the following stored procedure for MySQL but when it is executed in my ASP.NET Core application I get a Subquery returns more than 1 row error. What am I doing wrong here? The equivalent SQL Server version used to work without problems...
-- System Calculates Candidate’s Matching Score based on a Manager’s Answer Weights
CREATE PROCEDURE spSysCalcCandScore
(
IN Candidate_ID INT,
IN Manager_ID INT
)
Begin
DECLARE ansID INT;
DECLARE tempSum INT;
DECLARE Sum INT;
DECLARE Done INT DEFAULT FALSE;
DECLARE MyCursor CURSOR FOR
SELECT Answer_ID FROM Completed_Questionnaire
WHERE Candidate_ID = Candidate_ID;
DECLARE CONTINUE HANDLER FOR NOT FOUND SET Done = TRUE;
START TRANSACTION;
OPEN MyCursor;
myloop: LOOP
FETCH MyCursor INTO ansID;
IF Done THEN
LEAVE myloop;
END IF;
SET tempSum = (SELECT Weight_Value FROM Weight WHERE (Answer_ID = ansID AND Manager_ID = Manager_ID));
SET Sum = Sum + tempSum;
END LOOP;
CLOSE MyCursor;
IF (Sum IS NULL) THEN
SET Sum = 0;
END IF;
UPDATE `Interest`
SET Matching_Score = Sum
WHERE (Candidate_ID = Candidate_ID AND Manager_ID = Manager_ID);
COMMIT;
End//
I am trying to create a repetition in 'cursor' that uses 'join', but it doesn't work.
Already tested without 'join' and works normally.
My code:
DECLARE hvDataAtual DATE;
DECLARE manDataAtual DATETIME;
DECLARE motCodAtual INT;
DECLARE done INT DEFAULT FALSE;
DECLARE Crs_vei_man
CURSOR FOR (
SELECT hvedatageracao, hvedatageracao, hvemotorista
FROM tableone INNER JOIN tabletwo ON hveveiculo = manveiculo
WHERE SUBSTRING(mandata, 1, 10) = SUBSTRING(hvedatageracao, 1, 10) LIMIT 10);
DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = TRUE;
OPEN Crs_vei_man;
myloop: LOOP
FETCH Crs_vei_man
INTO hvDataAtual,
manDataAtual,
motCodAtual;
-- Insert 1 row (null, null, null) ?
INSERT INTO testes VALUES(hvDataAtual, manDataAtual, motCodAtual);
IF done THEN
LEAVE myloop;
END IF;
IF motCodAtual > 0 THEN
INSERT INTO testes VALUES('hvDataAtual', 'manDataAtual', 'motCodAtual');
END IF;
END LOOP;
CLOSE Crs_vei_man;
This code is in a stored procedure.
What is happening?
I normally try to figure things out on my own, but I'm stumped on this.
I have leads in one SugarCRM account that I want to reassign a specific number to each active user. Every time I try to run this I keep getting "ERROR 1064 (42000):... at Line 4" and I have no idea what is wrong.
This is what I have made so far:
Hello, I normally try to figure things out on my own, but I'm stumped on this.
I have leads in one SugarCRM account that I want to reassign a specific number to each active user. Every time I try to run this I keep getting "ERROR 1064 (42000):... at Line 4" and I have no idea what is wrong.
DELIMITER $$
DROP PROCEDURE IF EXISTS assign_leads $$
CREATE PROCEDURE assign_leads(num_rows INT)
BEGIN
SET num_rows = num_rows;
DECLARE i VARCHAR(255);
DECLARE exit_loop BOOLEAN;
DECLARE employee_cursor CURSOR FOR
SELECT users.id
FROM users
WHERE (((users.title)="South Carolina Qualifier") AND ((users.status)="Active"));
DECLARE CONTINUE HANDLER FOR NOT FOUND SET exit_loop = TRUE;
OPEN employee_cursor;
employee_loop: LOOP
FETCH employee_cursor INTO i;
SET #sql_text1 = concat('UPDATE leads SET assigned_user_id = ',#i,' WHERE ((assigned_user_id IS NULL OR assigned_user_id = '1' OR assigned_user_id = '') AND do_not_call = '0' AND deleted = '0' AND status = 'New') LIMIT ',#num_rows,' 1;')
PREPARE stmt1 FROM #sql_text1;
EXECUTE stmt1;
DEALLOCATE PREPARE stmt1;
IF exit_loop THEN
CLOSE employee_cursor;
LEAVE employee_loop;
END IF;
END LOOP employee_loop;
END $$
DELIMITER ;
Some considerations:
SET must be located after the DECLARE:
...
CREATE PROCEDURE assign_leads(num_rows INT)
BEGIN
-- SET num_rows = num_rows;
DECLARE i VARCHAR(255);
DECLARE exit_loop BOOLEAN;
DECLARE employee_cursor CURSOR FOR
SELECT users.id
FROM users
WHERE (((users.title)="South Carolina Qualifier") AND ((users.status)="Active"));
DECLARE CONTINUE HANDLER FOR NOT FOUND SET exit_loop = TRUE;
SET num_rows = num_rows;
OPEN employee_cursor;
...
This assignment (SET) does not make much sense, it assigns the value of num_rows parameter to the same num_rows parameter.
Must escape some characters from your #sql_text1 variable and add ; at the end of the statement:
...
/*
SET #sql_text1 = concat('
UPDATE leads SET assigned_user_id = ',#i,'
WHERE (
(assigned_user_id IS NULL OR assigned_user_id = '1' OR assigned_user_id = '') AND
do_not_call = '0' AND deleted = '0' AND status = 'New'
)
LIMIT ',#num_rows,' 1;
')
*/
SET #sql_text1 = concat('
UPDATE leads SET assigned_user_id = ',#i,'
WHERE (
(assigned_user_id IS NULL OR assigned_user_id = \'1\' OR assigned_user_id = \'\') AND
do_not_call = \'0\' AND deleted = \'0\' AND status = \'New\'
)
LIMIT ',#num_rows,' 1;
');
...
#i and #num_rows are 9.4. User-Defined Variables, i is one 13.6.4.1. Local Variable DECLARE Syntax and num_rows is a routine parameter, are different variables.
This is the query...
DELIMITER $$
DROP PROCEDURE IF EXISTS assign_leads $$
CREATE PROCEDURE assign_leads(num_rows INT)
BEGIN
DECLARE i VARCHAR(255);
DECLARE exit_loop BOOLEAN;
DECLARE employee_cursor CURSOR FOR
SELECT users.id
FROM users
WHERE (((users.title)="South Carolina Qualifier") AND((users.status)="Active"));
DECLARE CONTINUE HANDLER FOR NOT FOUND SET exit_loop = TRUE;
OPEN employee_cursor;
employee_loop: LOOP
FETCH employee_cursor INTO i;
SET #sql_text1 = concat('
UPDATE leads SET assigned_user_id = ',#i,'
WHERE (
(assigned_user_id IS NULL OR assigned_user_id = \'1\' OR assigned_user_id = \'\') AND
do_not_call = \'0\' AND deleted = \'0\' AND status = \'New\'
) LIMIT ',#num_rows,' 1;'
);
PREPARE stmt1 FROM #sql_text1;
EXECUTE stmt1;
DEALLOCATE PREPARE stmt1;
IF exit_loop THEN
CLOSE employee_cursor;
LEAVE employee_loop;
END IF;
END LOOP employee_loop;
END $$
DELIMITER ;enter code here
I am trying to convert a MSSQL function into MySQL. Here is what I've done so far. Can someone please take a look at it ?
ALTER FUNCTION [dbo].[GetCommaDelimitedCategoryIDs]
(
#datafeedcategoryinfoid int
)
RETURNS varchar(2000)
AS
BEGIN
DECLARE #category_list varchar(4500), #categoryid varchar(20)
SET #category_list = ''
DECLARE category_cursor CURSOR
LOCAL FAST_FORWARD FOR
SELECT DISTINCT categoryid
FROM category_mapping
WHERE datafeedcategoryinfoid = #datafeedcategoryinfoid
OPEN category_cursor;
FETCH NEXT FROM category_cursor
INTO #categoryid;
WHILE ##FETCH_STATUS = 0
BEGIN
SET #category_list = #category_list + #categoryid + ','
FETCH NEXT FROM category_cursor
INTO #categoryid;
END
CLOSE category_cursor;
DEALLOCATE category_cursor;
IF (LEN(#category_list) > 0)
SET #category_list = SUBSTRING(#category_list, 1, LEN(#category_list) - 1)
RETURN #category_list
END
And here is the MySQL function
DELIMITER $$
CREATE DEFINER=``#`` FUNCTION `GetCommaDelimitedCategoryIDs`(
p_datafeedcategoryinfoid int
) RETURNS varchar(2000) CHARSET latin1
BEGIN
DECLARE v_category_list varchar(4500);
DECLARE v_categoryid varchar(20);
DECLARE category_cursor CURSOR FOR
SELECT DISTINCT categoryid
FROM category_mapping
WHERE datafeedcategoryinfoid = p_datafeedcategoryinfoid;
SET v_category_list = '';
OPEN category_cursor;
myloop: LOOP
FETCH category_cursor INTO v_categoryid;
IF done THEN
LEAVE myloop;
END IF;
SET v_category_list = Concat(v_category_list , v_categoryid , ',');
FETCH category_cursor INTO v_categoryid;
END LOOP;
CLOSE category_cursor;
IF (CHAR_LENGTH(RTRIM(v_category_list)) > 0) THEN
SET v_category_list = SUBSTRING(v_category_list, 1, CHAR_LENGTH(RTRIM(v_category_list)) - 1);
END IF;
RETURN v_category_list;
END
But the above function doesn't return the value. Mysql Workbench doesn't return any error, how do i debug ?
Isn't this a job for group_concat()? Something like:
select group_concat(distinct categoryid order by categoryid SEPARATOR ',')
from category_mapping
where datafeedcategoryinfoid = p_datafeedcategoryinfoid;
Here is a demo of group_concat().
DELIMITER $$
CREATE PROCEDURE `remove_schedule_duplicate` ()
BEGIN
BLOCK1 : BEGIN
DECLARE finished INTEGER DEFAULT 0;
DECLARE schedule_id CHAR(36);
DECLARE gamePk INTEGER;
DECLARE keep_entry TINYINT(1);
DECLARE scheduleDuplicate CURSOR FOR SELECT game_pk FROM schedule where is_active = 1 group by game_pk,home_team_id,away_team_id,venue_id having count(game_pk) > 1 limit 2;
DECLARE CONTINUE HANDLER FOR NOT FOUND SET finished = 1;
OPEN scheduleDuplicate;
get_schedule_duplicate: LOOP
FETCH scheduleDuplicate INTO gamePk;
IF finished = 1 THEN
LEAVE get_schedule_duplicate;
END IF;
**BLOCK2 : BEGIN
DECLARE block_finished INTEGER DEFAULT 0;
DECLARE blockDuplicate CURSOR FOR SELECT id FROM schedule where game_pk = gamePk and is_active = 1;
DECLARE CONTINUE HANDLER FOR NOT FOUND SET block_finished = 1;
OPEN blockDuplicate;
block_schedule_duplicate: LOOP
FETCH blockDuplicate INTO schedule_id;
IF block_finished = 1 THEN
LEAVE block_schedule_duplicate;
END IF;
IF keep_entry = 0 THEN
UPDATE schedule set is_active = 0 where id = schedule_id;
END IF;
END LOOP block_schedule_duplicate;
CLOSE blockDuplicate;
END BLOCK2;**
END LOOP get_schedule_duplicate;
CLOSE scheduleDuplicate;
END BLOCK1;
END
$$
The problem is Innerloop first time execute well after that block_finished always be 1 so. always it quits the inner block.
How to resolve this issue. What i do ? Some one help me to resolve the issue.
I have Changed My Stored procedure like this:
DELIMITER $$
CREATE PROCEDURE `remove_schedule_duplicate`()
BEGIN
DECLARE finished INTEGER DEFAULT 0;
DECLARE schedule_id,temp CHAR(36) DEFAULT NULL;
DECLARE gamePk INTEGER;
DECLARE keep_entry TINYINT(1);
DECLARE scheduleDuplicate CURSOR FOR SELECT game_pk,id FROM schedule where game_pk in (SELECT game_pk FROM schedule where is_active = 1 group by game_pk,home_team_id,away_team_id,venue_id having count(game_pk) > 1) and is_active = 1 order by game_pk;
DECLARE CONTINUE HANDLER FOR NOT FOUND SET finished = 1;
OPEN scheduleDuplicate;
get_schedule_duplicate: LOOP
FETCH scheduleDuplicate INTO gamePk,schedule_id;
IF finished = 1 THEN
LEAVE get_schedule_duplicate;
END IF;
IF ((temp IS NULL) AND (gamePk IS NOT NULL)) OR ((temp IS NOT NULL) AND (temp <> gamePk)) THEN
SET temp = gamePk;
SET keep_entry = 1;
#ELSE IF temp IS NOT NULL AND temp = gamePk THEN
ELSE
SET keep_entry = 0;
END IF;
IF keep_entry = 0 THEN
UPDATE schedule set is_active = 0 where id = schedule_id;
END IF;
END LOOP get_schedule_duplicate;
CLOSE scheduleDuplicate;
END$$
DELIMITER ;