如何在MySQL语句中包含PHP变量

How to include a PHP variable inside a MySQL statement

提问人:Pinkie 提问时间:9/24/2011 最后编辑:MachavityPinkie 更新时间:5/7/2023 访问量:448553

问:

我正在尝试在内容表中插入值。如果我在 VALUES 中没有 PHP 变量,它可以正常工作。当我把变量放进去时,这是行不通的。我做错了什么?$typeVALUES

$type = 'testing';
mysql_query("INSERT INTO contents (type, reporter, description) 
     VALUES($type, 'john', 'whatever')");
php mysql sql 字符串 变量

评论

14赞 Machavity 11/11/2019
重要:将变量直接插入 SQL 是 SQL 注入攻击的主要来源

答:

2赞 Spencer Rose 9/24/2011 #1

$type中的文本直接替换为插入字符串,因此MySQL得到以下结果:

... VALUES(testing, 'john', 'whatever')

请注意,测试周围没有引号,您需要像这样输入这些引号:

$type = 'testing';
mysql_query("INSERT INTO contents (type, reporter, description) VALUES('$type', 'john', 'whatever')");

我还建议你阅读SQL注入,因为如果你不清理正在使用的数据,这种参数传递很容易被黑客攻击:

133赞 Your Common Sense 9/24/2011 #2

在任何MySQL语句中添加PHP变量的规则都很简单:

1. 使用准备好的语句

此规则涵盖 99% 的查询,尤其是您的查询。任何表示 SQL 数据文本(或者,简单地说 - SQL 字符串或数字)的变量都必须通过预准备语句添加。没有例外

这种方法包括四个基本步骤

  • 在 SQL 语句中,将所有变量替换为占位符
  • 准备生成的查询
  • 将变量绑定到占位符
  • 执行查询

以下是如何使用所有流行的PHP数据库驱动程序来做到这一点:

使用mysqli

当前的 PHP 版本允许您在一次调用中执行 prepare/bind/execute:

$type = 'testing';
$reporter = "John O'Hara";
$query = "INSERT INTO contents (type, reporter, description) 
             VALUES(?, ?, 'whatever')";
$mysqli->execute_query($query, [$type, $reporter]);

如果你的PHP版本是旧的,那么准备/绑定/执行必须显式完成:

$type = 'testing';
$reporter = "John O'Hara";
$query = "INSERT INTO contents (type, reporter, description) 
             VALUES(?, ?, 'whatever')";
$stmt = $mysqli->prepare($query);
$stmt->bind_param("ss", $type, $reporter);
$stmt->execute();

代码有点复杂,但所有这些运算符的详细说明都可以在我的文章《如何使用 Mysqli 运行 INSERT 查询》中找到,以及一个大大简化该过程的解决方案。

对于 SELECT 查询,可以使用与上述相同的方法:

$reporter = "John O'Hara";
$result = $mysqli->execute_query("SELECT * FROM users WHERE name=?", [$reporter]);
$row = $result->fetch_assoc(); // or while (...)

但同样,如果你的PHP版本是旧的,你将需要经历准备/绑定/执行例程,并添加对方法的调用,以便获得一个熟悉的,你可以从中获取数据,通常的方式:get_result()mysqli_result

$reporter = "John O'Hara";
$stmt = $mysqli->prepare("SELECT * FROM users WHERE name=?");
$stmt->bind_param("s", $reporter);
$stmt->execute();
$result = $stmt->get_result();
$row = $result->fetch_assoc(); // or while (...)
使用 PDO 添加数据文本
$type = 'testing';
$reporter = "John O'Hara";
$query = "INSERT INTO contents (type, reporter, description) 
             VALUES(?, ?, 'whatever')";
$stmt = $pdo->prepare($query);
$stmt->execute([$type, $reporter]);

在PDO中,我们可以将绑定和执行部分结合起来,这非常方便。PDO 还支持命名占位符,有些人认为这非常方便。

2.使用白名单过滤

任何其他查询部分(如 SQL 关键字、表或字段名称或运算符)都必须通过白名单进行筛选。

有时我们必须添加一个表示查询另一部分的变量,例如关键字或标识符(数据库、表或字段名称)。这种情况很少见,但最好做好准备。

在这种情况下,必须根据脚本中显式写入的值列表检查变量。这在我的另一篇文章中进行了解释,根据用户的选择在 ORDER BY 子句中添加字段名称

遗憾的是,PDO 没有标识符(表和字段名称)的占位符,因此开发人员必须手动过滤掉它们。这样的过滤器通常被称为“白名单”(我们只列出允许的值),而不是“黑名单”,我们列出不允许的值。

因此,我们必须在 PHP 代码中明确列出所有可能的变体,然后从中进行选择。

下面是一个示例:

$orderby = $_GET['orderby'] ?: "name"; // set the default value
$allowed = ["name","price","qty"]; // the white list of allowed field names
$key = array_search($orderby, $allowed, true); // see if we have such a name
if ($key === false) { 
    throw new InvalidArgumentException("Invalid field name"); 
}

方向应使用完全相同的方法,

$direction = $_GET['direction'] ?: "ASC";
$allowed = ["ASC","DESC"];
$key = array_search($direction, $allowed, true);
if ($key === false) { 
    throw new InvalidArgumentException("Invalid ORDER BY direction"); 
}

在这样的代码之后,可以安全地将 和 变量放入 SQL 查询中,因为它们要么等于允许的变体之一,要么会抛出错误。$direction$orderby

关于标识符的最后要提到的是,它们也必须根据特定的数据库语法进行格式化。对于MySQL,它应该是标识符周围的字符。因此,我们按示例排序的最终查询字符串将是backtick

$query = "SELECT * FROM `table` ORDER BY `$orderby` $direction";
1赞 Baloomba 8/31/2016 #3

答案很简单:

$query="SELECT * FROM CountryInfo WHERE Name = '".$name."'";

你可以定义任何你想要的东西。
另一种方式,复杂的方式,是这样的:
$name

$query = " SELECT '" . $GLOBALS['Name'] . "' .* " .
         " FROM CountryInfo " .
         " INNER JOIN District " .
         " ON District.CountryInfoId = CountryInfo.CountryInfoId " .
         " INNER JOIN City " .
         " ON City.DistrictId = District.DistrictId " .
         " INNER JOIN '" . $GLOBALS['Name'] . "' " .
         " ON '" . $GLOBALS['Name'] . "'.CityId = City.CityId " .
         " WHERE CountryInfo.Name = '" . $GLOBALS['CountryName'] .
         "'";

评论

2赞 Nico Haase 6/24/2021
....但这也是所有答案中最危险的。你甚至没有尝试以任何方式避免SQL注入,这样的代码永远不应该被使用
0赞 Mahmut Salman 9/5/2022
此外,它还会给出一个错误。语法错误。它应该是这样的:“。$variable ."
10赞 Stefan 12/13/2016 #4

为了避免 SQL 注入,使用 be 的 insert 语句

$type = 'testing';
$name = 'john';
$description = 'whatever';

$con = new mysqli($user, $pass, $db);
$stmt = $con->prepare("INSERT INTO contents (type, reporter, description) VALUES (?, ?, ?)");
$stmt->bind_param("sss", $type , $name, $description);
$stmt->execute();

评论

0赞 DrFaraday 4/19/2021
如果我尝试显示个人资料,并且在我的$stmt中有“SELECT * FROM Profile WHERE profile_id喜欢 (?)”怎么办?我只有一个参数要插入到我的 SQL 中,我该怎么做?
4赞 Tel 2/13/2017 #5

最好的选择是准备好的语句。弄乱引号和转义符是更难开始的工作,也很难维护。迟早你会不小心忘记引用一些东西,或者最终两次转义同一个字符串,或者搞砸类似的事情。可能需要数年时间才能找到这些类型的错误。

http://php.net/manual/en/pdo.prepared-statements.php