為防止主鍵沖突,設計DB的時候常常使用自增加(auto_increment 型)字段。因此插入數據前往往不知道改記錄的主鍵是什麼,為了方便後續或級聯查詢,我們需要在插入一行記錄後獲得DB自動生成的主鍵。這裡稍微整理了下幾種方法:
通用:
SELECT max(id) FROM user;這個方法的缺點是不適合高並發。如果同時插入的時候返回的值可能不准確。
MySQL:
SELECT LAST_INSERT_ID();重點: 假如你使用一條INSERT語句插入多個行, LAST_INSERT_ID() 只返回插入的第一行數據時產生的值。其原因是這使依靠其它服務器復制同樣的 INSERT語句變得簡單。
MS-SQL SERVER:
select @@IDENTITY;@@identity是表示的是最近一次向具有identity屬性(即自增列)的表插入數據時對應的自增列的值,是系統定義的全局變量。一般系統定義的全局變量都是以@@開頭,用戶自定義變量以@開頭。比如有個表A,它的自增列是id,當向A表插入一行數據後,如果插入數據後自增列的值自動增加至101,則通過select @@identity得到的值就是101。使用@@identity的前提是在進行insert操作後,執行select @@identity的時候連接沒有關閉,否則得到的將是NULL值。
補充:
SCOPE_IDENTITY、IDENT_CURRENT 和 @@IDENTITY 在功能上相似,因為它們都返回插入到 IDENTITY 列中的值。IDENT_CURRENT 不受作用域和會話的限制,而受限於指定的表。IDENT_CURRENT 返回為任何會話和作用域中的特定表所生成的值。有關更多信息,請參見 IDENT_CURRENT。
SCOPE_IDENTITY 和 @@IDENTITY 返回在當前會話中的任何表內所生成的最後一個標識值。但是,SCOPE_IDENTITY 只返回插入到當前作用域中的值;@@IDENTITY 不受限於特定的作用域。
PHP: mysql_insert_id(connection); or mysqli_insert_id(connection);
參數 connection
描述 必需。規定要使用的 MySQL 連接。
<?php $con = mysql_connect("localhost", "hello", "321"); if (!$con) { die('Could not connect: ' . mysql_error()); } $db_selected = mysql_select_db("test_db",$con); $sql = "INSERT INTO person VALUES ('Carter','Thomas','Beijing')"; $result = mysql_query($sql,$con); echo "ID of last inserted record is: " . mysql_insert_id(); mysql_close($con); ?><?php $con=mysqli_connect("localhost","my_user","my_password","my_db"); // Check connection if (mysqli_connect_errno($con)) { echo "Failed to connect to MySQL: " . mysqli_connect_error(); } mysqli_query($con,"INSERT INTO Persons (FirstName,LastName,Age) VALUES ('Glenn','Quagmire',33)"); // Print auto-generated id echo "New record has id: " . mysqli_insert_id($con); mysqli_close($con); ?>
補充:
PHP-MySQL 是 PHP 操作 MySQL 資料庫最原始的 Extension ,PHP-MySQLi 的 i 代表 Improvement ,提更了相對進階的功能,就 Extension 而言,本身也增加了安全性。
a. mysql與mysqli的概念相關:
b. mysql與mysqli的區別:
c. mysql與mysqli的用法:
$conn = mysql_connect('localhost', 'user', 'password'); //連接mysql數據庫 mysql_select_db('data_base'); //選擇數據庫 $result = mysql_query('select * from data_base');//第二個可選參數,指定打開的連接 $row = mysql_fetch_row( $result ) ) //只取一行數據 echo $row[0]; //輸出第一個字段的值
PS:mysqli以過程式的方式操作,有些函數必須指定資源,比如mysqli_query(資源標識,SQL語句),並且資源標識的參數是放在前面的,而mysql_query(SQL語句,'資源標識')的資源標識是可選的,默認值是上一個打開的連接或資源。
$conn = new mysqli('localhost', 'user', 'password','data_base'); //要使用new操作符,最後一個參數是直接指定數據庫 //假如構造時候不指定,那下一句需要$conn -> select_db('data_base')實現 $result = $conn -> query( 'select * from data_base' ); $row = $result -> fetch_row(); //取一行數據 echo row[0]; //輸出第一個字段的值
使用new mysqli('localhost', usenamer', 'password', 'databasename');會報錯,提示如下:
Fatal error: Class 'mysqli' not found in ...
一般是mysqli是沒有開啟的,因為mysqli類不是默認開啟的,win下要改php.ini,去掉php_mysqli.dll前的;,linux下要把mysqli編譯進去。
d. mysql_connect()與mysqli_connect()
JDBC 2.0:insertRow()
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()清理 }
JDBC 3.0:getGeneratedKeys()
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 { ... }