2009-07-15 30 views
0

我正試圖在mysql中實現「IF記錄EXISTS THEN UPDATE ELSE INSERT」。具體來說,我必須弄清楚如何使用Doctrine ORM來做到這一點。你可以用「IF」開始mysql語句嗎?

使用本機MySql的一個解決方案是使用「ON DUPLICATE KEY UPDATE」。原則中不支持這一點。

另一個半解決方案是使用「REPLACE INTO」語法。 Doctrine支持這一點,但REPLACE不會更新記錄,而是刪除記錄並創建一個新記錄(使用新的自動增量ID)。正因爲如此,如果您像我一樣依賴於自動增量ID,那麼這是一個糟糕的解決方案。

我試圖操作的表是INNODB,所以我研究了事務,但是我不完全理解在事務內部應用相同的規則是否適用於它們之外。

我可以說「IF(INSERT IGNORE INTO critical_id = $ id)然後在交易中退出ELSE(UPDATE表SET field ='new_value')」嗎?

如果我不能說這樣的話,有沒有解決這個問題的方法?

回答

1

要麼找到一種方法,使「對重複​​密鑰更新」的工作,或改用兩種說法:首先選擇找到的任何現有行,然後更新或根據需要插入。

這幾乎是你唯一的選擇,短建立一個存儲過程,爲你做上述工作。

+0

我發現了一種使用「ON DUPLICATE KEY」的方法,我認爲這是最好的解決方案,所以我會接受這個答案,但我仍然試圖弄清楚是否有沒有mysql特定術語的事務解決方案。但是,標題中提出的問題從未得到回答。我認爲答案是你不能用IF來開始一個SELECT,INSERT,UPDATE語句。我聽說過一個叫做Recordcount的屬性,存在於其他dbms中。我一直在尋找一個相當於mysql的「內部事務計數器」來告訴我是否有任何記錄被修改過。還在尋找。 – seans 2009-07-21 22:18:27

1

「插入或更新」稱爲「Upsert」。如果你谷歌「upsert MySQL」,你會發現只有幾個解決方案。

  1. 2步,插入,然後更新和變化
  2. 「對重複密鑰更新」
  3. 更換

也許數越多,但其中大部分都是變化。

使用事務的SQL是這樣的:

UPDATE xxx SET (x1, x2) = (y1, y2) WHERE id = myid; 
    IF found THEN 
     RETURN; 
    END IF; 
    BEGIN 
     INSERT INTO xxx (x1, x2) VALUES (y1, y2); 
     RETURN; 
    EXCEPTION WHEN unique_violation THEN 
    --##Do nothing, or you can put this whole sql code 
    --##in a LOOP and it will loop over and try update again 
    END; 

此代碼是從我的PostgreSQL的功能之一剝離。我認爲InnoDB不支持這一點,但我可能是錯的。