php - 我可以使用参数化 SQL 动态选择数据库中的字段吗?

标签 php mysqli

我有一个数据库表 USER_OPTIONS,其中包含应用程序中各种选项的每一个字段,它看起来有效如下:

USER_ID | OPTION_1 | OPTION_2 | OPTION_3 | ... | OPTION 20
----------------------------------------------------------
 100    | true     | true     | false    | ... | false 
 101    | true     | true     | false    | ... | false 
 102    | false    | false    | false    | ... | true 
 ... etc etc

然后我的应用程序想要触发一个 AJAX 请求来调整这个表。

通过 AJAX 发送的信息是一组已更改的数据库字段及其新值(JSON 格式),例如

$my_new_settings === {
    'OPTION_1' : 'false',
    'OPTION_2' : 'false'
    'OPTION_20' : 'true'
}

然后我的计划是按照以下方式使用参数化 SQL 查询

$query_string = "UPDATE `USER_OPTIONS` 
               SET ? = ? 
               WHERE  
               `USER_ID` = ? 
               LIMIT 1 ;";

$my_user_id = 100;
$my_field_for_updating = "OPTION_1";
$my_new_field_value = "false";

if ( $query = $mysqli->prepare($query_string) ) {

    $query->bind_param("sss", $my_field_for_updating, $my_new_field_value, $my_user_id);
    $query->execute();
    $query->close();

}

然后遍历关联数组,从 $my_new_settings 中获取彼此的一对 $my_field_for_updating$my_new_field_value

但是。

我随后有discovered the following in the php.net manual :

(“标记”是参数化 SQL 查询中用于“?”变量的术语)

Note:

The markers are legal only in certain places in SQL statements. For example, they are allowed in the VALUES() list of an INSERT statement (to specify column values for a row), or in a comparison with a column in a WHERE clause to specify a comparison value.

However, they are not allowed for identifiers (such as table or column names), in the select list that names the columns to be returned by a SELECT statement, or to specify both operands of a binary operator such as the = equal sign. The latter restriction is necessary because it would be impossible to determine the parameter type. It's not allowed to compare marker with NULL by ? IS NULL too. In general, parameters are legal only in Data Manipulation Language (DML) statements, and not in Data Definition Language (DDL) statements.

这破坏了我提出的解决方案。

我的下一个想法是使用一个 SQL 查询来更新数据库中的所有字段,但只包含新更新的字段值。但是我发现这需要一个神奇的“什么都不做”变量来分配给我没有数据的字段的“标记”。

$query_string = "UPDATE `USER_OPTIONS` 
                   SET `OPTION_1` = ?,
                   SET `OPTION_2` = ?,
                   SET `OPTION_3` = ?,
                   ...
                   SET `OPTION_20` = ?
                   WHERE  
                   `USER_ID` = ? 
                   LIMIT 1 ;";

$my_user_id = 100;
$my_new_OPTION_1_value = 'false';
$my_new_OPTION_2_value = 'false';
$my_new_OPTION_20_value = 'true';
$magic_do_nothing_value = ????;

if ( $query = $mysqli->prepare($query_string) ) {

    $query->bind_param("sssssssssssssssssssss", 
       $my_new_OPTION_1_value, 
       $my_new_OPTION_2_value,
       $magic_do_nothing_value,
       $magic_do_nothing_value,
       ...
       $magic_do_nothing_value,
       $my_new_OPTION_20_value,
       $my_user_id
    );
    $query->execute();
    $query->close();

}

但是,我不知道 $magic_do_nothing_value 实际可能是什么(并且发现很难用谷歌搜索)。我尝试的所有操作要么引发错误,要么被解释为“错误”。

所以我的第一个问题是:MYSQL 数据库是否接受一个值作为“什么都不做”的信号?

假设没有并继续前进,我的下一个想法是将给定 USER_ID 的所有当前值从数据库中拖出,用 中的更改修改这些值$my_new_settings 然后用所有字段相应地更新数据库。

然而,这似乎有很多不必要的工作,尤其是与我的第一个解决方案相比。

这让我在这里要求一个更好的!

非常感谢您提出任何想法,我真的很想听听。它运行在 PHP 5.2 和一个基本的 MySQL 5.0.92 数据库上。

最佳答案

我会简单地动态构建 SQL,然后像您已经完成的那样绑定(bind)参数值。下面是一个使用类来处理动态数量参数的示例(类取自 PHP 文档)。请注意我还没有测试代码,但无论如何逻辑应该很清楚。

// This class will store the value for each query parameter
class BindParam {
  private $values = array(), $types = '';

  public function add($type, &$value) {
    $this->values[] = $value; 
    $this->types .= $type; 
  } 

  public function get() {
    return array_merge(array($this->types), $this->values); 
  } 
}

$my_new_settings = array(
    'OPTION_1' => 'false',
    'OPTION_2' => 'false',
    'OPTION_20' => 'true',
)


$bind_param = new BindParam();

$query_arr = array("UPDATE `USER_OPTIONS`");

// This loop will build the query and store each parameter value in bin_param instance
foreach($my_new_settings as $field_name => $field_value) {
  $query_arr[] = sprintf('`%s` = ?', $field_name);
  $bind_param->add('s', $field_value);
}

$query_arr[] = 'WHERE `USER_ID` = ?';
$query_arr[] = 'LIMIT 1 ;";

// Put all pieces together, forming an SQL command
$query_string = implode(' ', $query_arr);

$my_user_id = 100;
$my_field_for_updating = "OPTION_1";
$my_new_field_value = "false";

if($query = $mysqli->prepare($query_string)) {
  // Bind all parameter values saved earlier
  call_user_func_array(array($query, 'bind_param'), $bind_param->get())

  $query->execute();
  $query->close();
}

关于php - 我可以使用参数化 SQL 动态选择数据库中的字段吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12064118/

相关文章:

javascript - 如何根据浏览器提供不同的内容

php - 需要有关 mysql 查询的帮助

php - mysqli 或 PDO - 优缺点是什么?

php - 获取错误对象类 mysqli_result 无法转换为字符串

java - 对多个条件运行选择查询

php - 为什么 codeigniter 购物车类不允许名称中有任何特殊字符?

php - 插入查询在 php 中被触发两次

php - Android java post 图像限制 64 kb mysql blob

php - MySQL SELECT 查询四舍五入到小数点后 12 位

php - 无法使用 mysqli (PHP) 在表中插入行