【问题标题】:PDO prepare/execute SQL issuePDO 准备/执行 SQL 问题
【发布时间】:2014-09-16 04:53:30
【问题描述】:

我对 PDO 的预处理语句有疑问。

在下面的代码中,示例 1 使用准备好的语句。但是,此代码不会产生预期的结果。示例 2 产生了预期的结果,但没有使用准备好的语句。

示例 1 在 SQL 字符串中使用 ? 占位符,字符串值随后绑定到这些占位符,然后执行(如您所料)。

代码如下:

<?php

// debugging
error_reporting(E_ALL);
ini_set("display_errors", 1);

// db vars
$host = 'localhost';
$db_name = 'cakeTut'; 
$db_username = 'root';
$db_password = 'password'; 

// try to connect to db, else catch exception.
try{
    $pdo = new PDO('mysql:host='.$host.';dbname='.$db_name, $db_username, $db_password);
    $pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
}catch (PDOException $e){
    echo $e->getMessage();
    die();
}

///////////////////////////////////////
// Example 1
///////////////////////////////////////

// query vars
$tablename = 'users';
$id = 'id';
$first_name = 'first_name';
$last_name = 'last_name';

// query string w/placeholders, then prepare query
$sql = "SELECT ?, ?, ? FROM $tablename";
$query = $pdo->prepare($sql);

// binding query vars to placeholders in query string
$query->bindParam(1, $id, PDO::PARAM_STR);
$query->bindParam(2, $first_name, PDO::PARAM_STR);
$query->bindParam(3, $last_name, PDO::PARAM_STR);

// execute query & print out query details for debugging
$query->execute();
$query->debugDumpParams();

// fetch result set & print it
$resultSet = $query->fetchAll();    
print_r($resultSet);

// loop through result set and print cols.
foreach($resultSet as $row) {
    echo $row['id'] . " " . $row['first_name'] . " " . $row['last_name'];
    echo "<br>";
}

///////////////////////////////////////
// Example 2
///////////////////////////////////////

// create query string with out placeholders, prepare and execute
$sql = "SELECT `id`, `first_name`, `last_name` FROM `users`";
$query = $pdo->prepare($sql);
$query->execute();

// get result set & print it
$resultSet = $query->fetchAll();
print_r($resultSet);

// loop through result set and print cols.
foreach($resultSet as $row) {
    echo $row['id'] . " " . $row['first_name'] . " " . $row['last_name'];
    echo "<br>";
}

?>

这是代码的输出:

示例 1 $query-&gt;debugDumpParams();

SQL: [25] SELECT ?, ?, ? FROM users Params: 3 Key: Position #0: paramno=0 name=[0] "" is_param=1 param_type=2 Key: Position #1: paramno=1 name=[0] "" is_param=1 param_type=2 Key: Position #2: paramno=2 name=[0] "" is_param=1 param_type=2 

示例 1 print_r($resultSet);

Array ( [0] => Array ( [id] => id [0] => id [first_name] => first_name [1] => first_name [last_name] => last_name [2] => last_name ) [1] => Array ( [id] => id [0] => id [first_name] => first_name [1] => first_name [last_name] => last_name [2] => last_name ) [2] => Array ( [id] => id [0] => id [first_name] => first_name [1] => first_name [last_name] => last_name [2] => last_name ) [3] => Array ( [id] => id [0] => id [first_name] => first_name [1] => first_name [last_name] => last_name [2] => last_name ) [4] => Array ( [id] => id [0] => id [first_name] => first_name [1] => first_name [last_name] => last_name [2] => last_name ) )

循环通过示例 1 的结果集并打印 cols。:

id first_name last_name
id first_name last_name
id first_name last_name
id first_name last_name
id first_name last_name

示例 2 print_r($resultSet);

Array ( [0] => Array ( [id] => 3 [0] => 3 [first_name] => fiona [1] => fiona [last_name] => mac [2] => mac ) [1] => Array ( [id] => 4 [0] => 4 [first_name] => ronan [1] => ronan [last_name] => duddy [2] => duddy ) [2] => Array ( [id] => 5 [0] => 5 [first_name] => tom [1] => tom [last_name] => thumb [2] => thumb ) [3] => Array ( [id] => 30 [0] => 30 [first_name] => ronan [1] => ronan [last_name] => mcl [2] => mcl ) [4] => Array ( [id] => 31 [0] => 31 [first_name] => Admin [1] => Admin [last_name] => admin [2] => admin ) ) 

循环通过示例 2 的结果集并打印 cols。:

3 fiona mac
4 ronan duddy
5 tom thumb
30 ronan mcl
31 Admin admin

我错过了什么吗?上面代码中的两个示例不应该打印出相同的数据,即示例 2?我搜索了一下,示例 1 的代码与准备好的语句中的基本示例相匹配。

非常感谢, 罗南

【问题讨论】:

  • 你不能这样做 => SELECT ?, ?, ?
  • 您从哪里读到可以将列名或表名定义为参数?
  • 换一种说法——你使用绑定参数作为值,而不是列名或表名。
  • 换句话说,它不知道“提前”选择什么,因为它是未知的;被“质疑”?。这有点像把马车放在马前。当你问一个问题?,那是因为你还不知道答案,对吧? ;-) 好吧,你去吧;同样的事情也适用于此。为它设置一个变量而不是$column1="column"; 然后SELECT $column1...,如果这是你想要实现的。
  • 我现在明白了。好比喻弗雷德!非常感谢大家! :) 文档的链接类似地解释它:php.net/manual/en/pdo.prepare.php#111977

标签: php sql pdo prepared-statement


【解决方案1】:

Prepared 语句占位符只能表示查询中的 VALUES。您不能将它们用于表名、字段名或任何其他 SQL 关键字。

SELECT * FROM foo WHERE (somefield = ?) // ok
SELECT ? FROM foo WHERE (somefield = 2) // bad - cannot use for field name
SELECT * FROM ? WHERE   (somefield = 2) // bad cannot use for table name
SELECT * FROM foo WHERE (somefield = 2) ORDER BY somefield ? // again bad, can't use for sort order
SELECT * FROM foo WHERE (? = 2) // again bad, can't use for field name

【讨论】:

  • 谢谢马克!非常感谢。
  • 对于最后一个例子是否可以这样做:$sql = "SELECT * FROM foo WHERE ($somefield = 2)";Thanks
  • @ronanduddy:那不是占位符。那是 PHP 变量插值,并将查询打开到注入攻击。这不是你想做的事情。
【解决方案2】:

在我阅读时,您不能在 PDO 中为表/列名称使用参数。 http://php.net/manual/en/book.pdo.php

请注意:

不起作用:

$sth = $dbh->prepare('SELECT name, colour, calories FROM ?  WHERE calories < ?');

这行得通!

$sth = $dbh->prepare('SELECT name, colour, calories FROM fruit WHERE calories < ?');

【讨论】:

  • 感谢亚历克斯的帮助。
猜你喜欢
  • 1970-01-01
  • 2015-12-08
  • 2012-07-20
  • 2011-07-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-03-29
相关资源
最近更新 更多