mysql和oracle插入的時候有一個很大的區別是,oracle支持序列作id,mysql自己有一個列能夠作自增加字段,mysql在插入一條數據後,如何能得到到這個自增id的值呢? java
方法一是使用last_insert_id mysql
mysql> SELECT LAST_INSERT_ID();
產生的ID 每次鏈接後保存在服務器中。這意味着函數向一個給定客戶端返回的值是該客戶端產生對影響AUTO_INCREMENT列的最新語句第一個 AUTO_INCREMENT值的。這個值不能被其它客戶端影響,即便它們產生它們本身的 AUTO_INCREMENT值。這個行爲保證了你可以找回本身的 ID 而不用擔憂其它客戶端的活動,並且不須要加鎖或處理。 sql
每次mysql_query操做在mysql服務器上能夠理解爲一次「原子」操做, 寫操做經常須要鎖表的, 是mysql應用服務器鎖表不是咱們的應用程序鎖表。 服務器
值得注意的是,若是你一次插入了多條記錄,這個函數返回的是第一個記錄的ID值。 session
由於LAST_INSERT_ID是基於Connection的,只要每一個線程都使用獨立的Connection對象,LAST_INSERT_ID函數將返回該Connection對AUTO_INCREMENT列最新的insert or update*做生成的第一個record的ID。這個值不能被其它客戶端(Connection)影響,保證了你可以找回本身的 ID 而不用擔憂其它客戶端的活動,並且不須要加鎖。使用單INSERT語句插入多條記錄, LAST_INSERT_ID返回一個列表。 併發
LAST_INSERT_ID 是與table無關的,若是向表a插入數據後,再向表b插入數據,LAST_INSERT_ID會改變。 oracle
方法二是使用max(id) 框架
使用last_insert_id是基礎鏈接的,若是換一個窗口的時候調用則會一直返回10 ide
若是不是頻繁的插入咱們也能夠使用這種方法來獲取返回的id值 函數
select max(id) from user;
這個方法的缺點是不適合高併發。若是同時插入的時候返回的值可能不許確。
方法三是建立一個存儲過程,在存儲過程當中調用先插入再獲取最大值的操做
DELIMITER $$ DROP PROCEDURE IF EXISTS `test` $$ CREATE DEFINER=`root`@`localhost` PROCEDURE `test`(in name varchar(100),out oid int) BEGIN insert into user(loginname) values(name); select max(id) from user into oid; select oid; END $$ DELIMITER ;
call test('gg',@id);
方法四使用@@identity
select @@IDENTITY@@identity是表示的是最近一次向具備identity屬性(即自增列)的表插入數據時對應的自增列的值,是系統定義的全局變量。通常系統定義的全局變量都是以@@開頭,用戶自定義變量以@開頭。好比有個表A,它的自增列是id,當向A表插入一行數據後,若是插入數據後自增列的值自動增長至101,則經過select @@identity獲得的值就是101。使用@@identity的前提是在進行insert操做後,執行select @@identity的時候鏈接沒有關閉,不然獲得的將是NULL值。
方法五是使用getGeneratedKeys()
Connection conn = ; Serializable ret = null; PreparedStatement state = .; ResultSet rs=null; try { state.executeUpdate(); rs = state.getGeneratedKeys(); if (rs.next()) { ret = (Serializable) rs.getObject(1); } } catch (SQLException e) { } return ret;
總結一下,在mysql中作完插入以後獲取id在高併發的時候是很容易出錯的。另外last_insert_id雖然是基於session的可是不知道爲何沒有測試成功。
其實在ibtias框架裏使用selectkey這個節點,並設置insert返回值的類型爲integer,就能夠返回這個id值。