sql >> Databasteknik >  >> RDS >> Mysql

Hur kan jag gå igenom alla rader i en tabell? (MySQL)

Eftersom förslaget om en loop innebär en begäran om en lösning av procedurtyp. Här är min.

Alla frågor som fungerar på en enskild post från en tabell kan lindas in i en procedur för att få den att köras genom varje rad i en tabell så här:

Ta först bort en befintlig procedur med samma namn och ändra avgränsaren så att din SQL inte försöker köra varje rad när du försöker skriva proceduren.

DROP PROCEDURE IF EXISTS ROWPERROW;
DELIMITER ;;

Här är proceduren enligt ditt exempel (tabell_A och tabell_B används för tydlighetens skull)

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

Glöm sedan inte att återställa avgränsaren

DELIMITER ;

Och kör den nya proceduren

CALL ROWPERROW();

Du kan göra vad du vill på raden "INSERT INTO" som jag helt enkelt kopierade från din exempelförfrågan.

Notera NOGA att raden "INSERT INTO" som används här speglar raden i frågan. Enligt kommentarerna till det här svaret måste du se till att din fråga är syntaktisk korrekt för vilken version av SQL du än kör.

I det enkla fallet där ditt ID-fält ökas och börjar på 1 kan raden i exemplet bli:

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

Ersätter raden "SELECT COUNT" med

SET n=10;

Låter dig endast testa din fråga på de första 10 posterna i tabell_A.

En sista sak. Denna process är också mycket lätt att kapsla över olika tabeller och var det enda sättet jag kunde utföra en process på en tabell som dynamiskt infogade olika antal poster i en ny tabell från varje rad i en överordnad tabell.

Om du behöver att den ska köras snabbare så försök att göra den inställningsbaserad, om inte så är det bra. Du kan också skriva om ovanstående i markörform men det kanske inte förbättrar prestandan. t.ex.:

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

Kom ihåg att deklarera variablerna du kommer att använda som samma typ som de från de efterfrågade tabellerna.

Mitt råd är att använda uppsättningsbaserade frågor när du kan, och bara använda enkla loopar eller markörer om du måste.



  1. FORALL-uttalande med VALUES-OF Bound-klausul i Oracle Database

  2. Frågan tar timeout när den körs från webben, men supersnabb när den körs från SSMS

  3. Oracle SQL pivotfråga

  4. Android :Fel vid kopiering av databas (Sqliite) från tillgångsmapp