2011-10-07 6 views
10

Vorrei utilizzare LIMIT in un cursore. Il cursore dovrebbe essere usato e aggiornato più volte all'interno di un ciclo, ogni volta con diversi parametri di LIMIT. Qui codice:Cursore dinamico in stored procedure

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 ; 

Questo, tuttavia, non funziona (ho anche provato con il cursore nella LOOP counterLoop). Mysql può gestire i cursori dinamici?

risposta

11

Dal MySQL Manual

un cursore non può essere utilizzato per un'istruzione dinamica che è preparato e eseguita con preparazione ed esecuzione. L'istruzione per un cursore è selezionata al momento della creazione del cursore, quindi l'istruzione non può essere dinamica.

Tuttavia ci sono 2 modi.

Il primo è per i casi in cui solo un utente alla volta eseguirà la procedura. È possibile utilizzare un'istruzione preparativa per creare una vista con l'SQL dinamico e il cursore può selezionare da questa vista con nome statico. Non c'è quasi nessun impatto sulle prestazioni. Sfortunatamente, queste visualizzazioni sono visibili anche ad altri utenti (non esiste una vista temporanea), quindi questo non funzionerà per più utenti.

Analogamente, una tabella temporanea può essere creata nell'istruzione prepar e il cursore può selezionare dalla tabella temporanea. Solo la sessione corrente può visualizzare una tabella temporanea, quindi il problema relativo a più utenti viene risolto. Ma questa soluzione può avere un impatto significativo sulle prestazioni dal momento che una tabella temporanea deve essere creata ogni volta che viene eseguito il proc.

Bottom line: abbiamo ancora bisogno di cursori per poter essere creati dinamicamente!

Ecco un esempio di utilizzo, al fine di passare il nome della tabella e il nome della colonna in un cursore dal 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

Grazie. Potrebbe funzionare per il mio problema. Ci provo. – Marcus

+1

mila grazie @ Pentium10 – gca

+1

La maggior parte di questa risposta sembra essere plagiata da http://forums.mysql.com/read.php?61,116597,226041 Forse l'appropriata attribuzione sarebbe appropriata. – Rob