INSERT 寫入數據的同時,原子性獲取自增主鍵 ID,**避免「先查 MAX(ID)+1 再插入」的併發競態條件**。
-- SQL
INSERT INTO KEYWORD (KEYWORD_ID, SITE_ID, KEYWORD_NAME, STATUS, SOURCE, CREATE_TIME, LAST_CHANGED)
VALUES (KEYWORD_SEQ.NEXTVAL, :SITE_ID, :NAME, 1, :SOURCE, SYSDATE, SYSDATE+0.0007)
RETURNING KEYWORD_ID INTO :Key_ID;
-- Java (JDBC/OracleDriver)
OracleParameter outputIdParm = new OracleParameter(":Key_ID", OracleDbType.Int32, ParameterDirection.Output);
command.Parameters.Add(outputIdParm);
command.ExecuteNonQuery();
var allKeyWordIds = outputIdParm.Value as OracleDecimal[];
關鍵點:RETURNING ... INTO + ParameterDirection.Output,單次往返完成寫入+取 ID。
-- T-SQL
INSERT INTO syslog (Thread) VALUES ('test');
SELECT @@IDENTITY AS Id; -- 或 SCOPE_IDENTITY() (推薦,不受觸發器影響)
-- C# (ADO.NET)
var cmd = conn.CreateCommand();
cmd.CommandText = "INSERT INTO syslog (Thread) VALUES ('test'); SELECT SCOPE_IDENTITY();";
var id = cmd.ExecuteScalar(); -- 直接返回標量值
區別**:@@IDENTITY 返回會話最後生成的身份值 (含觸發器副作用);SCOPE_IDENTITY() 返回當前作用域 (存儲過程/觸發器/批次) 最後生成值,**推薦用 SCOPE_IDENTITY()**;IDENT_CURRENT('table') 返回表最後生成值 (跨會話,併發不安全)。
-- SQL 方式
INSERT INTO t (name) VALUES ('test');
SELECT LAST_INSERT_ID(); -- 返回當前會話最後生成的 AUTO_INCREMENT 值
-- JDBC 標準方式 (推薦,跨數據庫兼容)
String sql = "INSERT INTO t (name) VALUES (?)";
try (PreparedStatement ps = conn.prepareStatement(sql, Statement.RETURN_GENERATED_KEYS)) {
ps.setString(1, "test");
ps.executeUpdate();
try (ResultSet rs = ps.getGeneratedKeys()) {
if (rs.next()) {
long id = rs.getLong(1); -- 獲取自增 ID
}
}
}
-- MyBatis 配置
INSERT INTO user (name, age) VALUES (#{name}, #{age})
關鍵點**:
LAST_INSERT_ID() 是**會話級**函數,併發安全,不受其他會話影響Statement.RETURN_GENERATED_KEYS 是 JDBC 3.0 標準,**首選方案**,屏蔽數據庫差異getGeneratedKeys() 返回所有生成的 ID (順序對應),LAST_INSERT_ID() 僅返回第一條
INSERT INTO t (name) VALUES ('test') RETURNING id;
-- 直接返回結果集,單條或批量均支持
| 數據庫 | 標準 SQL 方案 | 驅動層標準方案 | 備註 |
|---|---|---|---|
| Oracle | RETURNING INTO | OraclePreparedStatement + registerReturnParameter | 序列 SEQ.NEXTVAL 生成 ID |
| SQL Server | SCOPE_IDENTITY() | Statement.RETURN_GENERATED_KEYS (JDBC 4.0+ 支持) | 避免用 @@IDENTITY |
| MySQL | LAST_INSERT_ID() | Statement.RETURN_GENERATED_KEYS (首選) | 批量插入獲取所有 ID |
| PostgreSQL | RETURNING id | Statement.RETURN_GENERATED_KEYS | 功能最強,可返回任意列 |