sql >> Database >  >> RDS >> Mysql

Hoe kan ik door alle rijen van een tabel lopen? (MySQL)

Aangezien de suggestie van een lus het verzoek om een ​​oplossing van het proceduretype impliceert. Hier is de mijne.

Elke query die werkt op een enkele record die uit een tabel is gehaald, kan worden verpakt in een procedure om deze door elke rij van een tabel te laten lopen, zoals:

Verwijder eerst alle bestaande procedures met dezelfde naam en wijzig het scheidingsteken zodat uw SQL niet elke regel probeert uit te voeren terwijl u de procedure probeert te schrijven.

DROP PROCEDURE IF EXISTS ROWPERROW;
DELIMITER ;;

Dan is hier de procedure volgens uw voorbeeld (table_A en table_B gebruikt voor de duidelijkheid)

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

Vergeet dan niet het scheidingsteken te resetten

DELIMITER ;

En voer de nieuwe procedure uit

CALL ROWPERROW();

Je kunt doen wat je wilt op de regel "INSERT INTO" die ik eenvoudig heb gekopieerd van je voorbeeldverzoek.

Let er VOORZICHTIG op dat de hier gebruikte regel "INSERT INTO" de regel in de vraag weerspiegelt. Volgens de opmerkingen bij dit antwoord moet u ervoor zorgen dat uw query syntactisch correct is voor welke versie van SQL u ook gebruikt.

In het eenvoudige geval waarin uw ID-veld wordt opgehoogd en begint bij 1 zou de regel in het voorbeeld kunnen worden:

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

De regel "SELECT COUNT" vervangen door

SET n=10;

Hiermee kunt u uw zoekopdracht alleen testen op de eerste 10 records in table_A.

Nog een ding. Dit proces is ook heel gemakkelijk in verschillende tabellen te nesten en het was de enige manier waarop ik een proces op één tabel kon uitvoeren die dynamisch verschillende aantallen records in een nieuwe tabel invoegde uit elke rij van een bovenliggende tabel.

Als je het nodig hebt om sneller te werken, probeer het dan op basis van een set te maken, zo niet, dan is dit prima. Je zou het bovenstaande ook in cursorvorm kunnen herschrijven, maar het kan de prestaties niet verbeteren. bijv.:

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

Vergeet niet om de variabelen die je gaat gebruiken te declareren als hetzelfde type als die uit de opgevraagde tabellen.

Mijn advies is om zoveel mogelijk met set-based queries te werken, en alleen simpele loops of cursors te gebruiken als dat nodig is.



  1. Proactieve MySQL-bewaking (Developer Studio/Advisors Angle)

  2. Python- en SQLite-waarschuwingen

  3. PostgreSQL:Hoe stel ik het zoekpad in op gebruikersniveau?

  4. Microsoft Access versus SQL Server