首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 更多程式語言 >> 程式設計綜合問答

MySQL 儲存過程語法錯誤修正:游標嵌套、處理器衝突、變數宣告順序

     編輯:程式設計綜合問答

原始錯誤

[Err] 1064 - You have an error in your SQL syntax; 
near 'DECLARE cursor_company CURSOR FOR SELECT company FROM test WHERE status =' at line 10

主要問題

  1. 變數宣告順序錯誤:MySQL 要求 **所有 `DECLARE` 必須在 `BEGIN` 直後、任何陳述式之前**,且順序:變數 → 條件/處理器 → 游標。
  2. 重複宣告 `CONTINUE HANDLER`**:同一 `BEGIN...END` 區塊只能有一個相同條件的處理器,外層與內層游標共用 `SQLSTATE '02000'` 會衝突。
  3. 游標宣告位置:內層游標 `cursor_name` 宣告在迴圈內部,MySQL 不支援動態位置宣告,必須提至頂部。
  4. 迴圈變數 `a` 未宣告:外層 `WHILE a<>1` 但 `a` 只在處理器賦值,未 `DECLARE`。
  5. `ELSEIF` 語法錯誤**:`END ELSEIF` 應為 `END IF`,巢狀 `IF` 需正確閉合。

修正後完整代碼

CREATE PROCEDURE test()
BEGIN
    -- 1. 所有變數先宣告
    DECLARE fid INT;
    DECLARE days INT DEFAULT 1;
    DECLARE s INT DEFAULT 0;
    DECLARE a INT DEFAULT 0;              -- 外層游標結束標記
    DECLARE company_code VARCHAR(50);     -- 指定長度
    
    -- 2. 兩個游標都在這裡宣告
    DECLARE cursor_company CURSOR FOR 
        SELECT company FROM test WHERE status = 3;
    DECLARE cursor_name CURSOR FOR 
        SELECT id FROM test 
        WHERE UNIX_TIMESTAMP(check_time) < UNIX_TIMESTAMP(DATE_ADD(NOW(), INTERVAL -days DAY));
    
    -- 3. 單一處理器 (無法區分兩游標,需改用標記變數)
    DECLARE CONTINUE HANDLER FOR NOT FOUND SET s = 1; -- 通用 NOT FOUND
    
    OPEN cursor_company;
    FETCH cursor_company INTO company_code;
    
    WHILE s <> 1 DO
        -- 依公司設定天數
        IF company_code = 'DD' THEN SET days = 2;
        ELSEIF company_code = 'ZD' THEN SET days = 5;
        ELSEIF company_code = 'GG' THEN SET days = 8;
        END IF;
        
        FETCH cursor_company INTO company_code;
        
        -- 內層游標處理
        OPEN cursor_name;
        FETCH cursor_name INTO fid;
        SET s = 0; -- 重置內層標記
        
        WHILE s <> 1 DO
            UPDATE test SET status = 8 WHERE id = fid;
            FETCH cursor_name INTO fid;
        END WHILE;
        
        CLOSE cursor_name;
    END WHILE;
    
    CLOSE cursor_company;
END

關鍵修正說明

  • 所有 `DECLARE` 集中在開頭,順序:變數 → 游標 → 處理器。
  • 單一 `NOT FOUND` 處理器配合 `s` 標記區分內外層 (每開啟內層游標前 `SET s=0`)。
  • `VARCHAR` 必須指定長度 (如 `VARCHAR(50)`)。
  • `ELSEIF` 正確閉合為 `END IF`。

效能建議

游標逐行處理極慢,若資料量大請改用 **單一 SQL 陳述式**:

UPDATE test 
SET status = 8 
WHERE id IN (
    SELECT t2.id FROM test t2
    JOIN test t1 ON t1.company = t2.company
    WHERE t1.status = 3
      AND UNIX_TIMESTAMP(t2.check_time) < UNIX_TIMESTAMP(DATE_ADD(NOW(), INTERVAL - 
        CASE t1.company 
            WHEN 'DD' THEN 2 
            WHEN 'ZD' THEN 5 
            WHEN 'GG' THEN 8 
            ELSE 1 
        END DAY))
);
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved