Mysql stored procedure giving error at runtime - mysql

I have created a stored procedure in Mysql, as :
delimiter $$
drop procedure if exists test9$$
Create procedure test9(test_type varchar(20))
Reads sql data
begin
Declare 1_id int;
Declare 1_date varchar(20);
Declare done int default 0;
Declare cur1 cursor for
select id,name from buyers where ticket_type='test_type';
Declare Continue handler for not found set done=1;
Create temporary table if not exists ticketninja.history2(n_id int,n_date varchar(20));
Open cur1;
hist_loop:loop
fetch cur1 into 1_id,1_date;
if done=1 then
leave hist_loop;
end if;
insert into ticketninja.history2(n_id ,n_date) values(1_id,1_date);
End loop hist_loop;
close cur1;
select * from history2;
drop table history2;
End;
$$
delimiter ;
but when i call it using,
call test9('platinum');
it returns an error saying :
#1312 - PROCEDURE ticketninja.test1 can't return
a result set in the given context
what i am doing wrong here?

I think you need an OUT variable (see first code sample here)

Related

MySQL8 Procedure - Use Parameters in Cursor

I'm trying to use input parameters of a stored procedure within a cursor of the procedure.
Calling the procedure as follows results in an Error
-- -role- -table- -cond-
CALL grantRoleToUsersFromWhere('Student', 'studenten', true);
Error Code: 1146. Table 'uni4.utable' doesn't exist
This tells me that the parameter 'userTable' was not written to the variable 'uTable' OR 'uTable' is not recognized as a variable at all by the cursor Statement.
I tried different approaches storing / using the parameters. e.g. use them directly or store them in a Variable with a SET statement. However, if I try to use SET uTable=userTable; before the cursor declaration, MySQL WorkBench won't accept the Procedure declaration.
I spent quite some time on this but I think I'm missing an important yet simple part :-)
DROP PROCEDURE IF EXISTS grantRoleToUsersFromWhere;
DELIMITER $$
CREATE DEFINER=`root`#`localhost` PROCEDURE grantRoleToUsersFromWhere(IN grantRole VARCHAR(30), IN userTable VARCHAR(30), IN addCondition VARCHAR(50))
BEGIN
DECLARE workUser VARCHAR(30) default '';
DECLARE gRole VARCHAR(30) default grantRole;
DECLARE uTable VARCHAR(30) default userTable;
DECLARE aCond VARCHAR(50) default addCondition;
DECLARE cur1 CURSOR FOR SELECT Name FROM uTable WHERE aCond;
OPEN cur1;
read_loop: LOOP
FETCH cur1 INTO workUser;
GRANT gRole TO workUser;
END LOOP;
CLOSE cur1;
END $$
DELIMITER ;
Create dynamic cursors directly is not possible. You can however use VIEW's to achieve the same thing. See sample.
CREATE PROCEDURE p1 (select_statement VARCHAR(255))
BEGIN
DECLARE v1,v2 VARCHAR(255);
DECLARE c CURSOR FOR SELECT * FROM t;
SET #v = CONCAT('create temporary table t as ',select_statement);
PREPARE stmt1 FROM #v;
EXECUTE stmt1;
OPEN c;
FETCH c INTO v1,v2;
SELECT v1,v2;
END//
' DECLARE cur1 CURSOR FOR SELECT Name FROM uTable WHERE aCond;' is not possible mysql does not do variable substitution (for table name). Your read loop is infinite because you don't declare a continuation handler and test for not found in the read loop.

Get Columns Single Record in Stored Procedure Mysql

I have my procedure and is working, but my question is the following,
with the cursor is working correctly, but before the cursor I need a Single Record with several columns, I donĀ“t know if I need another cursor just for one record.
Which would be the right way to get the columns of that single row without a cursor.
The query to execute is:
'SELECT id,anio,fec_iniciointeres FROM mytable WHERE id=3 '
DELIMITER $$
DROP PROCEDURE IF EXISTS db.cal_intereses$$
CREATE DEFINER=`root`#`localhost` PROCEDURE `cal_intereses`()
BEGIN
DECLARE factura_id INT UNSIGNED;
DECLARE val_avaluo DECIMAL(16,2);
DECLARE fec_actual DATE;
DECLARE done INT;
DECLARE cur CURSOR FOR SELECT fac_facturas.id AS factura_id, fac_facturas.val_avaluo FROM fac_facturas WHERE fac_facturas.vigencia_id<=26 AND fac_facturas.estado=1 AND fac_facturas.val_avaluo>0 LIMIT 10;
DECLARE CONTINUE HANDLER FOR NOT FOUND SET done=1;
SET fec_actual=(SELECT CURDATE());
SET done = 0;
OPEN cur;
ciclo: LOOP
FETCH cur INTO factura_id,val_avaluo;
IF done=1 THEN LEAVE ciclo; END IF;
DELETE FROM val_interesaux;
IF fec_actual>='2006-07-29' THEN
INSERT INTO val_interesaux(factura_id,fec_inicio) VALUES(factura_id,fec_actual);
END IF;
END LOOP ciclo;
CLOSE cur;
END$$
DELIMITER ;

Cursor incorrect integer value error

I am trying to make my first cursor in MySQL and I am receiving an error. It says incorrect integer value. I was thinking this would grab the value in row one from column customer_Id, and store it into the IdValue variable. How do I code this correctly and fix this error?
DELIMITER $$
CREATE PROCEDURE CursorProcedure()
BEGIN
DECLARE IdValue int;
DECLARE myCursor CURSOR FOR
SELECT customer_Id FROM customers;
OPEN myCursor;
FETCH myCursor INTO IdValue;
CLOSE myCursor;
SELECT IdValue;
END$$
DELIMITER ;
DROP PROCEDURE IF EXISTS CursorProcedure;
DELIMITER $$
CREATE PROCEDURE CursorProcedure()
BEGIN
DECLARE done INT DEFAULT FALSE;
DECLARE IdValue int;
DECLARE myCursor CURSOR FOR SELECT customer_Id FROM customers;
DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = TRUE;
OPEN myCursor;
read_loop: LOOP
FETCH myCursor INTO IdValue;
IF done THEN
LEAVE read_loop;
END IF;
--
-- YOU ARE IN YOUR READ LOOP
-- DO SOMETHING WITH IT HERE
--
END LOOP;
CLOSE myCursor;
END$$
DELIMITER ;
But in the "do something with it here", don't do a SELECT on it because it will generate multiple result sets. Do something meaningful.
Manual page on Cursors.
As an aside, cursors are rarely your friends. They are extremely slow. Use them in dire emergencies only.

Cursor in Procedure does not return any values

I have a database where temp tables are created, those table names are randomly generated and saved in Checkouts.unid. I want to drop all those tables and truncate the table Checkouts. I thought the niftiest solution would be a procedure, but it will not work:
DROP PROCEDURE IF EXISTS `spCheckoutsCleanup`;
CREATE PROCEDURE `spCheckoutsCleanup` ()
SQL SECURITY INVOKER
BEGIN
DECLARE `t` VARCHAR(64);
DECLARE `ch` CURSOR FOR SELECT `unid` FROM `Checkouts`;
OPEN `ch`;
drop_tables: LOOP
FETCH `ch` INTO `t`;
DROP TABLE IF EXISTS `t`;
END LOOP;
CLOSE `ch`;
TRUNCATE TABLE `Checkouts`;
END
I always get "No data - zero rows fetched, selected, or processed" although those tables are there and the table Checkouts is not empty though.
You have to add something like this in order to end your loop:
DECLARE CONTINUE HANDLER FOR NOT FOUND SET ...;
See example in the documentation.. E.g. ...
DROP PROCEDURE IF EXISTS `spCheckoutsCleanup`;
CREATE PROCEDURE `spCheckoutsCleanup` ()
SQL SECURITY INVOKER
BEGIN
DECLARE done INT DEFAULT FALSE;
DECLARE `t` VARCHAR(64);
DECLARE `ch` CURSOR FOR SELECT `unid` FROM `Checkouts`;
DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = TRUE;
OPEN `ch`;
drop_tables: LOOP
FETCH `ch` INTO `t`;
IF done THEN
LEAVE drop_tables;
END IF;
DROP TABLE IF EXISTS `t`;
END LOOP;
CLOSE `ch`;
TRUNCATE TABLE `Checkouts`;
END
Otherwise you will get an error once you reached the end of your cursor.
I got it working with this:
DROP PROCEDURE IF EXISTS `spCheckoutsCleanup`;
CREATE PROCEDURE `spCheckoutsCleanup` ()
SQL SECURITY INVOKER
BEGIN
DECLARE done int DEFAULT 0;
DECLARE t CHAR(64);
DECLARE ch CURSOR FOR SELECT `unid` FROM `Checkouts`;
DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = 1;
OPEN ch;
drop_table: LOOP
FETCH ch INTO t;
IF done = 1 THEN
LEAVE drop_table;
END IF;
SET #sql := CONCAT('DROP TABLE IF EXISTS `', t, '`');
PREPARE dropt FROM #sql;
EXECUTE dropt;
END LOOP;
CLOSE ch;
TRUNCATE TABLE `Checkouts`;
END;
CALL spCheckoutsCleanup;

prepared statement in stored procedure not refreshing

Using a dynamically created view WITHIN a Loop in this MySQL stored procedure. The problem I'm having is the contents of temp_controller_view view only reflect the result from the view's first creation (e.g. first loop) as if the statement CREATE OR REPLACE VIEW isn't being read.
Obviously I'm trying to get the view to update upon each Looping so that I can work with the contents of the dynamic view
MYSQL ##VERSION > 5.1.61
DROP procedure if exists SITETOEPRISE;
DELIMITER //
CREATE PROCEDURE SITETOEPRISE()
BEGIN
DECLARE bDone INT;
DECLARE sid int(11); -- or approriate type
DECLARE curr_site_db VARCHAR(10);
DECLARE Var3 VARCHAR(50);
DECLARE site_curs CURSOR FOR SELECT siteid FROM sites;
DECLARE CONTINUE HANDLER FOR NOT FOUND SET bDone = 1;
OPEN site_curs;
SET bDone = 0;
site_loop : LOOP
FETCH site_curs INTO sid;
IF bDone THEN
CLOSE site_curs;
LEAVE site_loop;
END IF;
select sid as 'sid_in_loop';
SET #dyn_sql = CONCAT('CREATE OR REPLACE VIEW `temp_controller_view` AS SELECT * from site',sid,'.controller;');
select #dyn_sql;
PREPARE stmt_dyn_view FROM #dyn_sql;
EXECUTE stmt_dyn_view;
DEALLOCATE PREPARE stmt_dyn_view;
select * from temp_controller_view;
drop view temp_controller_view;
END LOOP;
END
//
DELIMITER ;