2011-10-07 5 views
10

Je souhaite utiliser LIMIT dans un curseur. Le curseur doit être utilisé et mis à jour plusieurs fois dans une boucle, chaque fois avec différents paramètres de LIMIT. Voici un code:Curseur dynamique dans la procédure stockée

DELIMITER $$ 
CREATE PROCEDURE `updateIt`() READS SQL DATA 
BEGIN 

declare done int(1) default 0; 
declare counter int(10) default 0; 
declare xabc int(10) default 0; 

declare tab1Cursor cursor for select abc from tab1 limit 100000*counter, 100000; 
declare continue handler for not found set done=1; 

loopCounter: LOOP 
    set done = 0; 
    open tab1Cursor; 
    igmLoop: loop 
     fetch tab1Cursor into xabc; 
     if done = 1 then leave igmLoop; end if; 
     -- do something 
    end loop igmLoop; 
    close tab1Cursor; 

    if (counter = 1039) 
     leave loopCounter; 
    end if; 
    set counter = counter + 1; 

END LOOP loopCounter; 
END $$ 
DELIMITER ; 

Ceci, cependant, ne fonctionne pas (j'ai aussi essayé avec le curseur dans la boucle counterLoop). Mysql peut-il gérer les curseurs dynamiques?

Répondre

11

De l'MySQL Manual

un curseur ne peut pas être utilisé pour une déclaration dynamique qui est préparée et exécutée avec PREPARE et EXECUTE. L'instruction pour un curseur est vérifiée au moment de la création du curseur, de sorte que l'instruction ne peut pas être dynamique.

Cependant il y a 2 façons. Le premier est pour les cas où absolument un seul utilisateur à la fois exécutera la procédure. Une instruction de préparation peut être utilisée pour créer une vue avec le SQL dynamique et le curseur peut sélectionner à partir de cette vue nommée statiquement. Il n'y a presque aucun impact sur les performances. Malheureusement, ces vues sont également visibles pour les autres utilisateurs (une vue temporaire n'existe pas), cela ne fonctionnera donc pas pour plusieurs utilisateurs.

De manière analogue, une table temporaire peut être créée dans l'instruction prepare et le curseur peut sélectionner dans la table temporaire. Seule la session en cours peut voir une table temporaire, de sorte que le problème de plusieurs utilisateurs est résolu. Mais cette solution peut avoir un impact significatif sur les performances, car une table temporaire doit être créée chaque fois que le processus s'exécute.

Conclusion: Nous avons encore besoin de curseurs pour pouvoir être créés dynamiquement!

Voici un exemple d'utilisation en vue de passer le nom de la table et le nom de la colonne dans un curseur de la mysql forums

DELIMITER // 
DROP PROCEDURE IF EXISTS test_prepare// 

CREATE PROCEDURE test_prepare(IN tablename varchar(255), columnname varchar(50)) 
BEGIN 
DECLARE cursor_end CONDITION FOR SQLSTATE '02000'; 
DECLARE v_column_val VARCHAR(50); 
DECLARE done INT DEFAULT 0; 
DECLARE cur_table CURSOR FOR SELECT * FROM test_prepare_vw; 
DECLARE CONTINUE HANDLER FOR cursor_end SET done = 1; 

SET @query = CONCAT('CREATE VIEW test_prepare_vw as select ', columnname, ' from ', tablename); 
select @query; 
PREPARE stmt from @query; 
EXECUTE stmt; 
DEALLOCATE PREPARE stmt; 

OPEN cur_table; 
FETCH cur_table INTO v_column_val; 
WHILE done = 0 DO 
SELECT v_column_val; 
FETCH cur_table INTO v_column_val; 
END WHILE; 
CLOSE cur_table; 

DROP VIEW test_prepare_vw; 

END; 
// 

DELIMITER ; 
+0

Merci. Cela pourrait fonctionner pour mon problème. J'essaie ça. – Marcus

+1

mille merci @ Pentium10 – gca

+1

La majeure partie de cette réponse semble être plagarized de http://forums.mysql.com/read.php?61,116597,226041 Peut-être que l'attribution appropriée serait appropriée. – Rob

Questions connexes