2017-09-13 43 views
0

我試圖通過phpMyAdmin來執行數據庫中的這個查詢MySQL的BEFORE INSERT觸發器把重複的主鍵插入到更新

create trigger avoid_duplicated_sharing 
before insert on sharingevents 
for each row 
begin 
    if (select count(*) from sharingevents where shared_note_id = NEW.shared_note_id AND shared_to = NEW.shared_to > 0) then 
     delete from sharingevents where shared_note_id = NEW.shared_note AND shared_to = NEW.shared_to 
    END IF; 
END 

的phpmyadmin給了我以下錯誤:

MySQL said: #1064 - You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'END IF' at line 7

兩個問題:

  • 我的腳本有什麼問題?
  • 經過BEFORE INSERT觸發後,是否會執行INSERT操作?如果它沒有我將不得不刪除INSERT INTO SharingEvents (SELECT * FROM NEW);
+0

你不能轉動將其插入到一個更新,你把它變成相同的插入。 – Barmar

+0

你說得對,我把查詢改爲:'從sharingevents中刪除where(shared_note = NEW.shared_note_id AND shared_to = NEW.shared_to);' – Maximetinu

+0

'INSERT INTO ... ON DUPLICATE KEY UPDATE'有什麼問題或者INSERT IGNORE'查詢?它們不適合你的用例嗎? – Mjh

回答

0

使用exists

if (exists (select 1 from sharingevents where shared_note_id = new.shared_note_id AND shared_to = new.shared_to) > 0) then 
    insert into sharingevents (shared_note_id,shared_to,permission_level) 
     values (NEW.shared_note_id,NEW.shared_to,NEW.permission_level); 
end if; 

或者,更好,在sharingevents(shared_note-id, shared_to)添加唯一索引,然後使用:

insert into sharingevents (shared_note_id, shared_to, permission_level) 
     values (NEW.shared_note_id, NEW.shared_to, NEW.permission_level) 
     on duplicate key update shared_note_id = values(shared_note_id); 

這將忽略表中已存在對的任何更新。否需要if

+0

同一個錯誤:/ '#1064 - 你的SQL語法錯誤;請檢查與您的MariaDB服務器版本相對應的手冊,以便在第5行' 插入到sharingevents(shared_note_id,shared_to,permission_level)'旁邊使用正確的語法' – Maximetinu

+0

括號不平衡,您不需要使用'> 0'來測試'exists()'的結果。 – Barmar

+0

你的第二個建議是好的,但可能需要更改他不想接觸的應用程序代碼,所以他使用觸發器自動化了它。 – Barmar

0

count(shared_note_id, shared_to)是無效的語法。當您使用count(DISTINCT ...)時,只能在COUNT()內放置多個列名稱。就你而言,你根本不需要輸入列名,只需使用COUNT(*)來計算匹配條件的行數。

count(*) and count(column_name), what's the diff?瞭解更多信息,當你應該把列名COUNT()

不幸的是,固定的語法錯誤不會真正解決你的問題,因爲你不能使用觸發器來做出改變的同一張桌子。從FAQ

Can triggers access tables?
A trigger can access both old and new data in its own table. A trigger can also affect other tables, but it is not permitted to modify a table that is already being used (for reading or writing) by the statement that invoked the function or trigger.

你需要重新編寫呼叫者使用INSERT ... ON DUPLICATE KEY UPDATE,或等同的東西,做到這一點。

+0

我已經做了這個改變,是的,這是一個錯誤!謝謝。但即使這樣也行不通。現在它在END IF – Maximetinu

0

我用下面的代碼解決這個問題:

delimiter $$ 

create trigger avoid_duplicated_sharing 
before insert on sharingevents 
for each row 
begin 
    if (select count(*) from sharingevents where shared_note_id = NEW.shared_note_id AND shared_to = NEW.shared_to > 0) then 
     delete from sharingevents where shared_note_id = NEW.shared_note_id AND shared_to = NEW.shared_to; 
    end if; 
END$$ 

問題是分隔符。

即便如此,我的觸發器不起作用。當應用程序插入複製的主鍵的MySQL引發以下錯誤:

#1442 - Can't update table 'sharingevents' in stored function/trigger because it is already used by statement which invoked this stored function/trigger.

+0

給我一個錯誤觸發器不允許修改它們觸發的同一個表。 – Barmar