[資料庫] Navicat for MySQL換種思維解決插入同時更新資料
阿新 • • 發佈:2019-01-08
這篇文章是我的學生在實際專案中遇到的一個案例,在對某張表插入資料過程中,某些特定的欄位需也要進行更新,比如說部門編號在前端插入,而部門名稱在插入時應該自動更新,如果前端設定選擇編號又選擇部門就重複功能了,那麼資料庫怎麼實現呢?
最早學生想通過觸發器實現,設定一個插入觸發器,插入的同時更新資料,但是問題來了,在同一張表中,觸發器是不能同時插入又更新的。這篇文章主要討論這個問題的解決方法。同時為了加深大家對觸發器的映像,也會在給大家講述些觸發器的知識,起到討論的作用。
一. 觸發器問題
現在存在兩張表。第一張表為部門表department,核心欄位為unit(學院名稱)、depid(學院編號),如下圖所示:
第二張表為插入資訊表task,depid表示部門編號、source表示部門名稱,對應表department表的unit欄位。還有插入時間、公告事件等欄位,這裡省略了。
現在前端有個按鈕,選擇部門編號,但是想通過department部門表同時插入部門名稱,怎麼實現呢?首先,學生想到的是通過觸發器,如下所示:
觸發器設定成功。但是當插入資料時,報錯如下所示:[Err] 1442 - Can't update table 'task' in stored function/trigger because it is already used by statement which invoked this stored function/trigger.DROP TRIGGER IF EXISTS `upd_info`; create trigger upd_info after insert on task for each row begin update task,department set source = department.unit where task.depid=department.depid; end;
二. 觸發器解決
現在修改需要通過set來設定值,我修改如下所示:
其中需要注意幾點:DROP TRIGGER IF EXISTS `test`; create trigger test before insert on task for each row begin declare dname varchar(20); select department.unit into dname from department,task where task.depid=department.depid and task.depid=new.depid; set new.source = dname; end;
1.觸發器Before和After的區別。
(1) before(insert、update)可以對new進行修改;
(2) after不能對new進行修改;
(3) 兩者都不能修改old資料;
(4) 對於Insert語句,只有new是合法的,對於delete語句,只有old合法,而update可以在new和old同時使用。
否則,在after insert觸發器中使用old,報錯如下:
[Err] 1363 - There is no OLD row in on INSERT trigger
2.這裡使用declare定義變數,並且select a into b把查詢結果a賦值到b使用。
但是執行結果是沒有反應,因為查詢條件中task.depid=new.depid在before insert觸發器中,插入資料前進行查詢,其結果是空的;而使用task.depid=old.depid又不能在insert中使用old。
比如執行下列SQL語句:
insert task (depid) VALUES('1067105002');
輸出結果如下所示:那怎麼解決呢?解決方法包括:
1.後臺執行插入語句後,再執行一條Update語句,更新該欄位是最方便的操作;
2.通過Event實時更新單位名稱,參考前文:
[資料庫] Navicat for MySQL事件Event實現資料每日定期操作
但是如果需要通過SQL語句實現呢?那麼我想到的是在使用insert插入過程中呼叫select查詢,這就是我說的換個思維解決該問題。
三. 換個思維解決
SQL語句程式碼如下:
INSERT INTO task(depid,source)
SELECT depid, unit FROM department
where department.depid='1067103002';
執行結果如下所示,可以看到插入資料成功,其中taskid是自增整型,單位名稱新增成功了。後臺把'1067103002'換成對應的Java變數即可連線前端插入。
同樣,有些時候需要插入條件判斷,如果不存在則插入替代設定唯一性,程式碼為:
INSERT INTO task(depid)
SELECT '106710511' FROM DUAL WHERE NOT EXISTS(SELECT depid FROM task WHERE depid = '106710511');
最後希望線上筆記對您有所幫助,基礎性文章,如果存在錯誤或不足之處,還請海涵~還是娜麼開心、娜麼美麗。
(By:Eastmount 2017-03-12 晚上1點 )