Error Code : 1324 Undefined CURSOR - mysql

I just started learning MySQL and am having trouble compiling a procedure.
It's giving me an error undefined cursor. I looked up a few examples on this forum and corrected my code but it still throws the same error.
DELIMITER $
CREATE PROCEDURE MY_PROC()
BLOCK1: BEGIN
DECLARE LOOP1_DONE BOOLEAN DEFAULT FALSE;
DECLARE VAR_TKR VARCHAR(100) DEFAULT 0;
DECLARE TKR_VALUE VARCHAR(100) DEFAULT 0;
-- OTHER VARIABLE DECLARATIONS
DECLARE CUR1 CURSOR FOR SELECT DISTINCT TKR FROM STG_TBL;
DECLARE CONTINUE HANDLER FOR NOT FOUND SET LOOP1_DONE = TRUE;
-- SET VARIABLE VALUES
OPEN CUR1;
CUR1_LOOP: LOOP
FETCH CUR1 INTO VAR_TKR;
IF LOOP1_DONE THEN
CLOSE CUR1;
LEAVE CUR1_LOOP;
END IF;
-- OTHER SELECT STATEMENTS AND CALCULATIONS
BLOCK2: BEGIN
DECLARE LOOP2_DONE BOOLEAN DEFAULT FALSE;
DECLARE CUR1_DATA CURSOR FOR
SELECT TKR_VALUE
FROM STG_VALUE_TBL
WHERE TKR = VAR_TKR
ORDER BY TKR_DATE;
DECLARE CONTINUE HANDLER FOR NOT FOUND SET LOOP2_DONE = TRUE;
OPEN CUR1_DATA;
-- SET VARIABLE VALUES
CUR1_DATA_LOOP: LOOP
FETCH CUR1_DATA INTO TKR_VALUE;
IF LOOP2_DONE THEN
CLOSE CUR1_DATA;
LEAVE CUR1_DATA_LOOP;
END IF;
-- OTHER SELECT STATEMENTS AND CALCULATIONS
END LOOP CUR1_DATA_LOOP;
END BLOCK2;
-- CLOSE CUR1_DATA; <removed as not needed>
END LOOP CUR1_LOOP;
-- CLOSE CUR1; <removed as not needed>
END BLOCK1;
$
DELIMITER;
Please find below table and sample data:
CREATE TABLE STG_TBL
(
ID NUMERIC(38),
TKR VARCHAR(10) NOT NULL
);
INSERT INTO STG_TBL VALUES (100000,'TKR1');
INSERT INTO STG_TBL VALUES (200000,'TKR2');
INSERT INTO STG_TBL VALUES (300000,'TKR3');
COMMIT;
CREATE TABLE STG_VALUE_TBL
(
TKR_DATE DATE,
TKR VARCHAR(10),
TKR_VALUE DECIMAL(20,10),
ADDED_DATE DATE
);
INSERT INTO STG_VALUE_TBL VALUES ('01-01-2015','TKR1','10.231','01-30-2016');
INSERT INTO STG_VALUE_TBL VALUES ('01-02-2015','TKR1','18.151','01-30-2016');
INSERT INTO STG_VALUE_TBL VALUES ('01-03-2015','TKR1','22.952','01-30-2016');
COMMIT;

Related

Return empty table after rollback

Im writing a procedure, I want it to return table if there wasnt any rollbacks, and return empty table / nothing if there was at least 1 rollback.
DELIMITER $$
CREATE PROCEDURE payment(IN amount int, IN profession varchar(50))
BEGIN
DECLARE done BOOL DEFAULT FALSE;
DECLARE salary INT;
DECLARE pes VARCHAR(11);
DECLARE summary INT DEFAULT 0;
DECLARE employee_cursor CURSOR FOR (SELECT RIGHT(PESEL,3), pensja FROM Pracownicy WHERE zawod=profession);
DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = TRUE;
DROP TEMPORARY TABLE IF EXISTS tmp1;
CREATE TEMPORARY TABLE tmp1(pesel char(11), status varchar(20) DEFAULT 'wyplacono');
SET AUTOCOMMIT =0;
START TRANSACTION;
OPEN employee_cursor;
readLoop : LOOP
FETCH employee_cursor INTO pes,salary;
IF done THEN
LEAVE readLoop;
END IF;
SET summary = summary + salary;
IF( summary > amount ) THEN
ROLLBACK;
END IF;
INSERT INTO tmp1(pesel) VALUES(CONCAT('********',pes));
END LOOP;
CLOSE employee_cursor;
COMMIT;
SELECT * from tmp1;
END $$
DELIMITER ;
As far it works fine when it doesnt rollback, but
INSERT INTO tmp1(pesel) VALUES(CONCAT('********',pes));
seems to ignore transaction :/
move the rollback test to outside the loop.

Need help customizing mysql trigger

This is my current trigger:
DELIMITER $$
CREATE DEFINER=`root`#`127.0.0.1` TRIGGER `unique_visit_new_campaign` AFTER INSERT ON `unique_visit` FOR EACH ROW
BEGIN
DECLARE done INT DEFAULT FALSE;
DECLARE pixel_id int;
DECLARE campaign_id varchar(45);
DECLARE cur CURSOR FOR SELECT id FROM pixels;
DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = TRUE;
OPEN cur;
ins_loop: LOOP
FETCH cur INTO pixel_id;
IF done THEN
LEAVE ins_loop;
END IF;
INSERT IGNORE INTO pixels_campaign (campaign_id , pixel_id , date) VALUES (NEW.campaign_id ,pixel_id, current_timestamp);
END LOOP;
CLOSE cur;
END
I need it to NOT TRIGGER when new.campaign_id is empty or equals to the string {campaign_id}
I tried using MySQL IF but with no success.
Also, It kinda auto increment even when there is a campaign id already (when it ignores). any way I can stop that from happening?
Did you try this?
DELIMITER $$
CREATE DEFINER=`root`#`127.0.0.1` TRIGGER `unique_visit_new_campaign` AFTER INSERT ON `unique_visit` FOR EACH ROW
BEGIN
DECLARE done INT DEFAULT FALSE;
DECLARE pixel_id int;
DECLARE campaign_id varchar(45);
DECLARE cur CURSOR FOR SELECT id FROM pixels;
DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = TRUE;
IF new.campaign = '' or new.campaign = '{campaign_id}' or new.campaign is null THEN
OPEN cur;
ins_loop: LOOP
FETCH cur INTO pixel_id;
IF done THEN
LEAVE ins_loop;
END IF;
INSERT IGNORE INTO pixels_campaign (campaign_id , pixel_id , date) VALUES (NEW.campaign_id ,pixel_id, current_timestamp);
END LOOP;
CLOSE cur;
END IF
END

MySQL: Not allowed to return a result set from a trigger

I'm getting "ERROR 1415 (0A000): Not allowed to return a result set from a trigger" when updating a table containing the following trigger, but don't understand why.
CREATE TRIGGER my_trigger AFTER UPDATE ON my_triggering_table
FOR EACH ROW CALL my_procedure();
I'm away that triggers cannot use a SELECT which returns a result set, but the called procedure (and its children) use only CURSOR FOR SELECT and FETCH INTO which, I understand, is permitted. They read, but do not modify, the triggering table.
Can anyone explain the error? (MySQL 5.5) The called procedures below.
CREATE PROCEDURE my_procedure()
BEGIN
DECLARE v_mark VARCHAR(4);
DECLARE v_lat, v_lon DOUBLE;
DECLARE eof INT DEFAULT FALSE;
DECLARE my_cursor CURSOR FOR SELECT `mark`, `lat`, `lon` FROM my_triggering_table ORDER BY `order`;
DECLARE CONTINUE HANDLER FOR NOT FOUND SET eof = TRUE;
DELETE FROM my_output_table;
OPEN my_cursor;
loop1: LOOP
FETCH my_cursor INTO v_mark, v_lat, v_lon;
IF eof THEN
LEAVE loop1;
END IF;
CALL my_procedure_2(v_mark, v_lat, v_lon);
END LOOP;
CLOSE my_cursor;
END//
CREATE PROCEDURE my_procedure_2(IN from_mark VARCHAR(4), IN from_lat DOUBLE, IN from_lon DOUBLE)
BEGIN
DECLARE v_mark VARCHAR(4);
DECLARE v_lat, v_lon DOUBLE;
DECLARE eof INT DEFAULT FALSE;
DECLARE my_cursor CURSOR FOR SELECT `mark`, `lat`, `lon` FROM my_triggering_table ORDER BY `order`;
DECLARE CONTINUE HANDLER FOR NOT FOUND SET eof = TRUE;
OPEN my_cursor;
loop1: LOOP
FETCH my_cursor INTO v_mark, v_lat, v_lon;
IF eof THEN
LEAVE loop1;
END IF;
INSERT INTO my_output_table(`from`, `to`, `dist`, `brg`, `lat`, `lon`)
VALUES(from_mark
, v_mark
, IF(from_mark = v_mark, NULL, getDist(from_lat, from_lon, v_lat, v_lon))
, IF(from_mark = v_mark, NULL, getBearing(from_lat, from_lon, v_lat, v_lon))
, coord_dec2ms(from_lat, true)
, coord_dec2ms(from_lon, false)
);
END LOOP;
CLOSE my_cursor;
END//
The UDFs called do not reference any tables.

Mysql - How to use user defined variables on pointers

I´m new to InnoDB and starting with transactions. I´ve been 24 hours trying to get this to work.
I´m creating an exchange site and really need a transaction to be made. First, make a Select and find some data, and then some updates and inserts according with the results given.
I won´t post the full query as it might be very complicated to read so I created a new query to point out whats bothering.
Table Log
CREATE TABLE `log` (
`num_rows` int(10) unsigned NOT NULL,
`new_value` int(10) unsigned NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
Stored Procedure
DROP PROCEDURE IF EXISTS `test`//
CREATE PROCEDURE `test` (IN var1 BIGINT)
BEGIN
DECLARE done INT DEFAULT 0;
DECLARE result INT;
DECLARE num_rows INT;
DECLARE cur1 CURSOR FOR
SELECT #var1 := #var1 +1 AS result;
DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = 1;
START TRANSACTION;
OPEN cur1;
SELECT FOUND_ROWS() into num_rows;
INSERT INTO log (num_rows,new_value) VALUES (num_rows,var1);
read_loop:
LOOP
FETCH cur1 INTO result;
IF done = 1 THEN
LEAVE read_loop;
END IF;
END LOOP read_loop;
CLOSE cur1;
COMMIT;
END//
When I try
CALL test(1);
Im passing 1 as var1 parameter. So in cur1, the value should be increased. And later insert a new row to the log with the new value. It looks like := asignment isn´t working.
I actually changed
SELECT #var1 := #var1 +1 AS result;
for this
SELECT var1 := var1 +1 AS result;
And get an error on ":= var1 +1"
I understand that the code of the question is an abstraction of the actual code of the stored procedure, so do not quite understand what you need to do, however, a code like this can be helpful.
/* Procedure structure for procedure `test` */
/*!50003 DROP PROCEDURE IF EXISTS `test` */;
DELIMITER $$
CREATE PROCEDURE `test`(IN `var1` BIGINT)
BEGIN
DECLARE `done` TINYINT(1) DEFAULT 0;
DECLARE `result` BIGINT;
DECLARE `_num_rows` INT;
DECLARE `cur1` CURSOR FOR
SELECT SQL_CALC_FOUND_ROWS #`var1` := `var1` + 1;
DECLARE CONTINUE HANDLER FOR NOT FOUND SET `done` := 1;
START TRANSACTION;
OPEN `cur1`;
SET `var1` := #`var1`;
SELECT FOUND_ROWS() INTO `_num_rows`;
INSERT INTO `log` (`num_rows`, `new_value`) VALUES (`_num_rows`, `var1`);
`read_loop`: LOOP
FETCH `cur1` INTO `result`;
IF (`done`) THEN
LEAVE `read_loop`;
END IF;
END LOOP `read_loop`;
CLOSE `cur1`;
COMMIT;
END$$
DELIMITER ;
It is important to indicate the difference between 9.4. User-Defined Variables and routine parameters 13.1.15. CREATE PROCEDURE and CREATE FUNCTION Syntax, are different variables.
SQL Fiddle demo

MySQL Stored Procedure Nested Cursors Error

i am copying data for a Many to Many Relationship table making a Third Table.
The stored procedure currently looks like this but it has some error
DELIMITER $$
CREATE PROCEDURE `test`.UpdateRelatedAccounts()
BEGIN
DECLARE ssn_sel_id VARCHAR(255) DEFAULT 0;
DECLARE id_sel_id CHAR(36) DEFAULT 0;
DECLARE id_sel_rel CHAR(36) DEFAULT 0;
DECLARE no_more_rows BOOLEAN;
DECLARE num_rows INT DEFAULT 0;
DECLARE no_more_rel_rows BOOLEAN;
DECLARE rel_num_rows INT DEFAULT 0;
DECLARE ssn_all_cur CURSOR FOR
SELECT ssn, id FROM ssn WHERE ssn NOT IN ('','000-00-0000');
DECLARE ssn_cur CURSOR FOR
SELECT id FROM ssn WHERE id != id_sel_id AND ssn = ssn_sel_id;
DECLARE CONTINUE HANDLER FOR NOT FOUND SET no_more_rows = TRUE;
-- DECLARE CONTINUE HANDLER FOR NOT FOUND SET no_more_rel_rows = TRUE;
OPEN ssn_all_cur;
SELECT FOUND_ROWS() INTO num_rows;
the_loop: LOOP
FETCH ssn_all_cur
INTO ssn_sel_id, id_sel_id;
IF no_more_rows THEN
CLOSE ssn_all_cur;
LEAVE the_loop;
END IF;
OPEN ssn_cur;
SELECT FOUND_ROWS() INTO rel_num_rows;
the_rel_loop: LOOP
FETCH ssn_cur
INTO id_sel_rel;
IF no_more_rel_rows THEN
CLOSE ssn_cur;
LEAVE the_rel_loop;
END IF;
INSERT INTO `ssn_related` ( `ssn_primary`, `ssn_related` ) VALUES ( id_sel_id, id_sel_rel ), ( id_sel_rel, id_sel_id );
END LOOP the_rel_loop;
END LOOP the_loop;
END$$
DELIMITER ;
How do i nest to use the values and insert into third table.
Cursors are slow and most of the time unnecessary. Nested cursors are slow² and unnecessary². Cursors shall only be used as the last resort, when there's really no other way.
What you want to do can be broken down to this:
INSERT INTO `ssn_related` ( `ssn_primary`, `ssn_related` )
SELECT
ssn_1.id,
ssn_2.id
FROM
ssn ssn_1
INNER JOIN ssn ssn_2 ON ssn_2.ssn = ssn_1.id
WHERE ssn_1.ssn NOT IN ('', '000-00-0000')
AND ssn_2.id != ssn_1.id;
Then you do the same again with swapped columns in the SELECT.
INSERT INTO `ssn_related` ( `ssn_primary`, `ssn_related` )
SELECT
ssn_2.id,
ssn_1.id
FROM
ssn ssn_1
INNER JOIN ssn ssn_2 ON ssn_2.ssn = ssn_1.id
WHERE ssn_1.ssn NOT IN ('', '000-00-0000')
AND ssn_2.id != ssn_1.id;