我有一个类似
的功能function getInfoById($id, $info) {
}
我们的想法是让查询为"SELECT $info FROM table WHERE id = $id"
这不适用于PDO,因为您无法转义列名称。我也不是真的想使用"SELECT *"
,因为这不会返回更大的结果集并使用更多内存吗?
答案 0 :(得分:15)
是的,PDO没有用于分隔表名和列名等标识符的内置函数。 PDO::quote()
函数仅适用于字符串文字和日期文字。
值得一提的是,当我使用Zend Framework时,我实现了quoteIdentifier()
函数。
你是对的SELECT *
抓取所有列,可能使用更多内存并破坏覆盖索引的好处。
我的建议是白名单列名。也就是说,确保$ info实际上为table
列命名。然后,您无需担心列名称不存在,或包含奇怪的字符或任何内容。您可以控制合法放入查询的列集。
您还应该分隔列名称。如果列名称包含标点符号,空格,国际字符或匹配SQL保留字,则必须使用分隔标识符。见Do different databases use different name quote?
function getInfoById($id, $info) {
// you can make this a literal list, or query it from DESC or INFORMATION_SCHEMA
$cols = array('col1', 'col2', 'col3');
if (array_search($info, $cols) === false) {
return false;
}
$sql = "SELECT `$info` FROM table WHERE id = :id";
$stmt = $pdo->prepare($sql);
if ($stmt === false) {
return false;
}
. . .
}
我在演示文稿SQL Injection Myths and Fallacies中展示了更多白名单示例。
答案 1 :(得分:6)
我会用一些正则表达式过滤掉它。把事情简单化。
此外,您应绑定$id
并将其设为:id
$info = preg_replace('/[^A-Za-z0-9_]+/', '', $info);
$stmt = $pdo->prepare('SELECT $info FROM table WHERE id = :id');
$stmt->bindParam(':id', $id);
$stmt->execute();
答案 2 :(得分:0)
使用引号和底线怎么办
$sql = 'SELECT * FROM table WHERE `' . substr($db->quote($field), 1, -1) . '` = :id';
这将删除转义字段周围的引号。