为什么插入后跟选择 LAST_INSERT_ID() 不输出任何内容


Why is INSERT INTO followed by SELECT LAST_INSERT_ID() not outputting anything?

我拥有的PHP代码将上一页的HTML表单数据插入到数据库中,并在同一SQL语句中从插入的数据中返回PostID。"后 ID"列为AUTO_INCREMENTING。我已经研究了这个问题一两个星期,但没有找到重要的解决方案。

<?php
include("dbconnect.php");
mysql_select_db("astral_database", $con);
session_start();
$username = $_SESSION['username'];
$forumtext = $_POST["forumtext"];
$forumsubject = $_POST["forumsubject"];
$postquery = 'INSERT INTO Forums (Creator, Subject, Content) VALUES ("$username", "$forumsubject", "$forumtext"); SELECT LAST_INSERT_ID()';
$result = mysql_query($postquery, $con);
if (!$con) {
    echo "<b>If you are seeing this, please send the information below to astraldevgroup@gmail.com</b><br>Error (331: dbconnect experienced fatal errors while attempting to connect)";
    die();
}
if ($username == null) {
    echo "<b>If you are seeing this, please send the information below to astraldevgroup@gmail.com</b><br>Error (332: Username was not specified while attempting to send request)";
    die();
}
if ($result != null) {
    echo "last id: " . $result;
    $fhandle = fopen("recentposts.txt", "r+");
    $contents = file_get_contents("recentposts.txt");
    fwrite($fhandle, json_encode(array("postid" => $result, "creator" => $username, "subject" => $forumsubject, "activity" => time())) . "'n" . $contents);
    fclose($fhandle);
    mysql_close($con);
    header("location: http://astraldevgroup.com/forums");
    die();
} else {
    die("<b>If you are seeing this, please send the information below to astraldevgroup@gmail.com</b><br>Error (330: Unhandled exception occured while posting forum to website.)<br>");
    echo mysql_error();
}
mysql_close($con);
?>

首先,mysql_query不会从 SELECT 语句返回任何内容。我还没有找到任何可以在同一查询中同时正确运行 SELECT 语句和 INSERT 语句的内容。如果我尝试在两个不同的语句中运行它们,它仍然不会返回任何内容。我尝试在SQL控制台中运行以下语句,它运行良好,没有错误。

INSERT INTO Forums (Creator, Subject, Content) VALUES ("Admin", "Test forum 15", "This is a forum that should give me the post id."); SELECT LAST_INSERT_ID();

mysql_query函数运行多个语句

参考: http://php.net/manual/en/function.mysql-query.php

mysql_query()将唯一查询(不支持多个查询)发送到服务器上的当前活动数据库...

这就是对mysql_query调用不返回结果集的原因之一。

最明显的解决方法是不尝试在同一查询中运行SELECT。您可以改用对mysql_insert_id的调用。

参考: PHP: mysql_insert_id http://php.net/manual/en/function.mysql-insert-id.php


回答

一些你没有问的问题:

  • 是的,您的示例代码容易受到 SQL 注入的攻击。
  • 是的,mysql_接口已被弃用很长时间。
  • 是的,您应该使用 PDO 或 mysqli 接口,而不是已弃用的 mysql_ 函数。

随访

重新访问我的答案,再次查看问题和示例代码。

我之前指出该代码容易受到 SQL 注入的攻击,因为 SQL 文本中包含潜在的不安全值。这就是快速审查的样子。

但再看一遍,这并不完全正确,因为变量替换并没有真正发生,因为字符串文字被括在单引号中。考虑输出来自:

  $foo = "bar";
  echo '$foo';
  echo '"$foo"';

然后考虑这行代码分配给$postquery的内容:

$postquery = 'INSERT ... VALUES ("$username", "$forumsubject", "$forumtext")';

修复此问题,以便将$username视为对变量的引用,而不是文本字符(以获取分配给$username变量的值并入 SQL 文本),这将引入 SQL 注入漏洞。

带有绑定占位符的预准备语句实际上并不难

$result永远不会null。它要么是结果句柄,要么是布尔false。由于您正在测试错误的值,因此您永远不会看到mysql_query()返回的 false 告诉您查询失败。

正如其他人所指出的,您不能在单个query()调用中发出多个查询 - 这是针对PHP mysql驱动程序中一种形式的SQL注入攻击的廉价基本防御。但是,代码的其余部分容易受到其他形式的注入攻击,因此...最好开始阅读:http://bobby-tables.com

另外,在

逻辑方面,为什么要在尝试将相同的用户名插入数据库测试空用户名?您应该在运行查询之前测试/验证这些值。