程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 數據庫知識 >> MYSQL數據庫 >> MySQL綜合教程 >> MYSQL獲取自增主鍵【4種方法】

MYSQL獲取自增主鍵【4種方法】

編輯:MySQL綜合教程

MYSQL獲取自增主鍵【4種方法】   通常我們在應用中對mysql執行了insert操作後,需要獲取插入記錄的自增主鍵。本文將介紹java環境下的4種方法獲取insert後的記錄主鍵auto_increment的值:   通過JDBC2.0提供的insertRow()方式 通過JDBC3.0提供的getGeneratedKeys()方式 通過SQL select LAST_INSERT_ID()函數 通過SQL @@IDENTITY 變量 1. 通過JDBC2.0提供的insertRow()方式 自jdbc2.0以來,可以通過下面的方式執行。   [java]  Statement stmt = null;   ResultSet rs = null;   try {       stmt = conn.createStatement(java.sql.ResultSet.TYPE_FORWARD_ONLY,  // 創建Statement                                   java.sql.ResultSet.CONCUR_UPDATABLE);       stmt.executeUpdate("DROP TABLE IF EXISTS autoIncTutorial");       stmt.executeUpdate(                                                // 創建demo表               "CREATE TABLE autoIncTutorial ("               + "priKey INT NOT NULL AUTO_INCREMENT, "               + "dataField VARCHAR(64), PRIMARY KEY (priKey))");       rs = stmt.executeQuery("SELECT priKey, dataField "                 // 檢索數據          + "FROM autoIncTutorial");       rs.moveToInsertRow();                                              // 移動游標到待插入行(未創建的偽記錄)       rs.updateString("dataField", "AUTO INCREMENT here?");              // 修改內容       rs.insertRow();                                                    // 插入記錄       rs.last();                                                         // 移動游標到最後一行       int autoIncKeyFromRS = rs.getInt("priKey");                        // 獲取剛插入記錄的主鍵preKey       rs.close();       rs = null;       System.out.println("Key returned for inserted row: "           + autoIncKeyFromRS);   }  finally {       // rs,stmt的close()清理   }   優點:早期較為通用的做法 缺點:需要操作ResultSet的游標,代碼冗長。   2. 通過JDBC3.0提供的getGeneratedKeys()方式 [java]  Statement stmt = null;   ResultSet rs = null;   try {       stmt = conn.createStatement(java.sql.ResultSet.TYPE_FORWARD_ONLY,                                   java.sql.ResultSet.CONCUR_UPDATABLE);         // ...       // 省略若干行(如上例般創建demo表)       // ...       stmt.executeUpdate(               "INSERT INTO autoIncTutorial (dataField) "               + "values ('Can I Get the Auto Increment Field?')",               Statement.RETURN_GENERATED_KEYS);                      // 向驅動指明需要自動獲取generatedKeys!       int autoIncKeyFromApi = -1;       rs = stmt.getGeneratedKeys();                                  // 獲取自增主鍵!       if (rs.next()) {           autoIncKeyFromApi = rs.getInt(1);       }  else {           // throw an exception from here       }        rs.close();       rs = null;       System.out.println("Key returned from getGeneratedKeys():"           + autoIncKeyFromApi);   }  finally { ... }   這種方式只需要2個步驟:1. 在executeUpdate時激活自動獲取key; 2.調用Statement的getGeneratedKeys()接口 優點: 1. 操作方便,代碼簡潔 2. jdbc3.0的標准 3. 效率高,因為沒有額外訪問數據庫   這裡補充下, a.在jdbc3.0之前,每個jdbc driver的實現都有自己獲取自增主鍵的接口。在mysql jdbc2.0的driver org.gjt.mm.mysql中,getGeneratedKeys()函數就實現在org.gjt.mm.mysql.jdbc2.Staement.getGeneratedKeys()中。這樣直接引用的話,移植性會有很大影響。JDBC3.0通過標准的getGeneratedKeys很好的彌補了這點。 b.關於getGeneratedKeys(),官網還有更詳細解釋:OracleJdbcGuide   3. 通過SQL select LAST_INSERT_ID()函數 [java]  Statement stmt = null;   ResultSet rs = null;   try {       stmt = conn.createStatement();       // ...       // 省略建表       // ...       stmt.executeUpdate(               "INSERT INTO autoIncTutorial (dataField) "               + "values ('Can I Get the Auto Increment Field?')");       int autoIncKeyFromFunc = -1;       rs = stmt.executeQuery("SELECT LAST_INSERT_ID()");             // 通過額外查詢獲取generatedKey       if (rs.next()) {           autoIncKeyFromFunc = rs.getInt(1);       }  else {           // throw an exception from here       }        rs.close();       System.out.println("Key returned from " +                          "'SELECT LAST_INSERT_ID()': " +                          autoIncKeyFromFunc);   }  finally {...}   這種方式沒什麼好說的,就是額外查詢一次函數LAST_INSERT_ID(). 優點:簡單方便 缺點:相對JDBC3.0的getGeneratedKeys(),需要額外多一次數據庫查詢。   補充: 1. 這個函數,在mysql5.5手冊的定義是:“returns a BIGINT (64-bit) value representing the first automatically generated value successfully inserted for an AUTO_INCREMENT column as a result of the most recently executed INSERT statement.”。文檔點此 2. 這個函數,在connection維度上是“線程安全的”。就是說,每個mysql連接會有個獨立保存LAST_INSERT_ID()的結果,並且只會被當前連接最近一次insert操作所更新。也就是2個連接同時執行insert語句時候,分別調用的LAST_INSERT_ID()不會相互覆蓋。舉個栗子:連接A插入表後LAST_INSERT_ID()返回100,連接B插入表後LAST_INSERT_ID()返回101,但是連接A重復執行LAST_INSERT_ID()的時候,始終返回100,而不是101。這個可以通過監控mysql連接數和執行結果來驗證,這裡不詳述實驗過程。 3. 在上面那點的基礎上,如果在同一個連接的前提下同時執行insert,那可能2次操作的返回值會相互覆蓋。因為LAST_INSERT_ID()的隔離程度是連接級別的。這點,getGeneratedKeys()是可以做的更好,因為getGeneratedKeys()是statement級別的。同個connection的多次statement,getGeneratedKeys()是不會被相互覆蓋。   4. 通過SELECT @@IDENTITY 變量 這個方式和LAST_INSERT_ID()效果是一樣的。官網文檔如此表述:“This variable is a synonym for the last_insert_id variable. It exists for compatibility with other database systems. You can read its value with SELECT @@identity, and set it using SET identity.” 文檔點此   重要補充: 無論是SELECT LAST_INSERT_ID()還是SELECT @@IDENTITY,對於一條insert語句插入多條記錄,永遠只會返回第一條插入記錄的generatedKey.如: [java]  INSERT INTO t VALUES       -> (NULL, 'Mary'), (NULL, 'Jane'), (NULL, 'Lisa');   LAST_INSERT_ID(), @@IDENTITY都只會返回'Mary'所在的那條記錄的generatedKey

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved