為防止主鍵沖突,設計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 { ... }