2

アプリケーションのさまざまなオプションのそれぞれのフィールドを含むデータベーステーブル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_field_for_updating$my_new_field_valueからのペアを取得し$my_new_settingsます。

でも。

その後、php.netのマニュアルで次のことを発見しました

(「マーカー」は、パラメーター化されたSQLクエリの「?」変数に使用される用語です)

ノート:

マーカーは、SQLステートメントの特定の場所でのみ有効です。たとえば、INSERTステートメントのVALUES()リスト(行の列値を指定するため)、またはWHERE句の列との比較で比較値を指定することができます。

ただし、識別子(テーブル名や列名など)、SELECTステートメントによって返される列に名前を付ける選択リスト、または=等号などの二項演算子の両方のオペランドを指定することはできません。パラメータタイプを判別することは不可能であるため、後者の制限が必要です。マーカーをNULLと比較することはできませんか?もNULLです。一般に、パラメーターはデータ操作言語(DML)ステートメントでのみ有効であり、データ定義言語(DDL)ステートメントでは有効ではありません。

したがって、これは私の提案した解決策を台無しにしました。

次のアイデアは、データベース内のすべてのフィールドを更新する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実際に何であるかを知りません(そしてグーグルするのは難しいと思いました)。私が試したものはすべて、エラーをスローするか、「false」と解釈されました。

だから私の最初の質問は:MYSQLデータベースが「何もしない」ためのシグナルとして受け入れる値はありますか?

存在しないと仮定して、これから先に進むと、次の考えは、指定されたデータベースから現在のすべての値をドラッグUSER_IDし、変更を加えてこれらを修正し$my_new_settings、それに応じてすべてのフィールドでデータベースを更新することでした。

ただし、これは、特に私の最初のソリューションと比較すると、多くの不要な作業のように思われます。

それは私をここに導き、より良いものを求めます!

あなたが持っているかもしれないどんな考えにも感謝します、私はそれらを聞くことに本当に興味があります。これは、PHP5.2と基本的なMySQL5.0.92データベースで実行されています。

4

2 に答える 2

1

単純に SQL を動的に作成してから、既に行ったようにパラメーター値をバインドします。クラスを使用して動的な数のパラメーターを処理する例を次に示します (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();
}
于 2012-08-21T23:55:36.503 に答える
0

申し訳ありませんが、mysliまたはPDOの使用をまだ開始していません(怠惰な私:))しかし、mysqlテーブルに挿入または更新する必要がある場合に使用するこの関数を実装します。mysqliベースの使用法のために直接使用することはできませんが、アイデアが得られる場合があります。テーブルのフィールド名を検索し、それらを指定された配列キー名と照合します(指定されたプレフィックスがある場合でも)。また、$sql_conditionの更新用のキーフィールドと挿入される不要なデータをフィルタリングするための$exceptionsを指定する必要があります。

私の使用法では、キー名は「the_」で始まり、「t_」で始まる場合は自動的に無視されます。

  function q_put2($data_array=array() ,$table, $exceptions = '', $sql_type = 'insert', $sql_condition = NULL) {
      if($sql_condition!=NULL) $table_columns_filter=$sql_condition;
else $table_columns_filter="";
$table_columns_qs="SHOW COLUMNS FROM $table ;";
$table_columns_rs=mysql_query($table_columns_qs);

while ($row=mysql_fetch_row($table_columns_rs)){
   $table_columns[]=$row[0];
} 

$fields = '';$values = '';
foreach ($data_array as $field => $value) {
if(substr($field,0,4)=="the_")$field=substr($field,4);
    if(substr($field,0,2)!="t_" && !strstr($exceptions,$field) &&  in_array($field,$table_columns)){
        $value = mysql_real_escape_string($value);
        if ($sql_type == 'insert') {
        $fields .= "$field, ";
        $values .= "'$value', ";
        }
        else {
            $fields .= "$field = '$value', ";
        }
    }
}
$fields = preg_replace('/, $/', '', $fields);
$values = preg_replace('/, $/', '', $values);

if ($sql_type == 'insert') {
 $sql = "INSERT INTO $table ($fields) VALUES ($values)";
}
elseif ($sql_type == 'update') {
 if (!isset($sql_condition)) {
   echo 'ERROR: You must enter a sql condition!';
   exit;
 }
 $sql = "UPDATE $table SET $fields WHERE $sql_condition";}
else {
 echo 'ERROR: Invalid input for argument $sql_type: must be "insert" or "update"';
 exit;
}
if ($q_select_rs=mysql_query($sql)) {
return true;
} 
else 
{
return false;
}
}
于 2012-08-22T00:06:32.790 に答える