我知道这已被要求1000倍,但由于某些原因,我继续一声我的头agains墙..
这工作:
$sql = 'SELECT a.eventCode, a.eventTime, a.teamCode, a.playerCode, b.lastName, b.firstName, b.number, a.xCoord, a.yCoord, a.id ';
$sql = $sql . 'FROM events a, players b ';
$sql = $sql . 'WHERE a.regGUID in ( ' . $regGUID . ' ) and ';
$sql = $sql . 'a.playerCode=b.playerCode and a.gameCode = "' . $game . '" order by a.eventTime desc, a.actionCode asc';
$stmt = $db->prepare($sql);
$results = $stmt->execute();
这并不:
$sql = 'SELECT a.eventCode, a.eventTime, a.teamCode, a.playerCode, b.lastName, b.firstName, b.number, a.xCoord, a.yCoord, a.id ';
$sql = $sql . 'FROM events a, players b ';
$sql = $sql . 'WHERE a.regGUID in ( :regGUID ) and ';
$sql = $sql . 'a.playerCode=b.playerCode and a.gameCode = :game order by a.eventTime desc, a.actionCode asc';
$stmt = $db->prepare($sql);
$stmt->bindValue(':regGUID', $regGUID, PDO::PARAM_STR);
$stmt->bindValue(':game', $game, PDO::PARAM_STR);
$results = $stmt->execute();
我在想什么? 谢谢
问题就在这里:
$sql = $sql . 'WHERE a.regGUID in ( :regGUID ) and ';
$stmt->bindValue(':regGUID', $regGUID, PDO::PARAM_STR);
我假设$ regGUID是一个逗号分隔的加引号字串。
每个查询参数只接受单个标量值。 值的未列出 。
所以,你有两个选择:
继续插值$ regGUID字符串,即使您使用其它标值的参数。 但你还是要小心,避免SQL注入,所以你必须正确地形成$ regGUID字符串。 你不能只是调用PDO ::引用()在整个字符串,这将使它包含的UUID和逗号一个单引号字符。 你必须确保每个UUID字符串逃过并单独报价,然后一起破灭的列表,并将其插值到IN子句。
$regGUIDs = explode(',', $regGUID); $regGUIDs = array_map(function ($g) { return $db->quote($g); }, $regGUIDs); $regGUID = implode(',', $regGUIDs); $sql = $sql . 'WHERE a.regGUID in (' . $regGUID . ') and ';
explode()
的$ regGUID到一个数组,并添加一个查询参数为阵列中的每个元件。 插值查询参数占位符的动态列表。
$regGUIDs = explode(',', $regGUID); $params = array_fill(1, count($regGUIDs), '?'); $sql = $sql . ' WHERE a.regGUID in ( ' . implode(',', $params) . ' ) and ';
你可以在阵列的循环bindValue(),但请记住,其他参数也应通过位置的约束,叫不上名字。 PDO都有漏洞,使人们不开心的时候,你尝试在同一查询混合的两种不同风格的参数。
代替使用bindValue的(),我传递参数值的数组,以PDOStatement对象::执行(),它是要容易得多。
$paramValues = $regGUIDs;
$paramValues[] = $game;
$results = $stmt->execute($paramValues);
这确实已被要求1000倍。
准备的语句只能接受标量值 ,SQL查询的不是任意的部位。
您可以选择使用尽可能多的占位符,形成()语句,你必须投入,然后绑定逐一尽可能多的项目。
为了缓解这个任务可以使用一些辅助功能。
再说了,使用SafeMysql库这段代码可以写成
$sql = 'SELECT * FROM events a, players b WHERE regGUID in (?a) and';
$sql .= ' a.playerCode=b.playerCode and a.gameCode = ?s';
$sql .= ' order by a.eventTime desc, a.actionCode asc';
$results = $db->getAll($sql,$regGUID,$game);
需要注意的是$regGUID
应该是一个数组,不串和$results
已经包含了所有的请求数据,而无需任何进一步的处理。
什么是内容$regGUID
? 由于您使用的是in
条款,我怀疑一个逗号分隔的列表。
绑定到参数的变量是不喜欢代该字符串到查询; 这就像告诉MySQL的如何使用您的实际PHP变量。 所以,如果你喜欢一个字符串绑定'1,2,3'
的查询参数,它保持作为一个字符串,而没有重新解释为数字列表。
因此,如果$regGUID
是像"'AAA1', 'BBB2'"
,第一个查询变得
... WHERE a.regGUID in ( 'AAA1', 'BBB2' ) ...
但你的第二个查询更喜欢
... WHERE a.regGUID in ( '\'AAA1\', \'BBB2\'' ) ...
这等于说
... WHERE a.regGUID = '\'AAA1\', \'BBB2\'' ...
正如其他人的状态,你只能绑定一个标值的占位符。 因此,这意味着你实际上需要一个占位符,为您的每一个值IN
声明。 我通常做像下面这样。 应当指出的是,虽然我从来没有使用bindValue
所以如果有关于有是那么下面可能需要修改一样的mysqli引用的东西规则:
$regGUIDPlaceholders = array();
// prepare the placeholders
// assume regGUID is an array - if its a string then explode on whatever to make it an array
foreach($regGUID as $k => $v) {
$placeholder = ':regGUID' . $k;
$regGUIDPlaceholders[$key] = $value;
}
// prepare the IN statememnt
$in = sprintf('IN (%s)', implode(',', array_keys($regGUIDPlaceholders)));
$sql = 'SELECT a.eventCode, a.eventTime, a.teamCode, a.playerCode, b.lastName, b.firstName, b.number, a.xCoord, a.yCoord, a.id ';
$sql = $sql . 'FROM events a, players b ';
// USE the IN statement dynamically prepared above
$sql = $sql . 'WHERE a.regGUID '. $in . ' and ';
$sql = $sql . 'a.playerCode=b.playerCode and a.gameCode = :game order by a.eventTime desc, a.actionCode asc';
$stmt = $db->prepare($sql);
// bind each GUID to its placeholder
foreach($regGUIDPlaceholders as $placeholder => $value) {
$stmt->bindValue($placeholder, $value, PDO::PARAM_STR);
}
$stmt->bindValue(':game', $game, PDO::PARAM_STR);
$results = $stmt->execute();