使用mysql列的数字名称对mysql进行PDO查询。如何正确执行

时间:2014-12-31 03:42:29

标签: php mysql pdo

我在mysql表中有一个字段叫做“1”,这是一个数字......

我的PDO代码是:

$category = 1;

$stmt = $conn->prepare("SELECT * FROM account where :category = '1'");
$stmt->bindParam(':category', $category, PDO::PARAM_INT);
$stmt->execute(); 

它不起作用,因为在mysql中我必须使用:

SELECT * FROM account where `1` = '1';

而不是:

SELECT * FROM account where 1 = '1';

我怎么能用我的PDO做到这一点?

THX

1 个答案:

答案 0 :(得分:1)

PDO does not permit you to use a bound parameter as a column or table identifier因此无法直接将:categoryprepare()/execute()一起使用,并成功替换数字列名称。

但是,如果您可以安全地从下拉菜单中验证数字列名称以证明它在可接受的范围内并且确实是一个整数,那么在查询中使用变量是安全的。您需要使用反引号引用它,如您所知。

使用ctype_digit($category)preg_match('/^\d+$/', $category)之类的表达式对其进行验证,并测试它是否在您拥有列名的整数范围内。

// Validate $cateogry
// Assuming it came from $_POST['category']
$category = isset($_POST['category']) ? $_POST['category'] : null;

// And assuming the possible range was 1 - 4
// Ensure the input value was an integer with ctype_digit()
if (ctype_digit($category) && $category >= 1 && $category <=4) {
  // Execute the query with a backtick-quoted $category
  // Since you aren't going to bind any params, you can skip the overhead of
  // prepare()/bindParam()/execute() and just call query() instead
  $result = $conn->query("SELECT * FROM account where `$category` = '1' order by rand()");
  if ($result) {
    // Fetch rows and do whatever you planned with them
    $rows = $result->fetchAll(PDO::FETCH_ASSOC);
  }
}
else {
  // Invalid value, don't perform your query, show an error, etc....
}

如果您没有安装ctype扩展程序(您可能已经安装),请改用preg_match()示例。

另一种可能性是将in_array()range()一起使用,假设您的列按顺序命名。我可能更喜欢这个选择其他验证选项之一:

if (in_array($category, range(1, 4))) {
  // $category is valid - go ahead and query with it as above
} 

正如评论主题中所提到的,如果您处于更改此列命名方案的任何位置,那么这样做是个好主意。这简直令人困惑。如果您接受列名称的输入,它仍然不会改变您不能使用PDO参数的事实。您仍然需要根据可能的列名称数组对其进行验证。