php - PHP pdo lastInsertId() 总是返回一个 0
问题描述
这是数据库和PHP信息:
- 数据库供应商和版本:10.2.32-MariaDB
- PHP版本:PHP 7.3
我在尝试使用 PHP PDO 和 MariaDB 检索最后插入的 id 以在另一个插入语句中使用时遇到问题...
很抱歉下面的伪代码含糊不清,但试图掩盖专有数据:
try {
include_once $pdo connection stuff here;
$pdo->beginTransaction();
$sql = 'AN INSERT STATEMENT HERE';
$stmt = $pdo->prepare($sql);
$stmt->bindValue(':some_value', $some_value);
$stmt->bindValue(':another_one', $another_one);
$stmt->bindValue(':additional_value', $additional_value);
$stmt->execute();
// have tried to call $pdo->commit(): here to no avail.
//should get the last inserted id here on the AUTO_INCREMENT column in the target table from above prepared statement
// the AI column is not included in the insert statement above nor any value specified in the VALUES clause so should
// set to the next available value (and does so according to peeking at row over in phpMyAdmin).
$last_insert_id = $pdo->lastInsertId();
// don't really want to commit the above insert here just yet in case something goes wrong below and can rollback
// a file could be uploaded but it's not mandatory
if (!empty($_FILES['some_file'])) { // file has been attached.
// some file operations here
// some file operations here
// some file operations here
// some file operations here
$extensions = array("extension I am expecting");
if (in_array($file_ext, $extensions) === false) {
//Uh-oh not the correct extension so rolling back
$pdo->rollback();
die('message here...');
} else {
// file type is ok so proceeding
// if the file already exists, get rid of it so we don't have 2 copies on the server
if (file_exists($file_dir.$file_name)) {
unlink($file_dir.$file_name);
}
// storing the attached file in designated directory
move_uploaded_file($file_tmp, $file_dir.$file_name);
// going to parse the file...
$xml = simplexml_load_file('xml file to parse');
// have tried to call $pdo->commit(): here to no avail.
foreach ($xml->children() as $row) {
foreach ($row as $obj) {
if (some checking things with the obj here yada yada yada) {
$insert_sql = "INSERT INTO another table(columns.....) //there is no AUTO_INCREMENT column attribute on any column in this table just FYI
VALUES(column values...)";
$stmt = $pdo->prepare($insert_sql);
// want the AI value here from the very first insert above but it's always zero (0)
$stmt->bindValue(':last_insert_id', intval($last_insert_id), PDO::PARAM_INT);
$stmt->bindValue(':some_column', strval($some_column));
$stmt->bindValue(':another_one', strval($another_one));
$stmt->execute();
}
}
}
// all is good so committing the first insert
$pdo->commit();
}
} else {
// the file was not uploaded and it is not mandatory so committing the first insert here and the second insert never happens
$pdo->commit();
}
} catch (Exception $e) {
if ($pdo->inTransaction()) {
$pdo->rollback();
}
throw $e;
echo 'An error occurred.';
echo 'Database Error '. $e->getMessage(). ' in '. $e->getFile().
': '. $e->getLine();
}
}
我的目标是第一个插入总是被插入(应该没有失败)。第二个插入是可选的,具体取决于是否附加了文件。如果文件已附加并且所有文件操作都正常,那么我将在另一个表中插入一些值,并使用第二个表中第一个插入的 auto_increment 值(这个想法是作为外键)。
但无论出于何种原因,插入的值始终为零 (0)。
当代码成功执行时,两个表插入都完成(授予一个文件并且第二个插入甚至触发)...创建第一个表中的行,并创建第二个插入表中的 1 个或多个行,但它们有一个值在指定列中为 0,我希望它们包含第一次插入的 AI 值...
我试图调用$pdo->commit()
其他几个对我来说“有意义”的地方,认为必须提交第一个插入才能使 AI 值甚至存在于该表上,但其中任何一个都没有运气......
我什至尝试了我在另一篇 Stackoverflow 帖子中看到的测试,以确保 PDO 没有做任何奇怪的事情,但 PDO 很好......
$conn = new PDO(connection info here);
$conn->exec('CREATE TABLE testIncrement ' .
'(id INT NOT NULL AUTO_INCREMENT PRIMARY KEY, name VARCHAR(50))');
$sth = $conn->prepare('INSERT INTO testIncrement (name) VALUES (:name)');
$sth->execute([':name' => 'foo']);
var_dump($conn->lastInsertId());
以上确实返回:string(1) "1"
所以我认为 PDO 没问题(假设上述内容没有包含在事务中,我还没有尝试过)
希望我提供了足够清晰的细节......有谁知道为什么我得到 0 而不是最后一个插入 id?
非常感谢任何帮助,谢谢!
解决方案
您需要检查 $stmt->execute 的结果。阅读PDOStatement::execute上的文档,您会看到它返回一个布尔值:
成功时返回 TRUE,失败时返回 FALSE。
然后阅读PDOStatement::errorInfo上的文档。如果执行返回 FALSE,请检查此项。
$stmt->execute();
echo "\nPDOStatement::errorInfo():\n";
$arr = $stmt->errorInfo();
print_r($arr);
编辑:将错误输出到屏幕通常不是一个好主意,为了方便起见,我在这种情况下这样做了。更好的方法是编写一个日志文件:
$arr = $stmt->errorInfo();
file_put_contents("/path/to/file.log", print_r($arr, TRUE));
推荐阅读
- sql - SQLITE_ERROR SQL 错误或缺少数据库(“(”附近:语法错误)嵌套选择顺序按
- django - 如何通过 makemigrations 安装 Django pg_trgm?
- r - R Shiny 中的本地持久数据存储,适用于已部署应用程序中的多个用户
- sql - 如何使用 SQL Server 中的主键删除数据?
- amazon-web-services - 在维护时段任务中配置 SNS 主题通知 IAM 角色
- typescript - 使用枚举字符串时,我可以从分配的值中获取枚举键吗?
- javascript - Javascript 从 XMLHttpRequest 迁移到 CloudflareBypasser
- python - Python Gtts 助手
- c# - Delphi中如何从导入的DLL中初始化一个对象?
- python - 使用 Python 和 Selenium 抓取 iframe