I’m going crazy with this stored procedure.
I post the complete dump hoping someone could explain my mistake.
drop table if exists questions;
create table questions (
id int not null auto_increment primary key,
description varchar(200)
) engine = myisam;
insert into questions (description)
values
('Question 1'),
('Question 2'),
('Question 3');
drop table if exists answers;
create table answers (
id int not null auto_increment primary key,
question_id int,
description varchar(10)
) engine = myisam;
insert into answers (question_id,description)
values
(1,'no'),
(1,'no'),
(1,'yes'),
(1,'no'),
(1,'yes'),
(2,'no'),
(2,'yes'),
(2,'yes'),
(2,'yes'),
(2,'no'),
(2,'no'),
(2,'no'),
(2,'yes'),
(2,'no'),
(3,'no'),
(3,'no'),
(3,'no'),
(3,'yes');
This is my stored procedure:
delimiter //
drop procedure if exists dynamic_view //
create procedure dynamic_view()
begin
declare cnt int default 0;
declare finito int default 0;
declare qid int;
declare qdescription varchar(100);
declare qanswer varchar(100);
declare i int default 1;
declare j int;
declare str varchar(20000) default '';
declare str2 varchar(20000);
declare str3 varchar(20000);
declare curs1 cursor for select id,description from questions order by id;
declare curs2 cursor for select description from answers where question_id = qid;
declare continue handler for not found set finito = 1;
-- drop table if exists tmp;
select count(*) as num into @cnt from answers group by question_id order by num desc limit 1;
drop table if exists tmp;
while i <= @cnt do
set str = concat(str,'answer',i,' varchar(10),');
set i = i + 1;
end while;
set str = substr(str,1,char_length(str)-1);
set @str = concat('create temporary table tmp (id int,question varchar(200),',str,');');
prepare stmt from @str;
execute stmt;
deallocate prepare stmt;
open curs1;
mio_loop:loop
fetch curs1 into qid,qdescription;
if finito = 1 then
close curs1;
leave mio_loop;
end if;
open curs2;
set str2 = 'insert into tmp (id,question,';
set j = 1;
set str3 = '';
mio_loop2:loop
fetch curs2 into qanswer;
if finito = 1 then set finito = 0;
close curs2;
leave mio_loop2;
end if;
set str2 = concat(str2,'answer',j,',');
set str3 = concat(str3,"'",qanswer,"',");
set j = j + 1;
end loop mio_loop2;
set str2 = substr(str2,1,char_length(str2)-1);
set str3 = substr(str3,1,char_length(str3)-1);
set @str2 = concat(str2,') values (',qid,",'",qdescription,"',",str3,');');
prepare stmt from @str2;
execute stmt;
deallocate prepare stmt;
end loop mio_loop;
select * from tmp;
end; //
delimiter ;
and when i call it I get this output
mysql> call dynamic_view();
+------+------------+---------+---------+---------+---------+---------+---------+---------+---------+---------+
| id | question | answer1 | answer2 | answer3 | answer4 | answer5 | answer6 | answer7 | answer8 | answer9 |
+------+------------+---------+---------+---------+---------+---------+---------+---------+---------+---------+
| 1 | Question 1 | no | no | yes | no | yes | NULL | NULL | NULL | NULL |
| 2 | Question 2 | no | yes | yes | yes | no | no | no | yes | no |
| 3 | Question 3 | no | no | no | yes | NULL | NULL | NULL | NULL | NULL |
+------+------------+---------+---------+---------+---------+---------+---------+---------+---------+---------+
3 rows in set (0.23 sec)
Now let’s suppose that I delete a record that has question_id = 2.
This is the id that has the maximum number of records, that is 9. If I delete it the records become 8, so last column MUST disappeared.
delete from answers where id = 14;
If I recall my sp I get this error:
Error Code : 1054
Unknown column 'pivot.tmp.answer9' in 'field list'
However, if I execute again the whole code of the stored procedure and then I recall it I get the correct result:
mysql> call dynamic_view();
+------+------------+---------+---------+---------+---------+---------+---------+---------+---------+
| id | question | answer1 | answer2 | answer3 | answer4 | answer5 | answer6 | answer7 | answer8 |
+------+------------+---------+---------+---------+---------+---------+---------+---------+---------+
| 1 | Question 1 | no | no | yes | no | yes | NULL | NULL | NULL |
| 2 | Question 2 | no | yes | yes | yes | no | no | no | yes |
| 3 | Question 3 | no | no | no | yes | NULL | NULL | NULL | NULL |
+------+------------+---------+---------+---------+---------+---------+---------+---------+---------+
3 rows in set (0.19 sec)
I can’t understand why since I drop the temporary table. Thanks in advance.
edit. I wanted to start a bounty but I don’t find the button. 🙂
I’ve just read on meta that I can start a bounty only after two days. Never noted it. Hope someone could help me the same 🙂
Once I saw similar question. Have a look at this link – unable to add columns dynamically to table using alter
Nick, I’d suggest you to use prepared statement to output data from temporary table (…this table was created with prepared statement in the SP, and this looks like a bug – SELECT * inside PROCEDURE gives “Unknown column” on second loop if tbl changed).
Just change last line –
with this code –