Mysql
 sql >> Database >  >> RDS >> Mysql

Come posso scorrere tutte le righe di una tabella? (MySQL)

Poiché il suggerimento di un ciclo implica la richiesta di una soluzione di tipo procedura. Ecco il mio.

Qualsiasi query che funzioni su un singolo record preso da una tabella può essere racchiusa in una procedura per farla eseguire in ogni riga di una tabella in questo modo:

Per prima cosa elimina qualsiasi procedura esistente con lo stesso nome e cambia il delimitatore in modo che il tuo SQL non tenti di eseguire ogni riga mentre stai tentando di scrivere la procedura.

DROP PROCEDURE IF EXISTS ROWPERROW;
DELIMITER ;;

Quindi ecco la procedura come nel tuo esempio (tabella_A e tabella_B usate per chiarezza)

CREATE PROCEDURE ROWPERROW()
BEGIN
DECLARE n INT DEFAULT 0;
DECLARE i INT DEFAULT 0;
SELECT COUNT(*) FROM table_A INTO n;
SET i=0;
WHILE i<n DO 
  INSERT INTO table_B(ID, VAL) SELECT (ID, VAL) FROM table_A LIMIT i,1;
  SET i = i + 1;
END WHILE;
End;
;;

Quindi non dimenticare di reimpostare il delimitatore

DELIMITER ;

Ed esegui la nuova procedura

CALL ROWPERROW();

Puoi fare quello che vuoi alla riga "INSERT INTO" che ho semplicemente copiato dalla tua richiesta di esempio.

Nota ATTENTAMENTE che la riga "INSERT INTO" utilizzata qui rispecchia la riga nella domanda. Secondo i commenti a questa risposta, devi assicurarti che la tua query sia sintatticamente corretta per qualsiasi versione di SQL in esecuzione.

Nel semplice caso in cui il tuo campo ID viene incrementato e inizia da 1 la riga nell'esempio potrebbe diventare:

INSERT INTO table_B(ID, VAL) VALUES(ID, VAL) FROM table_A WHERE ID=i;

Sostituendo la riga "SELECT COUNT" con

SET n=10;

Ti consentirà di testare la tua query solo sui primi 10 record nella tabella_A.

Un'ultima cosa. Questo processo è anche molto facile da annidare su tabelle diverse ed era l'unico modo in cui potevo eseguire un processo su una tabella che inserisse dinamicamente diversi numeri di record in una nuova tabella da ogni riga di una tabella padre.

Se hai bisogno che funzioni più velocemente, prova a impostarlo in base, in caso contrario va bene. Puoi anche riscrivere quanto sopra sotto forma di cursore ma potrebbe non migliorare le prestazioni. es:

DROP PROCEDURE IF EXISTS cursor_ROWPERROW;
DELIMITER ;;

CREATE PROCEDURE cursor_ROWPERROW()
BEGIN
  DECLARE cursor_ID INT;
  DECLARE cursor_VAL VARCHAR;
  DECLARE done INT DEFAULT FALSE;
  DECLARE cursor_i CURSOR FOR SELECT ID,VAL FROM table_A;
  DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = TRUE;
  OPEN cursor_i;
  read_loop: LOOP
    FETCH cursor_i INTO cursor_ID, cursor_VAL;
    IF done THEN
      LEAVE read_loop;
    END IF;
    INSERT INTO table_B(ID, VAL) VALUES(cursor_ID, cursor_VAL);
  END LOOP;
  CLOSE cursor_i;
END;
;;

Ricordati di dichiarare le variabili che utilizzerai come dello stesso tipo di quelle delle tabelle interrogate.

Il mio consiglio è di utilizzare query basate su set quando puoi e di utilizzare semplici loop o cursori solo se necessario.