1 insert into user (username,password) VALUES ('zyl','123'); 2 //獲取剛插入的自增長id的值 3 select last_insert_id();
在MySQL中,使用auto_increment類型的id字段作為表的主鍵,並用它作為其他表的外鍵,形成“主從表結構”,這是數據庫設計中常見的用法。但是在具體生成id的時候,我們的操作順序一般是:先在主表中插入記錄,然后獲得自動生成的id,以它為基礎插入從表的記錄。這里面有個困難,就是插入主表記錄后,如何獲得它對應的id。通常的做法,是通過“select max(id) from tablename”的做法,但是顯然這種做法需要考慮並發的情況,需要在事務中對主表加以“X鎖“,待獲得max(id)的值以后,再解鎖。這種做法需要的步驟比較多,有些麻煩,而且並發性也不好。有沒有更簡單的做法呢?答案之一是通過select LAST_INSERT_ID()這個操作。乍一看,它和select max(id)很象,但實際上它是線程安全的。也就是說它是具體於數據庫連接的。下面通過實驗說明:
1、在連接1中向A表插入一條記錄,A表包含一個auto_increment類型的字段。
2、在連接2中向A表再插入一條記錄。
3、結果:在連接1中執行select LAST_INSERT_ID()得到的結果和連接2中執行select LAST_INSERT_ID()的結果是不同的;而在兩個連接中執行select max(id)的結果是相同的。
其實在MSSQL中SCOPE_IDENTITY()和IDENT_CURRENT()的區別和這里是類似的。使用SCOPE_IDENTITY()可以獲得插入某個IDENTITY字段的當前會話的值,而使用IDENT_CURRENT()會獲得在某個IDENTITY字段上插入的最大值,而不區分不同的會話。
注:使用select last_insert_id()時要注意,當一次插入多條記錄時,只是獲得第一次插入的id值,務必注意!可以試試
insert into tb(c1,c2) values (c1value,c2value),(c1value1,c2value2)..。
最后有個問題一直沒解決:
使用select last_insert_id()時要注意,當一次插入多條記錄時,只是獲得第一次插入的id值,務必注意。
我們在寫數據庫程序的時候,經常會需要獲取某個表中的最大序號數,
一般情況下獲取剛插入的數據的id,使用select max(id) from table 是可以的。
但在多線程情況下,就不行了。
下面介紹三種方法
(1) getGeneratedKeys()方法:
程序片斷:
1 Connection conn = ; 2 Serializable ret = null; 3 PreparedStatement state = .; 4 ResultSet rs=null; 5 try { 6 state.executeUpdate(); 7 rs = state.getGeneratedKeys(); 8 if (rs.next()) { 9 ret = (Serializable) rs.getObject(1); 10 } 11 } catch (SQLException e) { 12 } 13 return ret;
(2)LAST_INSERT_ID:
LAST_INSERT_ID 是與table無關的,如果向表a插入數據后,再向表b插入數據,LAST_INSERT_ID會改變。
在多用戶交替插入數據的情況下max(id)顯然不能用。
這就該使用LAST_INSERT_ID了,因為LAST_INSERT_ID是基於Connection的,只要每個線程都使用獨立的Connection對象,LAST_INSERT_ID函數將返回該Connection對AUTO_INCREMENT列最新的insert or update*作生成的第一個record的ID。這個值不能被其它客戶端(Connection)影響,保證了你能夠找回自己的 ID 而不用擔心其它客戶端的活動,而且不需要加鎖。使用單INSERT語句插入多條記錄, LAST_INSERT_ID返回一個列表。
(3)select @@IDENTITY:
顯示代碼
1 String sql="select @@IDENTITY";
@@identity是表示的是最近一次向具有identity屬性(即自增列)的表插入數據時對應的自增列的值,是系統定義的全局變量。一般系統定義的全局變量都是以@@開頭,用戶自定義變量以@開頭。比如有個表A,它的自增列是id,當向A表插入一行數據后,如果插入數據后自增列的值自動增加至101,則通過select @@identity得到的值就是101。使用@@identity的前提是在進行insert操作后,執行select @@identity的時候連接沒有關閉,否則得到的將是NULL值。