正如其他人已經建議,我們通常避免主要出於性能原因循環結果集RBAR(行激動行)。我們只是不想養成循環結果集的習慣。但是這並不能回答你問的問題。
要回答你問的問題,這裏有一個MySQL存儲程序的基本例子,它使用CURSOR來單獨處理查詢返回的行。 MySQL不支持匿名塊,所以要做到這一點的唯一方法是在MySQL存儲程序,像一個過程
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 ;
要執行的過程:
CALL loop_through_var_list();
注:爲處理語法MySQL中的CURSOR與其他數據庫有很大不同。
要獲得「循環」,我們需要使用LOOP ... END LOOP
結構。
但是爲了防止循環永久運行,我們需要一個LEAVE語句來允許我們退出循環。
我們使用條件測試來確定何時離開。在這個例子中,我們希望在處理完最後一行後退出。
FETCH
將在沒有更多行被提取時拋出異常。我們在CONTINUE HANDLER中「捕捉」了異常(出於一些神祕的原因,「處理程序」必須聲明最後的東西;如果我們試圖在HANDLER之後聲明某些東西(如另一個HANDLER除外),則MySQL會拋出錯誤。 )
當MySQL拋出「沒有更多的行」異常,觸發該處理程序代碼。在這個例子中,我們只是一個變量(命名爲done
)設定的值。
因爲它是一個「繼續「處理程序,處理在引發異常的語句處開始備份,在這種情況下,這將是FETCH後面的語句,因此,我們所做的第一件事是檢查我們是否」完成「。 '回覆「完成」,然後我們退出循環,並關閉光標。
否則,我們知道存儲在名爲v_id
的過程變量中的id
值爲var_list
。所以現在我們可以做任何我們想要的。看起來您想將一些SQL文本放入用戶定義的變量中(包括v_id的值到SQL文本中,然後是PREPARE,EXECUTE和DEALLOCATE PREPARE)
請務必聲明v_id
變量數據類型,它與var_list
中的id
列的數據類型匹配,我剛纔假設它是一個INT。
當我們到達循環結尾時,MySQL「循環」回到循環的開始處,並關閉我們再去
在循環的主體中,很可能你會想要將CONCAT v_id添加到你想要執行的SQL文本中,看起來你已經有了處理PREPARE,DEALLOCATE準備。對於測試,您可能希望在遊標聲明中的SELECT上添加一個LIMIT子句,然後執行一個簡單的SELECT v_id;在正文中,只是爲了驗證循環是否正常工作,然後添加更多代碼。
隨訪
我想提另一種替代的方法來工作,即運行一系列基於模板的語句,從單個SQL SELECT語句提供的值代...
舉例來說,如果我有這樣的模板:
SELECT *
INTO OUTFILE '/tmp/[email protected]'
FIELDS TERMINATED BY ',' ENCLOSED BY '"'
LINES TERMINATED BY '\n'
FROM data
WHERE id = @ID
ORDER BY 1
,我需要更換OCC從SELECT語句返回的列表中帶有特定id值的@ID的urrences,例如
SELECT id
FROM var_list
WHERE id IS NOT NULL
GROUP BY id
我可能不會使用帶有CURSOR循環的MySQL存儲程序,我會使用不同的方法。
我會利用SELECT語句來生成一組可以執行的SQL語句。假設id
是整數類型,我可能會做這樣的事情:
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
對於來自s
返回的id
每一個值,該語句返回SQL SELECT語句可能(並且需要)執行的文本。將其捕獲到文本文件中會給我一個我可以運行的SQL腳本。
你究竟想要完成什麼?一般來說,儘量遠離循環概念,因爲遊標速度非常慢。如果您要返回var_list表中的數據表結果,請改用「JOIN」。 – sgeddes 2014-09-11 04:11:46
我需要導出一系列的CSV報告,我有爲每個ID編寫的查詢,但我有大約50個循環。 – Atari2600 2014-09-11 04:13:06
我需要循環準備好的語句。 – Atari2600 2014-09-11 04:15:18