sql >> Databáze >  >> RDS >> Mysql

Připravené prohlášení MySQL - Jak procházet

Jak již naznačili ostatní, obvykle se vyhýbáme procházením sady výsledků RBAR (řádek po agonizujícím řádku) především z důvodu výkonu. Jen si nechceme zvyknout procházet sadu výsledků. Ale to není odpověď na otázku, kterou jste položili.

Abychom odpověděli na otázku, kterou jste položili, zde je základní příklad programu uloženého v MySQL, který používá CURSOR k individuálnímu zpracování řádků vrácených dotazem. MySQL nepodporuje anonymní bloky, takže jediný způsob, jak to udělat, je v programu uloženém v MySQL, jako je PROCEDURE

DELIMITER $$

CREATE PROCEDURE loop_through_var_list
BEGIN
   DECLARE done INT DEFAULT 0;
   DECLARE v_id INT DEFAULT NULL;  
   DECLARE csr_var_list CURSOR FOR SELECT id FROM var_list ORDER BY id;
   DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = 1;
   OPEN csr_var_list;
   get_id: LOOP
      FETCH csr_var_list INTO v_id; 
      IF done = 1 THEN
         LEAVE get_id;
      END IF;

      -- at this point, we have an id value in v_id, so we can do whatever
      SET @s1 = CONCAT('SELECT ... WHERE id =''', v_id, ''' ...');


   END LOOP get_id;
   CLOSE csr_var_list;
END$$

DELIMITER ;

Postup provedení:

CALL loop_through_var_list();

POZNÁMKY:Syntaxe pro zpracování CURSORu v MySQL je docela odlišná od jiných databází.

Abychom získali "smyčku", musíme použít LOOP ... END LOOP konstrukce.

Aby však tato smyčka neběžela navždy, potřebujeme příkaz LEAVE, který nám umožní smyčku opustit.

K určení, kdy odejít, používáme podmíněný test. V tomto příkladu chceme skončit poté, co dokončíme zpracování posledního řádku.

FETCH se chystá vyvolat výjimku, když již nejsou k načtení žádné další řádky.

Tuto výjimku „zachytíme“ v POKRAČOVACÍM HANDLER (z nějakého tajemného důvodu musí „obslužné rutiny“ do posledního deklarovaného obsahu; MySQL vyvolá chybu, pokud se pokusíme deklarovat něco za HANDLER (jiný než jiný HANDLER.)

Když MySQL vyvolá výjimku „žádné další řádky“, spustí se kód handleru. V tomto příkladu pouze nastavujeme proměnnou (s názvem done ) na hodnotu.

Vzhledem k tomu, že se jedná o obslužnou rutinu „pokračování“, zpracování začne zpět od příkazu, kde byla vyvolána výjimka, v tomto případě to bude příkaz následující po FETCH. Takže první věc, kterou uděláme, je zkontrolovat, zda jsme "hotoví" nebo ne. Pokud jsme "hotoví", opustíme smyčku a zavřeme kurzor.

Jinak víme, že máme id hodnota z var_list uloženy v proměnné procedury s názvem v_id . Takže teď si můžeme dělat, co chceme. Vypadá to, že chcete vložit nějaký text SQL do uživatelem definované proměnné (včetně hodnoty v_id do textu SQL, pak PREPARE, EXECUTE a DEALLOCATE PREPARE.

Nezapomeňte deklarovat v_id proměnná s příslušným datovým typem, který odpovídá datovému typu id v var_list , právě jsem předpokládal, že je to INT.

Když se dostaneme na konec smyčky, MySQL se "zacyklí" zpět na začátek smyčky a jedeme znovu.

V těle smyčky budete pravděpodobně chtít CONCAT v_id do textu SQL, který chcete spustit. Vypadá to, že už máte připravenou přípravu PŘIPRAVIT, ROZDĚLIT. Pro testování můžete chtít přidat klauzuli LIMIT na SELECT v deklaraci kurzoru a poté provést jednoduchý SELECT v_id; v těle jen pro ověření funkčnosti smyčky, než přidáte další kód.

NÁSLEDOVAT

Chtěl jsem zmínit další alternativní přístup k úkolu, tj. spuštění řady příkazů na základě šablony, nahrazování hodnot poskytnutých jedním příkazem SQL select...

Pokud bych měl například tuto šablonu:

SELECT * 
  INTO OUTFILE '/tmp/[email protected]'
  FIELDS TERMINATED BY ',' ENCLOSED BY '"'
  LINES TERMINATED BY '\n'
FROM data 
WHERE id = @ID
ORDER BY 1 

a potřeboval jsem nahradit výskyty @ID konkrétní hodnotou id ze seznamu vráceného z příkazu SELECT, např.

SELECT id
  FROM var_list
 WHERE id IS NOT NULL
 GROUP BY id

Pravděpodobně bych nepoužil program uložený v MySQL se smyčkou CURSOR, použil bych jiný přístup.

Použil bych příkaz SELECT ke generování sady příkazů SQL, které by mohly být provedeny. Za předpokladu id je celočíselný typ, pravděpodobně bych udělal něco takového:

SELECT CONCAT(' SELECT * 
                   INTO OUTFILE ''/tmp/orders_',s.id,'.csv''
                   FIELDS TERMINATED BY '','' ENCLOSED BY ''"''
                   LINES TERMINATED BY ''\n''
                FROM data
               WHERE id = ',s.id,'
               ORDER BY 1;') AS `stmt`
 FROM ( SELECT v.id
          FROM var_list v
         WHERE v.id IS NOT NULL
         GROUP BY v.id
      ) s
ORDER BY s.id

Pro každou hodnotu id vráceno z s , příkaz vrací text příkazu SQL SELECT, který se může (a musí) provést. Když to zachytím do textového souboru, získám skript SQL, který bych mohl spustit.



  1. SQL databáze s proměnným počtem sloupců

  2. Nástroj pro import CSV souborů do databáze MySQL?

  3. Příklady LOG10() v SQL Server

  4. Najděte skupinu záznamů, které odpovídají více hodnotám