如何将 prepare() 与动态列名一起使用?

Posted

技术标签:

【中文标题】如何将 prepare() 与动态列名一起使用?【英文标题】:How to use prepare() with dynamic column names? 【发布时间】:2015-06-19 13:28:57 【问题描述】:

我有一个函数,它以一个 sql 表列名字符串作为参数,返回 1 个字符串结果:

function myFunction($column_name) 
    return $wpdb->get_var($wpdb->prepare("SELECT %s FROM myTable WHERE user_id=%s", $column_name, $current_user->user_login));

但是,此代码不起作用,因为由于准备的性质,我不能将变量用于列名(和表名)。

这可行,但我认为它会带来安全问题:

return $wpdb->get_var('SELECT ' . $column_name . ' FROM myTable WHERE user_id=' . $current_user->user_login); 

我需要做什么才能在我的准备语句中使用动态列名?

【问题讨论】:

【参考方案1】:

您可以改用“已批准”值的列表,这样您就不会真正在查询中使用用户数据。像这样的:

$Approved = array ('firstname', 'lastname', 'birthdate') ;
$Location = array_search($ColumnName, $Approved) // Returns approved column location as int
if($Location !== FALSE) 
    // Use the value from Approved using $Location as a key
    $Query = $wpdb->Prepare('SELECT ' . $Approved[$Location] . ' FROM myTable WHERE user_id=:userid');
    $Query->Execute(array(
        :userid => $current_user->user_login
    ));

    return $Query;
 else 
    return false;

也许只获取所有(SELECT * 或 SELECT a、b、c、d)用户数据并将其保存到会话以供以后使用可能更容易?

【讨论】:

这行得通。但是,prepare() 中的 $Approved[$Location] 被篡改有多“安全”?谢谢! @Rollor 该代码不使用任何真正的动态值,仅使用 $Approved 数组中的值。只要您不允许以任何方式更改该数组,它将是安全的。它基本上是根据您手动设置的已批准值列表验证 $ColumnName 。如果我不验证,那么它将不会运行查询。在 Execute 中发送的值受到保护以防注入,因此无需验证/清除这些值。 ...既然$ColumnName别无选择,只能“通过”$Approved,我认为这是有道理的。 sanitize_text_field() 是否足以保证数据安全而不是列入白名单?

以上是关于如何将 prepare() 与动态列名一起使用?的主要内容,如果未能解决你的问题,请参考以下文章

将列名作为参数传递给 Redshift 中的“PREPARE”的问题

QSqlQuery 与列名 Sqlite 的 prepare 和 bindValue

C#如何将.OrderBy与多列一起使用并将列号解码为列名?

当列名包含特殊字符时,如何将 Convert 函数与 RowFilter/CustomFilter 一起使用?

将 ORMLite 与 Oracle 一起使用时,列名不是大写

oracle中如何对多张表进行动​​态选择查询?使用表名和列名作为其他表的值?