首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何将动态构造的ext/mysql查询转换为PDO预准备语句?

如何将动态构造的ext/mysql查询转换为PDO预准备语句?
EN

Stack Overflow用户
提问于 2012-09-08 09:40:44
回答 1查看 1.4K关注 0票数 9

我正在将我的一些使用ext/mysql (mysql_*()函数)的代码转换为PDO和准备好的语句。以前,当我动态构造查询时,我只是通过mysql_real_escape_string()传递字符串,并将它们直接放到查询中,但现在我发现,在执行查询时,需要将值作为数组传递,或者在执行之前绑定变量。

如何将旧代码转换为使用新的数据库驱动程序?

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2012-09-08 09:40:44

要将查询从ext/mysql迁移到PDO准备好的语句,需要在许多方面采用新的方法。在这里,我将介绍几个经常需要执行的常见任务。这并不意味着要详尽地匹配每种可能的情况,它只是为了演示在动态生成查询时可以使用的一些技术。

在我们开始之前,有几件事要记住--如果有什么不对劲,在提问之前检查一下这个列表!

如果不显式禁用模拟mysql_real_escape_string().,

  • 查询并不比使用 prepares更安全完整explanation.
  • It的See this不能在单个查询中混合使用命名占位符和问号占位符。在你开始构造你的查询之前,你必须决定使用另一个,你不能半途而废预准备语句中的through.
  • Placeholders只能用于值,它们不能用于对象名。换句话说,您不能使用占位符动态指定数据库、表、列或函数名,或任何SQL关键字。一般来说,如果你发现你需要这样做,你的应用程序的设计是错误的,你需要重新检查它。
  • 任何用于指定数据库/表/列标识符的变量都不应该直接来自用户输入。换句话说,不要使用$_POST$_GET$_COOKIE或来自外部源的任何其他数据来指定列名。在使用此数据构造动态查询之前,应对其进行预处理。
  • PDO命名占位符在查询中指定为:name。在传递数据以供执行时,相应的数组键可以选择包含前导:,但这不是必需的。占位符名称应仅包含字母数字characters.
  • Named占位符不能在查询中多次使用。要多次使用相同的值,必须使用多个不同的名称。如果查询有许多重复值,请考虑使用问号占位符。
  • 使用问号占位符时,传递的值的顺序很重要。还需要注意的是,占位符位置是1索引的,而不是0索引的。

下面的所有示例代码都假设已经建立了数据库连接,并且相关的PDO实例存储在变量$db中。

使用关联数组作为列/值列表

要做到这一点,最简单的方法是使用命名占位符。

使用ext/mysql,可以在构造查询时对这些值进行转义,并将转义的值直接放入查询中。在构造PDO prepared语句时,我们使用数组键来指定占位符名称,因此可以将数组直接传递给PDOStatement::execute()

在本例中,我们有一个由三个键/值对组成的数组,其中键表示列名,值表示列的值。我们希望选择任何列都匹配的所有行(数据具有OR关系)。

代码语言:javascript
复制
// The array you want to use for your field list
$data = array (
  'field1' => 'value1',
  'field2' => 'value2',
  'field3' => 'value3'
);

// A temporary array to hold the fields in an intermediate state
$whereClause = array();

// Iterate over the data and convert to individual clause elements
foreach ($data as $key => $value) {
    $whereClause[] = "`$key` = :$key";
}

// Construct the query
$query = '
  SELECT *
  FROM `table_name`
  WHERE '.implode(' OR ', $whereClause).'
';

// Prepare the query
$stmt = $db->prepare($query);

// Execute the query
$stmt->execute($data);

使用数组构造IN (<value list>)子句的值列表

实现这一点的最简单方法是使用问号占位符。

这里我们有一个由5个字符串组成的数组,我们想要匹配一个给定的列名,并返回列值至少与5个数组值中的一个匹配的所有行。

代码语言:javascript
复制
// The array of values
$data = array (
  'value1',
  'value2',
  'value3',
  'value4',
  'value5'
);

// Construct an array of question marks of equal length to the value array
$placeHolders = array_fill(0, count($data), '?');

// Normalise the array so it is 1-indexed
array_unshift($data, '');
unset($data[0]);

// Construct the query
$query = '
  SELECT *
  FROM `table_name`
  WHERE `field` IN ('.implode(', ', $placeHolders).')
';

// Prepare the query
$stmt = $db->prepare($query);

// Execute the query
$stmt->execute($data);

如果您已经确定要使用带有命名占位符的查询,则该技术会稍微复杂一些,但不会太多。您只需循环遍历数组,将其转换为关联数组并构造命名占位符。

代码语言:javascript
复制
// The array of values
$data = array (
  'value1',
  'value2',
  'value3',
  'value4',
  'value5'
);

// Temporary arrays to hold the data
$placeHolders = $valueList = array();

// Loop the array and construct the named format
for ($i = 0, $count = count($data); $i < $count; $i++) {
  $placeHolders[] = ":list$i";
  $valueList["list$i"] = $data[$i];
}

// Construct the query
$query = '
  SELECT *
  FROM `table_name`
  WHERE `field` IN ('.implode(', ', $placeHolders).')
';

// Prepare the query
$stmt = $db->prepare($query);

// Execute the query
$stmt->execute($valueList);
票数 15
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/12327363

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档