Mysql loop and insert - mysql

I have the following MySql script:
SET #skip = 0;
SET #max = (SELECT COUNT(*) FROM table1);
CREATE TEMPORARY TABLE TempTable(
id INT NOT NULL,
name VARCHAR(32) NOT NULL
);
loop1: LOOP
INSERT INTO TempTable (id, name) SELECT id, name FROM table1 LIMIT #skip, 1;
IF #skip < #max THEN
SET #skip = #skip + 1;
ITERATE loop1;
END IF;
LEAVE loop1;
END LOOP loop1;
SELECT * FROM TempTable;
This script is not working but it should select all the id and names in table1. I am using a loop because I am also going to do other stuff in those loops but that is for later.
I am not looking for a solution like SELECT id, name FROM table1 but I want my error fixed. So I can continue with my loop.
The error I get is:
1064 - You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use
near 'loop1: LOOP INSERT INTO TempTable (id, name) SELECT id, name
FROM table1' at line 1

/* set delimiter */
DELIMITER $$
/* remove procedure if exists... */
DROP PROCEDURE IF EXISTS insert_it $$
/* create procedure */
CREATE PROCEDURE insert_it ()
BEGIN
DECLARE varcount INT DEFAULT 1;
DECLARE varmax INT DEFAULT 15;
WHILE varcount <= varmax DO
INSERT INTO yourtable(fixed_val, count_val) VALUES(3493, varcount);
SET varcount = varcount + 1;
END WHILE;
END $$
/* reset delimiter back to normal */
DELIMITER ;
/* call procedure */
CALL insert_it();

try something like this for the syntax of your loop:
DECLARE #count INT;
DECLARE #max INT;
SET #count=1;
SET #max= (SELECT COUNT(*) FROM table1);
WHILE(#count < #max)
BEGIN
/*your database query logic*/
END
use "SET #count=(#count+1)" to increment your counter within the loop

There is a syntax error in your code (the LIMIT #skip which is dynamic SQL and requires some tricks to make it work) but it is not at loop1: LOOP.
My guess is you are trying to use LOOP outside a compound statement (BEGIN ... END) like a stored procedure, which is not possible. You have to create a stored procedure to do that.

Related

Nested Cursor Declare Issue Mysql

I'm trying to make a Nested Cursor in Mysql by following this instruction.
Then i got this issue:
#1064 - You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'DECLARE activityids CURSOR FOR SELECT activity_id FROM #_activity;
END BLOCK2;' at line 22
I've 2 table 'account' and 'n_activity' (n = account_id in table 'account')
Ex: i've table 'account' and '20_activity'.
So i want to loop the 'account_id' and get the 'activity_id' from that loop.
Here is my code:
DROP PROCEDURE if exists update_schema_activity_startdate_and_duedate;
DELIMITER $$
CREATE PROCEDURE update_schema_activity_startdate_and_duedate()
BEGIN
DECLARE done INT DEFAULT FALSE;
DECLARE accountid INT;
--
-- GET ALL ACCOUNT ID
--
DECLARE accountids CURSOR FOR SELECT account_id FROM account;
--
-- LOOP
--
OPEN accountids;
read_loop: LOOP
FETCH accountids INTO accountid;
BLOCK2: BEGIN
SET #_activity = CONCAT(accountid,'_activity');
DECLARE activityids CURSOR FOR SELECT activity_id FROM #_activity;
END BLOCK2;
END LOOP;
CLOSE accountids;
END$$
DELIMITER ;
CALL update_schema_activity_startdate_and_duedate();
Please help, thanks.

End while loop missing semicolon

I created a simple stored procedure that loops through rows of one table and inserts them into another. For some reason the END WHILE loop is throwing a missing semicolon error. All the code looked right to me, and all the delimiters were set up right. I just can't figure out why it would be throwing these errors, googling this problem only pointed me to improperly used delimiter answers, but nothing more. Any help would be nice!
USE test;
DELIMITER $$
DROP PROCEDURE IF EXISTS `testLoop`$$
CREATE PROCEDURE `testLoop`()
BEGIN
DECLARE n INT DEFAULT 0;
DECLARE i INT DEFAULT 0;
SELECT COUNT(*) FROM `test_dropship_upload` INTO n;
SET i=0;
WHILE i<n DO
INSERT INTO `test_2` (sku, qty) VALUES(sku, qty) FROM `test_dropship_upload` LIMIT i,1;
SET i = i + 1;
END WHILE;
END $$
DELIMITER ;
When I am stuck with a problem in a large block of code and can't find where the problem is, I usually split my code in smaller chunks and test them one at a time:
Test 1:
DELIMITER $$
DROP PROCEDURE IF EXISTS `testLoop`$$
CREATE PROCEDURE testLoop()
BEGIN
END $$
DELIMITER ;
No errors: procedure declaration and use of delimiters is OK.
Test 2:
DELIMITER $$
DROP PROCEDURE IF EXISTS `testLoop`$$
CREATE PROCEDURE `testLoop`()
BEGIN
DECLARE n INT DEFAULT 0;
DECLARE i INT DEFAULT 0;
END $$
DELIMITER ;
No errors: the declaration of variables within the procedure is OK.
Test 3:
DELIMITER $$
DROP PROCEDURE IF EXISTS `testLoop`$$
CREATE PROCEDURE `testLoop`()
BEGIN
DECLARE n INT DEFAULT 0;
DECLARE i INT DEFAULT 0;
SELECT COUNT(*) FROM `test_dropship_upload` INTO n;
SET i=0;
END $$
DELIMITER ;
No errors: the SELECT query and the variable assignment are OK.
Test 4:
DELIMITER $$
DROP PROCEDURE IF EXISTS `testLoop`$$
CREATE PROCEDURE `testLoop`()
BEGIN
DECLARE n INT DEFAULT 0;
DECLARE i INT DEFAULT 0;
SELECT COUNT(*) FROM `test_dropship_upload` INTO n;
SET i=0;
WHILE i<n DO
SET i = i + 1;
END WHILE;
END $$
DELIMITER ;
No errors: the WHILE loop is OK.
Test 5:
The only untested part is now the INSERT query:
INSERT INTO `test_2` (sku, qty) VALUES(sku, qty) FROM `test_dropship_upload` LIMIT i,1;
Looking a the documentation for INSERT and INSERT ... SELECT, we can see that your query is not valid: it is apparently missing a SELECT part and shouldn't have a VALUES part if you want to insert values from another table:
DELIMITER $$
DROP PROCEDURE IF EXISTS `testLoop`$$
CREATE PROCEDURE `testLoop`()
BEGIN
DECLARE n INT DEFAULT 0;
DECLARE i INT DEFAULT 0;
SELECT COUNT(*) FROM `test_dropship_upload` INTO n;
SET i=0;
WHILE i<n DO
INSERT INTO `test_2` (sku, qty) SELECT sku, qty FROM `test_dropship_upload` LIMIT i, 1;
SET i = i + 1;
END WHILE;
END $$
DELIMITER ;
The procedure creation now completes without errors.
Test 6:
However, you will get a syntax error on the SELECT query when executing the procedure: MySQL doesn't accept using LIMIT with a variable.
To make it work, you need to use a prepared statement.
PREPARE stmt FROM "INSERT INTO `test_2` (sku, qty) SELECT sku, qty FROM `test_dropship_upload` LIMIT ?, 1";
EXECUTE stmt using #i;
DEALLOCATE PREPARE stmt;
It is also not allowed to used local variables in prepared statements:
Because local variables are in scope only during stored program
execution, references to them are not permitted in prepared statements
created within a stored program. Prepared statement scope is the
current session, not the stored program, so the statement could be
executed after the program ends, at which point the variables would no
longer be in scope. For example, SELECT ... INTO local_var cannot be
used as a prepared statement. This restriction also applies to stored
procedure and function parameters.
To circumvent this problem, use a session variable #i instead of your local variable i:
Final version of the procedure:
DELIMITER $$
DROP PROCEDURE IF EXISTS `testLoop`$$
CREATE PROCEDURE `testLoop`()
BEGIN
DECLARE n INT DEFAULT 0;
SELECT COUNT(*) FROM `test_dropship_upload` INTO n;
SET #i=0;
WHILE #i<n DO
PREPARE stmt FROM "INSERT INTO `test_2`(sku, qty) SELECT sku, qty FROM `test_dropship_upload` LIMIT ?, 1";
EXECUTE stmt USING #i;
DEALLOCATE PREPARE stmt;
SET #i = #i + 1;
END WHILE;
END $$
DELIMITER ;
You can apply the same method to debug many complex programming problems: start with a simple version of your code, test it. If it works test again with a more code, if not locate and fix the errors before continuing.

procedure, setting variable, repeat until, substring from one variable, mysql

I am looking for help with my sql procedure.
I would like to substring in loop each username, and alias from two input arguments and add it into table users. I have two procedures.
Sorry for Polish variable names and procedure names.
My first procedure is
CREATE DEFINER=`root`#`localhost` PROCEDURE `dodajZawodnika`(IN `dane` VARCHAR(50), IN `wyswietlanie` VARCHAR(50))
NO SQL
BEGIN
IF (SELECT 1 = 1 from zawodnicy where danezawodnika = dane AND dowyswietlenia=wyswietlanie) THEN
BEGIN
Select id from zawodnicy where danezawodnika=dane AND dowyswietlenia=wyswietlanie;
END;
ELSE
BEGIN
Insert INTO zawodnicy (danezawodnika, dowyswietlenia) VALUES(dane, wyswietlanie);
SELECT last_insert_id() AS ID;
END;
END IF;
END;
My second procedure is
CREATE DEFINER=`root`#`localhost` PROCEDURE `stworzSklad`(IN `dane` VARCHAR(1500), IN `pseudo` VARCHAR(1000))
NO SQL
BEGIN
DECLARE counter INTEGER;
DECLARE zawodnik VARCHAR(1500);
DECLARE pseudonim VARCHAR(1000);
DECLARE zawodnicy VARCHAR(1500);
DECLARE pseudonimy VARCHAR(1000);
DECLARE exit handler for sqlexception
BEGIN
-- ERROR
ROLLBACK;
END;
DECLARE exit handler for sqlwarning
BEGIN
-- WARNING
ROLLBACK;
END;
set counter = 0;
set #zawodnicy = dane;
set #pseudonimy = psuedo;
select #zawodnicy, #pseudonimy;
REPEAT
set zawodnik=(SELECT TRIM(SUBSTRING_INDEX(#zawodnicy, ',', 1)));
set pseudonim=(SELECT TRIM(SUBSTRING_INDEX(#pseudonimy, ',', 1)));
call dodajZawodnika(zawodnik, pseudonim);
SELECT RIGHT(#zawodnicy, TRIM(length(#zawodnicy) - length(SUBSTRING_INDEX(#zawodnicy, ',', 1)) - 1)) into #zawodnicy;
SELECT RIGHT(#pseudonimy, TRIM(length(#pseudonimy) - length(SUBSTRING_INDEX(#pseudonimy, ',', 1)) - 1)) into #pseudonimy;
select zawodnik as 'zawodnik', pseudonim as 'pseudonim', dane as 'dane', pseudo as 'pseudo', #zawodnicy as 'zawodnicy', #pseudonimy as 'pseudonimy';
set counter = counter + 1;
UNTIL (#zawodnicy = '' or counter = 30)
END REPEAT;
select counter;
END
I am fighting with it from about 2 hours.
I would like to use also transaction for this insert.
Please help me with this little problem.
How to make this in proper way?
Now, calling stworzSklad procedure make endless loop (ofc without counter in until condition) and any of user was not inserted in my table.
Cheers!

Mysql stored procedure multiple selects

I am running a stored procedure. The issue seems to be that it will go into the if statement. Also for some reason or another regardless of how many selects I use it will only return the first. I've copied this from another stored procedure that works like a charm, but this one just won't go. Any ideas?
DROP PROCEDURE IF EXISTS genSelPriceTier;
DELIMITER $$
CREATE PROCEDURE genSelPriceTier(tier_id INT, default_id INT)
BEGIN
DECLARE rowCount INT DEFAULT 0;
SELECT * FROM price_tier WHERE price_tier_id = tier_id;
SET rowCount = FOUND_ROWS();
IF rowCount < 1 THEN
SELECT * FROM price_tier WHERE price_tier_id = default_id;
END IF;
END$$
DELIMITER ;
There is a bug reported related to the usage of FOUND_ROWS(). So, I recommend using Count(*) for the number of rows returned. Something like the following should work.
DROP PROCEDURE IF EXISTS genSelPriceTier;
DELIMITER $$
CREATE PROCEDURE genSelPriceTier(tier_id INT, default_id INT)
BEGIN
DECLARE rowCount INT DEFAULT 0;
SELECT COUNT(*) INTO rowCount FROM price_tier WHERE price_tier_id = tier_id
IF rowCount < 1 THEN
SELECT * FROM price_tier WHERE price_tier_id = default_id;
END IF;
END$$
DELIMITER ;

MySQL Syntax Error In Variable Declaration

I have the following MySQL query:
DELIMITER //
CREATE PROCEDURE InsertResult (IN winnerID INT, IN loserID INT)
BEGIN
INSERT INTO KomperResult (WinnerID, LoserID) VALUES (#winnerID, #loserID);
DECLARE winnerScore, loserScore INT;
SELECT Score INTO #winnerScore FROM KomperPerson WHERE ID = #winnerID;
SELECT Score INTO #loserScore FROM KomperPerson WHERE ID = #loserID;
IF (#loserScore >= #winnerScore) THEN UPDATE KomperPerson SET Score = #loserScore + 1 WHERE ID = #winnerID; END IF;
END//
I get an error on:
DECLARE winnerScore, loserScore INT;
What am I doing wrong?
DECLAREs need to go on the first line of your procedure.
From the docs:
DECLARE is permitted only inside a
BEGIN ... END compound statement and
must be at its start, before any other
statements.