【问题标题】:PHP PDO doesn't select dataPHP PDO 不选择数据
【发布时间】:2013-02-17 17:37:08
【问题描述】:

当我在没有“准备”和“执行”的情况下获取数据时,代码工作正常。示例:

$this->db->query("select {$val} from {$table_name} where username={$username}")->fetch();

但是这段代码总是返回False:

$this->db->prepare("select :val from :table_name where username = :username")
->execute(array(':username'=>$username,':val'=>$val,':table_name'=>$this->table_name));

求助!:(

感谢您的回答。现在我的代码在这里:

$q=$this->db->prepare("select pass from nm_users where username = :username");
return $q->execute(array('username'=>$username));

返回值为True,但我无法从数据库中获取数据。

【问题讨论】:

标签: php pdo


【解决方案1】:

不要尝试将 PDO 用作流畅的接口。你不能这样做:

$db->prepare()->execute();

原因是流畅的接口只有在函数保证返回一个在这种情况下具有执行方法的对象时才起作用。

但是 prepare() 出错时返回 falsefalse 的值不是对象,也没有 execute() 方法。

您需要在每次prepare() 和每次execute() 后检查false

$stmt = $this->db->prepare("select :val from :table_name where username = :username");
if ($stmt === false) {
  $err = $this->db->errorInfo();
  error_log($err[2]);
}
$result = $stmt->execute(array(':username'=>$username,':val'=>$val,':table_name'=>$this->table_name));
if ($result === false) {
  $err = $stmt->errorInfo();
  error_log($err[2]);
}

如果你这样做,你会发现你的 prepare() 报告了一个错误:

您的 SQL 语法有错误;检查与您的 MySQL 服务器版本相对应的手册,以在第 1 行的 ''user' where username = 'bill'' 附近使用正确的语法

原因是查询参数仅适用于常量值。您不能将它们用于表名、列名、SQL 关键字、表达式、值列表等。

我推断:val 也意味着是一个动态列名,这也是不允许的。但在这种情况下,它不会导致错误,它只会用 $val 的值替换返回的每一行的文字字符串。

换句话说,用参数替换表名是错误的,因为你不能像SELECT * FROM 'user'(文字字符串,而不是表名)这样的查询,这就是参数的作用。这只是无效的 SQL。

但动态列名会执行类似SELECT 'val' FROM ... 的查询,这是合法的,但不会从名为 val 的列中进行选择,它会选择文字字符串常量 'val'。

【讨论】:

  • 匿名投反对票,请解释为什么你认为这个答案是错误的,也许我可以改进它。
  • 查看我上面编辑的代码,它准确地显示了如何访问 errorInfo() 以及您应该得到的错误。
  • 谢谢!我得到了这个错误。现在一切都清楚了。但是现在,当我更改查询时: $this->db->prepare ("select pass from nm_users where username=: username");变量 $result 应该返回一个 PDO 对象。但它返回 True。很奇怪。
  • 你应该把:放在参数名称旁边,不要用空格隔开。
  • 在我的代码中一切都是真的。在上面的消息中,StackOverflow 编辑器添加了一个空格。错误似乎很奇怪,我不相信我会找到解决方案。谢谢大家帮忙,可能是我的系统问题。
【解决方案2】:

不能为表名等设置参数,必须在数组中设置没有冒号:

$dbSelect=$db->prepare("select aField from aTable where username = :username")
$dbSelect->execute(array('username' => $username));

aFieldaTable 替换为标准str_replace 或类似的东西。

【讨论】:

【解决方案3】:

当您“准备”它时,表名必须包含在查询中,它不能作为其余参数动态添加。因此,您必须结合使用两种策略来完成查询:

$stmnt=sprintf('select %1$s from %2$s where username=:username',
               $val, $this->table_name);
if (FALSE===($query=$this->db->prepare($stmnt)))
    exit('Buggy statement: '.$stmnt);
$query->execute(array(':username'=>$username));

不幸的是,这也意味着您必须注意 $this->table_name 是否被正确转义!

【讨论】:

  • 感谢您的回答!但是当我从上面的代码结果应用 fetch() 方法时,我收到:调用非对象上的成员函数 fetch()。可能是我做错了什么......
  • OK,这意味着对象$query还没有被创建。在使用该对象之前,您确实应该检查一下。我将该检查添加到答案中。不确定是什么,可能$this->table_name 没有有效的表名?
  • 发生了一些错误:解析错误:语法错误,意外'$query'
  • 好吧好吧,我忘了;。我很抱歉!但有一个问题:你自己真的看不到吗?还是你总是复制和粘贴别人给你看的所有东西,然后沮丧地放弃,甚至不去理解你复制的是什么?
  • 好吧,不要。如果你这样做,你就不会成功。你会产生废话。
猜你喜欢
  • 2017-07-02
  • 1970-01-01
  • 2017-03-01
  • 1970-01-01
  • 2014-02-14
  • 2012-04-28
  • 1970-01-01
  • 2017-11-03
  • 2013-07-11
相关资源
最近更新 更多