хранимая процедура с динамическим представлением не обновляет количество полей - PullRequest
0 голосов
/ 15 августа 2011

Я схожу с ума от этой хранимой процедуры.Я публикую полный дамп, надеясь, что кто-нибудь сможет объяснить мою ошибку.

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');

Это моя хранимая процедура:

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 ;

, и когда я ее вызываю, я получаю этот вывод

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)

Теперь давайте предположим, что я удаляю запись, у которой question_id = 2. Это идентификатор с максимальным количеством записей, то есть 9. Если я удаляю его, записи становятся 8, поэтому последний столбец ДОЛЖЕН исчезнуть.

delete from answers where id = 14;

Если я вспоминаю свой sp, я получаю эту ошибку:

Error Code : 1054
Unknown column 'pivot.tmp.answer9' in 'field list'

Однако, если я снова выполню весь код хранимой процедуры, а затем вспомню его, я получу правильный результат:

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)

Я не могу понять почему, так как я удаляю временную таблицу.Заранее спасибо.редактировать.Я хотел начать щедрость, но не могу найти кнопку.:)

Я только что прочитал на мета, что я могу начать награду только через два дня.Никогда этого не замечал.Надеюсь, кто-нибудь может помочь мне так же:)

1 Ответ

1 голос
/ 18 августа 2011

Однажды я увидел похожий вопрос. Посмотрите на эту ссылку - невозможно динамически добавить столбцы в таблицу, используя alter

Ник, я бы посоветовал вам использовать подготовленный оператор для вывода данных из временной таблицы (... эта таблица была создана с подготовленным оператором в SP, и это похоже на ошибку - SELECT * внутри PROCEDURE дает «Неизвестный столбец» во втором цикле, если tbl изменилось ).

Просто измените последнюю строку -

select * from tmp';

с этим кодом -

PREPARE stmt FROM 'select * from tmp';
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...