使用PDO转义列名称

时间:2012-11-19 05:39:51

标签: php pdo

我有一个类似

的功能
function getInfoById($id, $info) {

}

我们的想法是让查询为"SELECT $info FROM table WHERE id = $id"

这不适用于PDO,因为您无法转义列名称。我也不是真的想使用"SELECT *",因为这不会返回更大的结果集并使用更多内存吗?

3 个答案:

答案 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';

这将删除转义字段周围的引号。