PHP和MySQL选择单个值

25

我想知道如何从我的MySQL表中选择单个值。该表包括多列,其中包括usernameidid是自动递增的,而username是唯一的)。给定用户名,我想将会话变量$_SESSION['myid']设置为对应于给定用户名的id列中的值。这是我已经尝试过的代码:

session_start();
$name = $_GET["username"];
$sql = "SELECT 'id' FROM Users WHERE username='$name'";
$result = mysql_query($sql);
$value = mysql_fetch_object($result);
$_SESSION['myid'] = $value;

到目前为止,我遇到的问题是:

可捕获的致命错误:无法将 stdClass 类的对象转换为字符串。

$value 强制转换为字符串类型并不能解决这个问题。


只是提醒一下...mysql扩展已经被弃用,并将在未来被移除:请改用mysqli或PDO。 - Wes Cossick
2
这个程序存在严重的安全问题。正如@WesC所指出的,不要使用mysql_*函数。此外,您容易受到SQL注入攻击的威胁。 - elixenide
8个回答

60
  1. 不要在查询中使用引号作为字段名或表名。

  2. 获取对象后,您需要通过属性名称访问对象属性/属性(在您的情况下为id)。

请注意:由于mysql_*已过时,请改用mysqli_*或PDO。 这里使用mysqli:

session_start();
mysqli_report(MYSQLI_REPORT_ERROR | MYSQLI_REPORT_STRICT);
$link = new mysqli('localhost', 'username', 'password', 'db_name');
$link->set_charset('utf8mb4'); // always set the charset
$name = $_GET["username"];
$stmt = $link->prepare("SELECT id FROM Users WHERE username=? limit 1");
$stmt->bind_param('s', $name);
$stmt->execute();
$result = $stmt->get_result();
$value = $result->fetch_object();
$_SESSION['myid'] = $value->id;

奖励技巧: 对于这种情况,请使用limit 1,它将节省执行时间 :)


这个方法成功消除了错误信息,但是现在将 $_SESSION['myid'] 打印到屏幕上显示的是 "id" 而不是一个具体的整数。 - user3055501
@user3055501:尝试上面的代码。我已经在$sql行中进行了更改,请提供您的反馈。它应该可以工作 :) - Awlad Liton
1
在查询中永远不要使用原始用户输入。 - mickmackusa

11

mysql_*函数已经过时且不安全。 您问题中的代码容易受到注入攻击的威胁。强烈建议您改为使用PDO扩展,像这样:

session_start();

$query = "SELECT 'id' FROM Users WHERE username = :name LIMIT 1";
$statement = $PDO->prepare($query);
$params = array(
    'name' => $_GET["username"]
);
$statement->execute($params);
$user_data = $statement->fetch();

$_SESSION['myid'] = $user_data['id'];

其中$PDO是您的PDO对象变量。有关PHP和PDO的更多信息,请参见https://www.php.net/pdo_mysql

需要额外帮助:

这是使用PDO连接到数据库的快速入门:

$database_username = "YOUR_USERNAME";
$database_password = "YOUR_PASSWORD";
$database_info = "mysql:host=localhost;dbname=YOUR_DATABASE_NAME";
try
{
    $PDO = new PDO($database_info, $database_username, $database_password);
}
catch(PDOException $e)
{
    // Handle error here
}

谢谢你的回答,Wes。我一定会在有更多时间时研究PDO。 - user3055501
从个人经验来看,我建议您尽早研究它。您使用 mysql_* 函数编写的代码越多,就会发现您需要完全重写它们。此外,在其他方面,它实际上非常方便和更有组织性。 - Wes Cossick
1
如果有人看到此内容并感到恐慌,您可以改用更好的mysqli。请注意,在mysql末尾加上i。 - Anders M.
就像@AndersM所说的那样 - 对于简单查询,我也发现mysqli比PDO更易于使用/阅读。但请注意,Wes提出了一个非常重要的观点:如果查询的任何部分包含不完全受您控制的文本,则使用预处理语句。在mysqli中,这是prepare预处理语句的手册讨论 - ToolmakerSteve

4

mysql_*扩展在2013年已被弃用,并在2018年从PHP中完全移除。您有两个备选方案:PDO 或者 MySQLi

PDO

更简单的选择是PDO,它具有一个方便的辅助函数fetchColumn()

$stmt = $pdo->prepare("SELECT id FROM Users WHERE username=?");
$stmt->execute([ $_GET["username"] ]);
$value = $stmt->fetchColumn();

PDO正确的教程

MySQLi

你可以用MySQLi做同样的事情,但这更加复杂:

$stmt = $mysqliConn->prepare('SELECT id FROM Users WHERE username=?');
$stmt->bind_param("s", $_GET["username"]);
$stmt->execute();
$data = $stmt->get_result()->fetch_assoc();
$value = $data ? $data['id'] : null;

fetch_assoc() 如果从数据库中没有返回行,则可能返回 NULL,因此我使用三元运算符检查是否有任何数据被返回。

自 PHP 8.1 起,您也可以使用 fetch_column()

$stmt->execute();
$value = $stmt->get_result()->fetch_column();

获取MySQL数据库中的ID并基于此加载数据是非常困难的,因为很难找到安全的查询来关闭新问题。 - mickmackusa

4

您可以使用 mysqli_fetch_field 方法来实现这一功能。

session_start();
$link = mysqli_connect("localhost", "my_user", "my_password", "world");
$name = $_GET["username"];
$sql = "SELECT 'id' FROM Users WHERE username='$name' limit 1";
$result = mysqli_query($link, $sql);
if ($result !== false) {
    $value = mysqli_fetch_field($result);
    $_SESSION['myid'] = $value;
}

注意:您也可以使用mysql_fetch_field()方法来实现,但在PHP v5.5中它将被弃用。


2
mysqli_fetch_field函数“返回一个包含字段定义信息的对象,如果没有可用的字段信息,则返回FALSE。”因此,根据答案的建议,这种方法不起作用。由于这个原因,评分为-1。 - El Gucs
1
@GusstavvGil:我通过确保在调用mysqli_fetch_field之前有一个有效的$result来纠正了代码。我还添加了缺失的$link参数。 - ToolmakerSteve
4
@ToolmakerSteve mysqli_fetch_field不会返回值,它返回字段定义,例如名称、表、标志。因为这个原因返回-1... http://php.net/manual/zh/mysqli-result.fetch-field.php - commonpike
请勿使用此答案,因为其不安全/不稳定。 - mickmackusa
2
警告:这个答案完全错误。mysqli_fetch_field()返回的是关于表列的元数据,而不是它本身的值。 - Dharman

3

试试这个

$value = mysql_result($result, 0);

警告:mysql_*扩展自PHP 5.5.0起被弃用,并在PHP 7.0.0中被删除。相反,应使用mysqli或PDO_MySQL扩展。有关选择MySQL API时的进一步帮助,请参阅MySQL API概述 - Dharman
在Stackoverflow上,“试试这个”答案的价值很低,因为它们不能很好地教育/授权OP和成千上万的未来研究人员。即使您觉得您的解决方案是超级基础/自我说明的,所有答案都应包含某种形式的简单英文支持文本。告诉研究人员它是如何工作的,为什么它有效,它与其他答案的不同之处,为什么您认为这是一个好主意,提供链接到文档等。当您回答问题时,请慷慨大方,以帮助人们并向他人展示良好的答案发布行为。 - mickmackusa

2
很明显,每个唯一的username只对应一个id,因为username是唯一的。但实际的问题在于查询本身-
$sql = "SELECT 'id' FROM Users WHERE username='$name'";

输出

+----+
| id |
+----+
| id |
+----+

也就是说,'id' 实际上被视为字符串而不是 id 属性。

正确语法:

$sql = "SELECT `id` FROM Users WHERE username='$name'";

即,使用重音符号(`)而不是单引号(')。 或者
$sql = "SELECT id FROM Users WHERE username='$name'";

完整代码

session_start();
$name = $_GET["username"];
$sql = "SELECT `id` FROM Users WHERE username='$name'";
$result = mysql_query($sql);
$row=mysql_fetch_array($result)
$value = $row[0];
$_SESSION['myid'] = $value;

2
第五行需要加上一个分号。 - Brian Fleming
警告:mysql_*扩展自PHP 5.5.0起已被弃用,并在PHP 7.0.0中删除。相反,应使用mysqliPDO_MySQL扩展。在选择MySQL API时,还应参阅MySQL API概述以获得进一步帮助。 - Dharman

2

使用mysql_fetch_object时,您将获得一个对象(类为stdClass),其中包含该行的所有字段。

建议使用mysql_fetch_field代替mysql_fetch_object,这将给你结果集中的第一个字段(在您的情况下为id)。相关文档请参见此处


1
警告:这个答案完全错误。mysql_fetch_field()返回的是关于表列的元数据,而不是值本身。 - Dharman

1
尝试这个。
session_start();
$name = $_GET["username"];
$sql = "SELECT 'id' FROM Users WHERE username='$name' LIMIT 1 ";
$result = mysql_query($sql) or die(mysql_error());
if($row = mysql_fetch_assoc($result))
{
      $_SESSION['myid'] = $row['id'];
}

警告:mysql_*扩展自PHP 5.5.0起已被弃用,并在PHP 7.0.0中删除。相反,应使用mysqliPDO_MySQL扩展。在选择MySQL API时,还应参阅MySQL API概述以获得进一步帮助。 - Dharman

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接