2016-05-29 150 views
0

我正在使用存儲的過程來插入和更新一些刮取的數據到表中。邏輯非常簡單。MySQL存儲過程。 /唯一鍵衝突

  • 檢查表中是否存在匹配值。
  • 如果是 - 更新賠率。
  • 如果否 - 插入數據。

我用下面的源代碼:

DECLARE match_id bigint; 
SET match_id = -1; 
SELECT id INTO match_id FROM scrape_initial_horses sih 
    WHERE `time` = event_time 
    AND `track_name` = event_track 
    and `date` = event_date 
    and `participant_name` = participant_name 
    and `bookmaker_name` = provider 
    and `betting_type` = offer_type LIMIT 1; 

# Here I am placing a debug statements showing me the raw data and match_id. 

IF match_id = -1 THEN 
    insert into `scrape_initial_horses` (`time`, `track_name`, `date`, `participant_name`, `odds`, `bookmaker_name`, `betting_type`) 
    values (event_time, event_track, event_date, participant_name, offer_odds, provider, offer_type); 
ELSE 
    UPDATE scrape_initial_horses sih SET sih.odds = offer_odds where id = match_id; 
end IF; 
END 

我進一步對覆蓋列在表中的唯一關鍵:time, track_name, date, participant_name, bookmaker_name, betting_type

我遇到的問題是,match_Id經常看起來與具有不同參與者ID的記錄匹配,因此不正確的行被更新而不是被插入的新行。 我有雙倍和高音檢查,唯一的關鍵是在位。在設置爲3個查詢之前,我有一個查詢風格

Insert into ... on duplicate key update ...

這有完全相同的效果。我錯過了什麼?

我也在InnoDB和MyISAM表之間切換,重新創建表。我在Centos 6服務器上運行MySQL 5.7。我的理解是,變量應該只能在運行存儲過程的線程中訪問,但要麼不是這種情況,要麼我對數據表的唯一性做了一些其他不正確的假設。

回答

1

我懷疑你所缺少的是在MySQL存儲程序中,局部變量優先於列名。

如果participant_name是列的兩個名字,一個局部變量的名字,那麼這個:

and `participant_name` = particpant_name 

將執行局部變量的局部變量的比較。列中的值不會被引用。

這只是一個猜測,因爲發佈在問題中的代碼不足以讓我們做出決定。 (我們沒有看到任何聲明的局部變量,也沒有看到表格定義。)

最佳做法是以合格列引用與表名或表別名。另外,請考慮命名過程和局部變量,以便名稱不與列名衝突。

SELECT sih.`id` INTO match_id 
    FROM `scrape_initial_horses` sih 
    WHERE sih.`time`    = v_event_time 
     AND sih.`track_name`  = v_event_track 
     AND sih.`date`    = v_event_date 
     AND sih.`participant_name` = v_participant_name 
     AND sih.`bookmaker_name` = v_provider 
     AND sih.`betting_type`  = v_offer_type 
    LIMIT 1;