在mysql中,“where column=?”这个问号的意义是什么?

mkh04yzy  于 2021-06-25  发布在  Mysql
关注(0)|答案(4)|浏览(503)

我在分析一些代码,发现了这个,

$sql = 'SELECT page.*, author.name AS author, updator.name AS updator '
     . 'FROM '.TABLE_PREFIX.'page AS page '
     . 'LEFT JOIN '.TABLE_PREFIX.'user AS author ON author.id = page.created_by_id '
     . 'LEFT JOIN '.TABLE_PREFIX.'user AS updator ON updator.id = page.updated_by_id '
     . 'WHERE slug = ? AND parent_id = ? AND (status_id='.Page::STATUS_REVIEWED.' OR status_id='.Page::STATUS_PUBLISHED.' OR status_id='.Page::STATUS_HIDDEN.')';

我在想“?”在where语句中的作用。它是某种参数保持器吗?

cgh8pdjw

cgh8pdjw1#

prepared语句在mysql中使用“?”来允许将参数绑定到语句。如果使用得当,被认为对sql注入更安全。这还允许更快的sql查询,因为请求只需编译一次,就可以重用。

g6ll5ycj

g6ll5ycj2#

这些都是事先准备好的陈述,事先准备好的陈述有两大好处:
查询只需要解析(或准备)一次,但可以使用相同或不同的参数执行多次。准备好查询后,数据库将分析、编译并优化执行查询的计划。对于复杂的查询,此过程可能会占用足够的时间,如果需要使用不同的参数多次重复同一查询,则会显著降低应用程序的速度。通过使用准备好的语句,应用程序避免了重复分析/编译/优化循环。这意味着准备好的语句使用更少的资源,因此运行得更快。
准备语句的参数不需要引用;驱动程序会自动处理这个问题。如果应用程序专门使用准备好的语句,那么开发人员可以确保不会发生sql注入(但是,如果查询的其他部分是使用非scaped输入构建的,那么sql注入仍然是可能的)。
http://php.net/manual/en/pdo.prepared-statements.php

iezvtpos

iezvtpos3#

? 在mysql中没有特殊意义 WHERE = 声明,仅在准备好的声明中
我们看到的最常见的情况是由于赋予 ? 通过一些web框架,比如php和rails。 ? 只是语法错误:

CREATE TABLE t (s CHAR(1));
SELECT * FROM t WHERE s = ?;

因为它没有被引用,而且在:

INSERT INTO t VALUES ('a');
INSERT INTO t VALUES ("?");
SELECT * FROM t WHERE s = '?';

它返回:

s
?

显然没有特别的意义。
MySQL5.0准备语句
mysql 5.0增加了prepared statement特性,其语义与web框架中的问号类似。
文档示例:

PREPARE stmt1 FROM 'SELECT SQRT(POW(?,2) + POW(?,2)) AS hypotenuse';
SET @a = 3;
SET @b = 4;
EXECUTE stmt1 USING @a, @b;

输出:

hypotenuse
5

这些字符也按预期转义特殊字符:

PREPARE stmt1 FROM 'SELECT ? AS s';
SET @a = "'";
EXECUTE stmt1 USING @a;

输出:

s
'

rails示例
例如,在rails中,问号被库的编程语言(ruby)的一个变量给出的参数所取代,例如:

Table.where("column = ?", "value")

它会自动引用参数以避免bug和sql注入,生成如下语句:

SELECT * FROM Table WHERE column = 'value';

如果出现以下情况,报价将拯救我们:

Table.where("column = ?", "; INJECTION")
8cdiaqws

8cdiaqws4#

问号表示稍后将被替换的参数。使用参数化查询比将参数直接嵌入查询更安全。
SQLServer调用这个参数化查询,oracle调用它绑定变量。
用法因执行查询所用的语言而异。
下面是一个如何从php使用它的示例。
假设 $mysqli 是数据库连接和 people 是一个有4列的表。

$stmt = $mysqli->prepare("INSERT INTO People VALUES (?, ?, ?, ?)");

$stmt->bind_param('sssd', $firstName, $lastName, $email, $age);

这个 'sssd' 是标识其余参数的标志,其中 s 表示字符串和 d 表示数字。

相关问题