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

ltskdhd1  于 2023-05-12  发布在  PHP
关注(0)|答案(5)|浏览(100)

我正在尝试在内容表中插入值。如果VALUES中没有PHP变量,它可以正常工作。当我把变量$type放在VALUES里面时,这不起作用。我做错了什么?

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

b09cbbtk1#

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

1.使用预处理语句

这个规则涵盖了99%的查询,尤其是你的查询。任何表示 SQL数据文字 * 的变量(或者,简单地说-SQL字符串或数字)必须通过准备好的语句添加。 没有例外 *。
这种方法包括四个基本步骤

  • 在SQL语句中,用 * 占位符 * 替换所有变量
  • prepare 结果查询
  • bind 变量到占位符
    • 执行 * 查询

下面是如何使用所有流行的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版本很旧,那么prepare/bind/execute必须显式完成:

$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();

代码有点复杂,但所有这些操作符的详细解释可以在我的文章How to run an INSERT query using Mysqli中找到,以及一个大大简化该过程的解决方案。
对于SELECT查询,您可以使用与上面相同的方法:

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

但同样,如果你的PHP版本很旧,你需要执行prepare/bind/execute例程,并添加一个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关键字、表名或字段名、运算符等,必须通过白色名单过滤。
有时我们必须添加一个变量来表示查询的另一部分,例如关键字或标识符(数据库、表或字段名)。这是一个罕见的情况,但最好做好准备。
在这种情况下,必须根据脚本中显式编写的值列表检查变量。我在另一篇文章Adding a field name in the ORDER BY clause based on the user's choice中解释了这一点:
不幸的是,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"); 
}

在这样的代码之后,$direction$orderby变量都可以安全地放入SQL查询中,因为它们要么等于允许的变量之一,要么会抛出错误。
关于标识符,最后要提到的是,它们还必须根据特定的数据库语法进行格式化。对于MySQL,标识符周围应该有backtick个字符。因此,我们的orderby示例的最终查询字符串将是

$query = "SELECT * FROM `table` ORDER BY `$orderby` $direction";
nfeuvbwi

nfeuvbwi2#

为了避免SQL注入,插入语句中的be

$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();
dl5txlt9

dl5txlt93#

**最好的选择是准备好的语句。**乱用引号和转义是一项更难的工作,也很难维护。迟早你会不小心忘记引用某些东西,或者两次转义同一个字符串,或者搞砸类似的事情。可能要过好几年你才能找到那种虫子。

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

oyxsuwqo

oyxsuwqo4#

$type中的文本被直接替换到插入字符串中,因此MySQL得到:

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

请注意,测试中没有引号,您需要像这样将其放入:

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

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

hlswsv35

hlswsv355#

答案很简单:

$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'] .
         "'";

相关问题