我正在将我的所有查询切换为PDO格式,并且我遇到一个特别涉及IN()子句的问题。
$nba[0] = "Boston Celtics";
$nba[1] = "New York Knicks";
$nba[2] = "Houston Rockets";
$query = "SELECT game_id
FROM table
WHERE date_int >= :date_int
AND (home_team = :team OR away_team = :team)
AND home_team IN(:list)
AND away_team IN(:list)
ORDER BY game_date_int ASC
LIMIT 1";
$stmt = $db->prepare($query);
$stmt->execute(array(':date_int' => $limit, ':team' => $team, ':list' => implode(',', $nba)));
答案 0 :(得分:6)
IN
cannot be parameterized like other values。所以只需要使用内插占位符和值。我一直在考虑尝试在PHP中实现它一段时间。然而,我从来没有考虑过这个问题。
我还在查询中看到您有两次相同的命名参数(:list
)。如果您使用真实的预准备语句,这也是不可能的。 Note that when you are using the mysql driver and PDO you have to disable emulated prepared statements
答案 1 :(得分:4)
你可以这样解决这个问题:
$nba = array();
$nba[0] = "Boston Celtics";
$nba[1] = "New York Knicks";
$nba[2] = "Houston Rockets";
$params = array(':date_int' => $limit, ':team' => $team);
$nba_teams = array();
for($i=0;$i<count($nba);$i++){
$nba_teams[] = ':list' . $i;
$params[':list' . $i] = $nba[$i];
}
$query = "SELECT game_id
FROM table
WHERE date_int >= :date_int
AND (home_team = :team OR away_team = :team)
AND home_team IN(".implode(',', $nba_teams).")
AND away_team IN(".implode(',', $nba_teams).")
ORDER BY game_date_int ASC
LIMIT 1";
$stmt = $db->prepare($query, $params);
$stmt->execute();
尚未测试过,但我想你知道我在尝试什么
答案 2 :(得分:0)
PDO在这样的情况下非常弱,所以任务将非常辛苦
与任何其他API一样,PDO仅适用于初学者手册中的基本任务,并且对于任何现实生活中的问题都没有为开发人员提供真正的帮助。
因此,开发人员必须采用某种抽象库来让它完成所有肮脏的工作。
所以,我会给你一个safeMysql例子,它比PDO更好:
$nba[0] = "Boston Celtics";
$nba[1] = "New York Knicks";
$nba[2] = "Houston Rockets";
$query = "SELECT game_id
FROM table
WHERE date_int >= ?i
AND (home_team = ?s OR away_team = ?s)
AND home_team IN(?a)
AND away_team IN(?a)
ORDER BY game_date_int ASC
LIMIT 1";
$data = $db->getAll($query, $limit, $team, $team, $nba, $nba);
看 - 这段代码简洁明了。它只做有意义的事情,隐藏了绑定复杂数据的所有脏工作。 与丑陋的代码不同,您可以使用一些PHP和API函数,这些代码可读。这是重要的事情。你可以告诉这段代码在一年左右后会做什么。
NLZ的答案是一个完美的例子 - 代码被不必要且令人费解的代码所污染
当您查找代码时,您首先要寻找业务逻辑。而这样的无用的代码块,只是为了创建一小部分SQL查询,会让你头晕目眩,隐藏真实的事情。
在应该被移动到内部的某个地方。