我试图在目录中插入值.如果我的值中没有PHP变量,它就可以正常工作.当我把变量$type放在VALUES里面,这就不起作用了.我做错了什么?

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

推荐答案

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

  1. 任何代表SQL data literal的变量(或者简单地说,一个SQL字符串或一个数字)都必须通过一个准备好的语句添加.没有例外.
  2. 任何其他查询部分,例如SQL关键字、表或字段名或运算符,都必须通过white list进行筛选.

因此,由于您的示例只涉及数据文本,所以必须通过占位符(也称为参数)添加所有变量.为此:

  • 在SQL语句中,将所有变量替换为placeholders
  • prepare生成的查询
  • bind个变量到占位符
  • execute.询问

下面是如何使用所有流行的PHP数据库驱动程序:

使用mysql ext添加数据文本

这样的司机doesn't exist岁.

Adding data literals using mysqli

$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查询,您只需添加一个对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还支持一些非常方便的命名占位符.

添加关键字或标识符

有时,我们必须添加一个代表查询另一部分的变量,例如关键字或标识符(数据库、表或字段名).这是一个罕见的病例,但最好做好准备.

在这种情况下,必须对照脚本中写入的值列表判断变量.这在我的另一篇文章《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个字符.因此,我们的order by示例的最终查询字符串是

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

Mysql相关问答推荐

MySQL在定义表的位置后抛出错误

在 postgresql 中实现 UML 类:创建类型与创建表

如何判断嵌套查询返回的元组中的每个条目是否相同?

MYSQL 或 Laravel Eloquent 如何从这个订单中统计细节

如何查询打印已售罄的产品? [MYSQL]

SUBSTRING_INDEX 获取第 n 个值

MySQL查询根据同一表中其他字段的值更新表中的字段

如何过滤表格,以便它显示最新的数据?

如何在 SQL 的计算列中显示小数点后两位?

Docker(Apple Silicon/M1 Preview)MySQL“ list 列表条目中没有与 linux/arm64/v8 匹配的 list ”

LEFT JOIN 仅第一行

如何使用axios发布查询参数?

如何在 MySQL 8.0.11 中重置 root 密码?

MySQLdb、mysqlclient 和 MySQL 连接器/Python 有什么区别?

用于 UNIX 套接字文件的 mysqld_safe 目录“/var/run/mysqld”不存在

无法在 ubuntu 16 上使用 --skip-grant-tables 重置 root 密码

Laravel Eloquent 与查询构建器 - 为什么使用 eloquent 来降低性能

使用 Docker 我收到错误:“SQLSTATE[HY000] [2002] 没有这样的文件或目录”

的表存储引擎在按查询排序时没有此选项(错误 1031)

SQLSTATE [42000]:语法错误或访问冲突:1055 SELECT 列表的表达式 #3 不在 GROUP BY 子句中并且包含非聚合