mysql 中得到新插入數(shù)據(jù)的 ID ,在 ibatis 中的應(yīng)用 有一點意外的發(fā)現(xiàn)就是,ibatis 里的 sqlmap insert 操作,竟然返回新插入數(shù)據(jù)的自增 id
我們經(jīng)常有這種需求,插入一條數(shù)據(jù)庫記錄時,需要馬上得到這條記錄的 AUTO_INCREMENT ID 。很多數(shù)據(jù)庫有內(nèi)置支持,mysql 中一直沒有找到辦法,以為沒有內(nèi)置支持呢,所以用個比較笨的辦法,有朋友問我這個問題時,我也是說的這個:
select max(ID) from mytable
返
回最大的 id 。這個語句得與插入記錄的語句在同一個“事務(wù)”里,如果用 jdbc 事務(wù),應(yīng)該一個 connection commit
里。在數(shù)據(jù)量不大時,應(yīng)用當(dāng)然是沒有問題?!?shù)據(jù)量非常大的情況我就不知道了,我認(rèn)為應(yīng)該是沒有問題的。因為,一個“事務(wù)”就保證了 SQL
插入操作后與 SQL 取得 max(ID) 的操作之間,不可能再有別的數(shù)據(jù)庫操作?!∥沂沁@樣以為,但還是沒有底。。。
今天無意中發(fā)現(xiàn),mysql 還是有內(nèi)置支持的,有專門的一個函數(shù):LAST_INSERT_ID([expr])
google 這個函數(shù)名稱,找到英文或者中文的 mysql 參考手冊都有詳細(xì)的說明。文檔說明也特別提到,用這個函數(shù)得到最新的 id ,操作也還是需要在與插入操作同一個 connection 范圍內(nèi)。應(yīng)該說與原來的作法是類似的。
還
。這樣我在程序里就不需要用二個獨立的方法了,一個 sqlmap insert 就搞定了,真是爽。當(dāng)然 sqlmap insert SQL
寫法有不同:
<insert id="insertTopic" parameterClass="topic">
insert into TOPIC (FORUM_ID, USERID, TITLE, SUMMARY, CREATE_TIME)
values (#forumId#, #userid#, #title#, #summary#, now())
<selectKey resultClass="string" keyProperty="id">
select last_insert_id() as ID from TOPIC limit 1
</selectKey>
</insert>
現(xiàn)在我們來注意一下這行 select last_insert_id() as ID from TOPIC limit 1
,不同的數(shù)據(jù)庫,這地方有不同,都有自己特別的內(nèi)置實現(xiàn)。請又特別注意
limit 1
這地方,看文檔應(yīng)該是返回一條記錄的,就是返回 id 呀,但實際應(yīng)用中我發(fā)現(xiàn),竟然返回了 n 條記錄。沒有辦法,我只有限制記錄條數(shù)為 1 ,但結(jié)果也是對的。不知道這個算不算 mysql 的 bug 。
如
果大家仔細(xì)看 last_insert_id() 這個函數(shù)的文檔,他舉了個用這個函數(shù)實現(xiàn) sequence
的例子,感覺很值得引起注意,暫時我是用不著,但有需要用得著的時候??赡苡羞@樣一種需要:需要得到自增 id ,這個 id
我可能是用作數(shù)據(jù)庫表的主鍵,也可能有別的用途。一般的想法,好像只有在數(shù)據(jù)庫里寫個存儲過程,反正我是沒有寫過,關(guān)鍵是需要考慮多用戶并發(fā)。。。
用 last_insert_id() 函數(shù)這樣來模擬一個 sequence 實現(xiàn):
mysql> CREATE TABLE sequence (id INT NOT NULL);
mysql> INSERT INTO sequence VALUES (0);
mysql> UPDATE sequence SET id=LAST_INSERT_ID(id+1);因為“如果
expr
被作為一個參數(shù)傳遞給 LAST_INSERT_ID()
,那么函數(shù)將返回這個參數(shù)的值,并且被設(shè)置為 LAST_INSERT_ID()