i have such procedure but all the time i want to execute it i get syntax error near declaring variables... can anybody tell me what i am doint wrong
i have two tables one for questions and one for answers and excel file to migrate data to this tables.
data in excel looks like this:
ID N TITLE
3 99500 question1
4
5 answer1
6 X answer2
7 answer3
DELIMITER $$
create Procedure proc_answermigration()
begin
DECLARE #i,#n,#q,#ind,#pt varchar default '';
DECLARE #done,#aord int default 0;
DECLARE cur cursor for select ID, N, question, from test.qustionmigration;
DECLARE CONTINUE HANDLER FOR NOT FOUND SET #done = 1;
open cur;
read_loop: Loop
fetch cur into i,n,q;
IF done THEN
LEAVE read_loop;
END IF;
if n <> '' or n <> 'X'
then
select #ind = iq.question_id, #pt = iq.points from test.qustionmigration qm
inner join ilias.qpl_questions iq on qm.question = iq.question_text
where question = q
else
insert into qpl_a_sc
(
answer_id,
question_fi,
answertext,
points,
aorder,
tstamp
)
select (select sequence from qpl_a_sc_seq),
ind,
question,
pt,
aord,
'1342884200'
from test.qustionmigration
end if;
update qpl_a_sc_seq
set sequence = sequence + 1;
if #aord = 0 then set #aord = 1;
elseif #aord = 1 then set #aord = 2;
else set #aord = 0;
end loop;
CLOSE cur;
end$$
DELIMITER ;
i corrected some statements but still it has syntax error saying:
#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 'LOOP; close cur; end' at line 52
DELIMITER $$
create Procedure proc_answermigration()
begin
DECLARE i,n,q,ind,pt varchar(500) default '';
DECLARE done,aord,c int default 0;
DECLARE cur cursor for select ID, N, question from test.qustionmigration;
DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = 1;
open cur;
read_loop: LOOP
fetch cur into i,n,q;
IF n <> '' or n <> 'X'
then
select ind = iq.question_id, pt = iq.points from test.qustionmigration qm
inner join ilias.qpl_questions iq on qm.question = iq.question_text
where question = q;
else
insert into qpl_a_sc
(
answer_id,
question_fi,
answertext,
points,
aorder,
tstamp
)
select (select sequence from qpl_a_sc_seq),
ind,
question,
pt,
aord,
'1342884200'
from test.qustionmigration;
end IF;
update qpl_a_sc_seq
set sequence = sequence + 1;
if aord = 0 then set aord = 1;
elseif aord = 1 then set aord = 2;
else set aord = 0;
set c = c + 1;
IF done = 1 THEN
LEAVE read_loop;
END IF;
END LOOP;
close cur;
end$$
DELIMITER ;
Your last IF ELSE block is missing its END IF:
if #aord = 0 then set #aord = 1;
elseif #aord = 1 then set #aord = 2;
else set #aord = 0;
/* END IF either belongs here or after following statements, depending on your intended logic */
/* Either way, this block is unclosed when you close the loop */
end if
When the parser reads the END LOOP;, it is looking for the END IF, and reports a syntax error at LOOP.
You can't DECLARE user variables (those beginning with a #). Just SET them, or else use local variables (not beginning with a #).
Related
I want to search in Wp post(title) column and delete entries which contains words longer then 10 characters but i am unable to find a query to do that. can anyone help?
Edit: I made following SP.
DELIMITER $$
CREATE DEFINER=`root`#`localhost` PROCEDURE `p`(IN `instring` VARCHAR(255))
begin
declare tempstring varchar(10000);
declare idin int;
declare outstring varchar(100);
declare c1 varchar(100);
declare c2 varchar(100);
declare totallength int DEFAULT 0;
declare checkit int;
declare done int;
DECLARE CUR1 CURSOR for SELECT id,post_title FROM wp_posts;
DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = TRUE;
drop table if exists occursresults;
create table occursresults (col1 varchar(20), col2 varchar(20),totallength int );
open CUR1;
read_loop: LOOP
FETCH CUR1 INTO idin,tempstring;
if done then leave read_loop; end if;
set checkit = 0;
looper: while tempstring is not null and instr(tempstring,' ') > 0 do
set checkit = checkit + 1;
if checkit > 100 then #In case of infinite loop
leave looper;
end if;
set outstring = substr(tempstring,1,instr(tempstring, ' ') - 1);
set tempstring = ltrim(rtrim(replace(tempstring,concat(outstring,' '),'')));
set c1 = substr(outstring,1,instr(outstring, ' ') - 1);
set c2 = replace(outstring,concat(c1,' '),'');
if Length(c2) > 10 then
delete from wp_posts where id=idin;
end if;
if Length(c2) < 10 then
INSERT INTO occursresults (COL1,COL2,totallength) VALUES (c1,c2,Length(c2));
end if;
end while;
select tempstring;
set outstring = tempstring;
set c1 = substr(outstring,1,instr(outstring, ' ') - 1);
set c2 = replace(outstring,concat(c1,' '),'');
if Length(c2) > 10 then
delete from wp_posts where id=idin;
end if;
if Length(c2) < 10 then
INSERT INTO occursresults (COL1,COL2,totallength) VALUES (c1,c2,Length(c2));
end if;
end loop;
close cur1;
end$$
DELIMITER ;
but when i call it. i get this error.
Error
Static analysis:
1 errors were found during analysis.
Missing expression. (near "ON" at position 25)
SQL query: Edit Edit
SET FOREIGN_KEY_CHECKS = ON;
MySQL said: Documentation
2014 - Commands out of sync; you can't run this command now
You can use a regex to identify the rows to delete:
DELETE FROM post
WHERE title RLIKE '[a-zA-Z]{10}'
This defines a word as a sequence of alphabetic characters. You might want to adapt the regex to add more characters if needed (digits, underscore, dash, ...).
you can use CHAR_LENGTH as a function to get the length.
Select:
SELECT
*
FROM
post
WHERE
CHAR_LENGTH(title) > 10;
Delete query:
DELETE FROM post
WHERE
CHAR_LENGTH(title) > 10;
Note: LENGTH function too works but it will calculate in bytes rather than chars more info on this refer this MySQL - length() vs char_length()
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 ;
We are using the following stored procedure and all the mentioned tables are using "Collation = utf8_general_ci" Still we are getting this error:
Error Code: 1267. Illegal mix of collations (utf8_general_ci,IMPLICIT) and (utf8_unicode_ci,IMPLICIT) for operation '='
Store Procedure is:
DELIMITER $$
CREATE DEFINER=`root`#`localhost` PROCEDURE `AssignCallRates`()
begin
declare countrycode varchar(8000);
declare countryname varchar(8000);
declare currencycode varchar(8000);
declare priceval varchar(8000);
declare mobileprice varchar(8000);
declare landprice varchar(8000);
declare reccnt int;
DECLARE done INT DEFAULT FALSE;
declare country_cursor cursor for select country_code,country_name from dialoone_countries;
declare aud_cursor cursor for select convert(price,char) as price from tbl_rate_aud where quick_search=1 and trim(substring_index(`place`,'-',1)) = countryname LIMIT 0,2;
declare euro_cursor cursor for select convert(price,char) as price from tbl_rate_euro where quick_search=1 and trim(substring_index(`place`,'-',1)) = countryname LIMIT 0,2;
declare gbp_cursor cursor for select convert(price,char) as price from tbl_rate_gbp where quick_search=1 and trim(substring_index(`place`,'-',1)) = countryname LIMIT 0,2;
declare usd_cursor cursor for select convert(price,char) as price from tbl_rate_dollar where quick_search=1 and trim(substring_index(`place`,'-',1)) = countryname LIMIT 0,2;
declare continue handler for not found set done=TRUE;
truncate table tbl_rates;
open country_cursor;
CountryLOOP: loop
fetch country_cursor into countrycode,countryname;
if done=TRUE then
close country_cursor;
leave CountryLOOP;
end if;
set mobileprice = "";
set landprice="";
set reccnt = 0;
set priceval = "";
open aud_cursor;
AUDLOOP: loop
fetch aud_cursor into priceval;
if done = TRUE then
set done = FALSE;
close aud_cursor;
leave AUDLOOP;
end if;
set reccnt = reccnt + 1;
if reccnt = 1 then
set landprice=priceval;
end if;
if reccnt = 2 then
set mobileprice=priceval;
end if;
end loop AUDLOOP;
insert into tbl_rates (country_code,currency_code,mobile,land) values (countrycode,"AUD",mobileprice,landprice);
set mobileprice = "";
set landprice="";
set reccnt = 0;
set priceval = "";
open euro_cursor;
EUROLOOP: loop
fetch euro_cursor into priceval;
if done = TRUE then
set done = FALSE;
close euro_cursor;
leave EUROLOOP;
end if;
set reccnt = reccnt + 1;
if reccnt = 1 then
set landprice=priceval;
end if;
if reccnt = 2 then
set mobileprice=priceval;
end if;
end loop EUROLOOP;
insert into tbl_rates (country_code,currency_code,mobile,land) values (countrycode,"EUR",mobileprice,landprice);
set mobileprice = "";
set landprice="";
set reccnt = 0;
set priceval = "";
open gbp_cursor;
GBPLOOP: loop
fetch gbp_cursor into priceval;
if done = TRUE then
set done = FALSE;
close gbp_cursor;
leave GBPLOOP;
end if;
set reccnt = reccnt + 1;
if reccnt = 1 then
set landprice=priceval;
end if;
if reccnt = 2 then
set mobileprice=priceval;
end if;
end loop GBPLOOP;
insert into tbl_rates (country_code,currency_code,mobile,land) values (countrycode,"GBP",mobileprice,landprice);
set mobileprice = "";
set landprice="";
set reccnt = 0;
set priceval = "";
open usd_cursor;
USDLOOP: loop
fetch usd_cursor into priceval;
if done = TRUE then
set done = FALSE;
close usd_cursor;
leave USDLOOP;
end if;
set reccnt = reccnt + 1;
if reccnt = 1 then
set landprice=priceval;
end if;
if reccnt = 2 then
set mobileprice=priceval;
end if;
end loop USDLOOP;
insert into tbl_rates (country_code,currency_code,mobile,land) values (countrycode,"USD",mobileprice,landprice);
end loop CountryLOOP;
select "Query Executed Successfully";
end$$
DELIMITER ;
Any updation needed to this SP?
From other answer: The default collation for stored procedure parameters is utf8_general_ci and you can't mix collations, so that means either database / tables are probably unicode.
First Try this:
SELECT ##collation_database;
Then look into the CREATE statement for the actual tables you are using.
More Info
I tried to code a simple nested loop as a mysql block. The server got me a syntax error, but i can't find it.
Does anybody see it?
The error message was:
Query: END LOOP get_invoice
Error Code: 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 'END LOOP get_invoice' at line 1
BEGIN
DECLARE v_id INT DEFAULT 0;
DECLARE v_finished1 INT DEFAULT 0;
DECLARE invoices_cursor CURSOR FOR
SELECT id_invoice FROM invoice i WHERE invoice_type = 'RE' AND EXISTS (SELECT 1 FROM invoice ma WHERE invoice_type = 'MA' AND ma.origin = i.id_invoice);
DECLARE CONTINUE HANDLER
FOR NOT FOUND SET v_finished1 = 1;
OPEN invoices_cursor;
get_invoice: LOOP
FETCH invoices_cursor INTO v_id;
IF v_finished1 = 1 THEN
CLOSE invoices_cursor;
LEAVE get_invoice;
END IF;
DECLARE v_finished2 INT DEFAULT 0;
DECLARE v_dunning_level INT DEFAULT 1;
DECLARE dunning_cursor CURSOR FOR
SELECT id_invoice FROM invoice ma WHERE invoice_type = 'MA' AND ma.origin = v_id ORDER BY `create` ASC;
DECLARE CONTINUE HANDLER
FOR NOT FOUND SET v_finished2 = 1;
OPEN dunning_cursor;
get_dunnings: LOOP
DECLARE v_id_dun BIGINT DEFAULT NULL;
FETCH dunning_cursor INTO v_id_dun;
IF v_finished = 1 THEN
LEAVE get_dunnings;
END IF;
UPDATE invoice SET dunning_level = v_dunning_level WHERE invoice_type = 'MA' AND id_invoice = v_id_dun;
SET v_dunning_level = v_dunning_level + 1;
END LOOP get_dunnings ;
CLOSE dunning_cursor;
END LOOP get_invoice ;
END;
I have the following bunch of code trying to update a field using 2 cursors the one inside the other. I use the first cursor just to get an id value (1st cursor) and then I get a list of other id values based on that id (2nd cursor). The problem is that the result set from the 2nd cursor contains the last id twice! I can't find the bug! Something in the loop, something in the termination variable for the 2 cursors?
Any help more than welcome! Thanks in advance!
DELIMITER $$
DROP PROCEDURE IF EXISTS updateNumberOfPoisForPlacesWithChildren$$
CREATE PROCEDURE updateNumberOfPoisForPlacesWithChildren()
BEGIN
DECLARE single_place_id INT(11);
DECLARE single_unique_parents_id INT(11);
DECLARE done, temp_number_of_pois, sum_number_of_pois INT DEFAULT 0;
DECLARE unique_parents_ids CURSOR FOR SELECT DISTINCT `parent_id` FROM `places` WHERE `parent_id` IS NOT NULL;
DECLARE temp_places_ids CURSOR FOR SELECT `id` FROM `places` WHERE `parent_id` = single_unique_parents_id;
DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = 1;
OPEN unique_parents_ids;
main_loop_for_parent_ids : LOOP
SET sum_number_of_pois = 0;
IF done = 1 THEN
CLOSE unique_parents_ids;
LEAVE main_loop_for_parent_ids;
END IF;
IF NOT done = 1 THEN
FETCH unique_parents_ids INTO single_unique_parents_id;
OPEN temp_places_ids;
main_loop_for_places : LOOP
IF done = 1 THEN
CLOSE temp_places_ids;
LEAVE main_loop_for_places;
END IF;
IF NOT done = 1 THEN
FETCH temp_places_ids INTO single_place_id;
SELECT COUNT(`id`) INTO temp_number_of_pois FROM `pois` WHERE `place_id` = single_place_id;
SET sum_number_of_pois = sum_number_of_pois + temp_number_of_pois;
END IF;
END LOOP;
UPDATE `places` SET `number_of_pois`=sum_number_of_pois WHERE `id` = single_unique_parents_id;
END IF;
END LOOP;
END$$
DELIMITER ;
I think your problem is about here...
IF NOT done = 1 THEN
FETCH temp_places_ids INTO single_place_id;
SELECT COUNT(`id`) INTO temp_number_of_pois FROM `pois` WHERE `place_id` = single_place_id;
SET sum_number_of_pois = sum_number_of_pois + temp_number_of_pois;
END IF;
The FETCH sets DONE to be 1 when it exhausts the result set, but you proceed because you've already passed the DONE test.
Perhaps...
FETCH temp_places_ids INTO single_place_id;
IF NOT done = 1 THEN
SELECT COUNT(`id`) INTO temp_number_of_pois FROM `pois` WHERE `place_id` = single_place_id;
SET sum_number_of_pois = sum_number_of_pois + temp_number_of_pois;
END IF;