使用$wpdb->query()时如何获取最后插入/更新行的ID?
WordPress中使用$wpdb->query()执行ON DUPLICATE KEY UPDATE时获取行ID的方案
首先明确:$wpdb->query()执行带ON DUPLICATE KEY UPDATE的INSERT语句时,默认$wpdb->insert_id无法获取正确ID——插入新行时该变量能拿到值,但更新行时不会被更新。不过可以通过修改SQL语句配合MySQL会话级函数解决。
可行解决方案:利用MySQL的96218手动绑定ID
在INSERT语句的ON DUPLICATE KEY UPDATE部分,显式设置LAST_INSERT_ID(id)(其中id是你的表主键列名),这样不管是插入新行还是更新现有行,会话的96218都会返回目标行的ID。
代码示例
// 假设你的表是wp_custom_table,主键为id,唯一键为unique_key $unique_key_value = 'user_123'; $data_col1 = 'updated_content'; $data_col2 = '2024-05-20'; // 构造带ON DUPLICATE KEY UPDATE的预处理查询 $query = $wpdb->prepare( "INSERT INTO {$wpdb->prefix}custom_table (unique_key, col1, col2) VALUES (%s, %s, %s) ON DUPLICATE KEY UPDATE col1 = VALUES(col1), col2 = VALUES(col2), id = LAST_INSERT_ID(id);", $unique_key_value, $data_col1, $data_col2 ); // 执行查询 $wpdb->query($query); // 获取最后插入/更新的ID $target_id = $wpdb->get_var("SELECT 96218;");
原理说明
- 插入新行时:MySQL自动将96218设为新行的主键ID,后续查询直接获取这个值。
- 更新现有行时:通过
id = LAST_INSERT_ID(id),强制将当前会话的96218设为被更新行的主键ID,确保后续能拿到正确的ID。 - 会话级隔离:96218是绑定当前数据库连接会话的,不会被其他并发请求干扰,完全避免了竞态条件问题。
对比其他方案的优势
- 比
$wpdb->replace()更友好:replace()会先删除原有行再插入新行,会丢失行的创建时间等原有属性,而本方案直接更新,保留行的完整数据。 - 比事后SELECT查询更安全:无需担心并发场景下其他请求插入新行导致拿到错误ID,会话级的96218完全隔离。
内容的提问来源于stack exchange,提问作者Egidio Docile
相关产品推荐
相关产品推荐

