当前位置:  开发笔记 > 编程语言 > 正文

PHP PDO语句可以接受表名或列名作为参数吗?

如何解决《PHPPDO语句可以接受表名或列名作为参数吗?》经验,为你挑选了3个好方法。

为什么我不能将表名传递给准备好的PDO语句?

$stmt = $dbh->prepare('SELECT * FROM :table WHERE 1');
if ($stmt->execute(array(':table' => 'users'))) {
    var_dump($stmt->fetchAll());
}

是否有另一种安全的方法将表名插入SQL查询?安全我的意思是我不想这样做

$sql = "SELECT * FROM $table WHERE 1"

Noah Goodric.. 206

表和列名称不能由PDO中的参数替换.

在这种情况下,您只需手动过滤和清理数据.一种方法是将速记参数传递给将动态执行查询的函数,然后使用switch()语句创建用于表名或列名的有效值的白名单.这样,用户输入就不会直接进入查询.例如:

function buildQuery( $get_var ) 
{
    switch($get_var)
    {
        case 1:
            $tbl = 'users';
            break;
    }

    $sql = "SELECT * FROM $tbl";
}

通过不保留默认情况或使用返回错误消息的默认情况,您可以确保仅使用您想要使用的值.



1> Noah Goodric..:

表和列名称不能由PDO中的参数替换.

在这种情况下,您只需手动过滤和清理数据.一种方法是将速记参数传递给将动态执行查询的函数,然后使用switch()语句创建用于表名或列名的有效值的白名单.这样,用户输入就不会直接进入查询.例如:

function buildQuery( $get_var ) 
{
    switch($get_var)
    {
        case 1:
            $tbl = 'users';
            break;
    }

    $sql = "SELECT * FROM $tbl";
}

通过不保留默认情况或使用返回错误消息的默认情况,您可以确保仅使用您想要使用的值.


+1用于白名单选项,而不是使用任何类型的动态方法.另一种替代方法可能是将可接受的表名映射到具有与潜在用户输入相对应的键的数组(例如`array('u'=>'users','t'=>'table','n'=>'nonsensitive_data ')`等)
读到这个,我发现这里的例子为坏输入生成了无效的SQL,因为它没有`default`.如果使用这种模式,你应该将你的`case`s标记为`default`,或者添加一个明确的错误情况,例如`default:throw new InvalidArgumentException;`
我在想一个简单的`if(in_array($ tbl,['users','products',...]){$ sql ="SELECT*FROM $ tbl";}`.感谢你的想法.
我想念`mysql_real_escape_string()`。也许在这里我可以说出来而无需有人说:“但是PDO并不需要它”

2> IMSoP..:

要理解为什么绑定表(或列)名称不起作用,您必须了解预处理语句中的占位符如何工作:它们不是简单地替换为(适当转义的)字符串,而是执行生成的SQL.相反,DBMS要求"准备"一个语句,它会提供一个完整的查询计划,说明它将如何执行该查询,包括它将使用哪些表和索引,无论您如何填充占位符,这些表和索引都是相同的.

SELECT name FROM my_table WHERE id = :value无论你替换什么,计划都是一样的:value,但看似相似SELECT name FROM :table WHERE id = :value无法计划,因为DBMS不知道你实际上要从哪个表中选择.

这不是PDO之类的抽象库可以或应该解决的问题,因为它会破坏预准备语句的两个关键目的:1)允许数据库提前决定如何运行查询,并使用相同的方法计划多次; 2)通过将查询逻辑与变量输入分开来防止安全问题.



3> Don..:

我看到这是一个旧帖子,但我发现它很有用,并且我认为我会分享一个类似于@kzqai建议的解决方案:

我有一个函数接收两个参数,如...

function getTableInfo($inTableName, $inColumnName) {
    ....
}

在内部我检查我设置的数组,以确保只有"祝福"表的表和列可访问:

$allowed_tables_array = array('tblTheTable');
$allowed_columns_array['tblTheTable'] = array('the_col_to_check');

然后在运行PDO之前的PHP检查看起来像......

if(in_array($inTableName, $allowed_tables_array) && in_array($inColumnName,$allowed_columns_array[$inTableName]))
{
    $sql = "SELECT $inColumnName AS columnInfo
            FROM $inTableName";
    $stmt = $pdo->prepare($sql); 
    $stmt->execute();
    $result = $stmt->fetchAll(PDO::FETCH_ASSOC);
}


有利于简短的解决方案,但为什么不只是`$ pdo-> query($ sql)`
推荐阅读
臭小子
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有