Nasıl tek bir MySQL sorgusu ile bir tabloda birden kayıtları güncelleştirmek mi?

6 Cevap php

Tek bir sorgu kullanarak bir MySQL tablodaki birden fazla kayıt güncellemek istiyorum. Temel olarak, bu farklı tarihlerde farklı insanlar için atamaları sahip olan bir görevleri tablodur. Bu atamaları değişti ve online form aracılığıyla teslim edildiğinde (hemen hemen tüm bekleyen atamalar) teslim alır POST verilerinin bir çok şey var. Ben bütün bu bilgileri sıralar ve ben bunun dışında istediğini alır bir algoritma yazdım, ama ben MySQL tablosunu güncelleştirmek için sorguyu yazmaya şaşırıp:

  // Find the modified records and save their information
  $update = 0;
  for ( $n = 0; $n < $total_records; $n++ )
  {
     if ( $_POST['update'.$n] == true )
     {
        $updates_arr[$update] = array( intval($_POST['user_id'.$n]), intval($_POST['task'.$n]), $_POST['date'.$n] );
        $update++;
     }
  }

  if ( $mysql_db = OpenDatabase() )
  {
     $query  = "UPDATE tasks_tbl";
     if ( $updates_arr[0] )
     {
        $query .= "   SET task = ".$updates_arr[0][1]." WHERE user_id = ".$updates_arr[0][0]." AND date = ".$updates_arr[0][2];
     }

     for ( $n = 1; $n < $updates; $n++ )
     {
        $query .= ",   SET task = ".$updates_arr[$n][1]." WHERE user_id = ".$updates_arr[$n][0]." AND date = ".$updates_arr[$n][2];
     }

     $result = mysql_query( $query, $mysql_db );

     if ( $result )
     {
        $page .= "<p>Success!</p>\n\n";
     }
     else
     {
        $page .= "<p>Error: ".mysql_error()."</p>\n\n";
     }
  }

Bu oluşturulan sorgu:

UPDATE tasks_tbl 
   SET task = 1 
 WHERE user_id = 16 
   AND date = 2010-05-05,  
   SET task = 1 
 WHERE user_id = 17 
   AND date = 2222-02-22

Herhangi bir öneriniz mutluluk duyacağız. Teşekkürler.

6 Cevap

Öneriler için teşekkürler, herkese. Görünüşe göre ben umduğu gibi yapmak gibi basit olacak değil gibi ben, birden fazla sorgu ile gidiş sona erdi.

    foreach ( $updates_arr as $record => $data ):
       $query  = "UPDATE tasks_tbl";
       $query .= "   SET task = ".$data[1];
       $query .= "   WHERE task_id = ".$data[0];
       $result = mysql_query( $query, $mysql_db );
       if ( !$result )
       {
          break;
       }
       endforeach;

Böyle bir sorgu oluşturabilirsiniz:

UPDATE tasks_tbl SET task=1 WHERE 
    (user_id=16 AND date='2010-05-05') OR
    (user_id=17 AND date='2010-02-22')

Orada (... and ...) or (... and ...) yapıları (birleştirdiğiniz alanlar ve params kullanarak önlemek için kesmek şunlardır: "concat(user_id, date) = '". $user_id. $date. "'", ama onlar biraz daha yavaş çalışır.

PHP kodu:

for ($i = 0; !empty($_POST['update'. $i]; $i++)
    if (intval($_POST['task'.$i]) == 1)
        $cond[] = '(user_id='. intval($_POST['user_id'. $i]).
        ' and date=\''. mysql_real_escape_string($_POST['date'.$i]). '\')';

$query = 'UPDATE tasks_tbl SET task=1 WHERE '. implode(' OR ', $cond). ')';

Eğer tek bir sorguda bunu yapmak gerekir neden Edit: Oldukça anlamıyorum. task Kaç değerler olabilir? 1, 2, 3 ya da daha fazla? 3 değerleri ile, iç içe IF(...) işlevlerini kullanabilirsiniz:

UPDATE tasks_tbl SET task=if('. <imploded tasks with value 1>. ', 1, if('.
<tasks with value 2>. ', 2, if('. <tasks with 3>. ', 3,
task))) /* leave as is otherwise */

Yoksa benim verdiğim kodu basit bir halka koymak olabilir:

for ($j = 1; $j <= 3; $j++)
    for ($i = 0; !empty($_POST['update'. $i]; $i++)
        if (intval($_POST['task'.$i]) == 1)
            $cond[] = '(user_id='. intval($_POST['user_id'. $i]).
            ' and date=\''. mysql_real_escape_string($_POST['date'.$i]). '\')';

    mysql_query('UPDATE tasks_tbl SET task=1 WHERE '. implode(' OR ', $cond). ')');

Ben burada mimarisi ile katılmıyorum, ama şu çalışmalıdır. Kendi sorumluluğunuzdadır kullanın:

UPDATE
     Tasks_Table
SET
     task =
          CASE
               WHEN user_id = 16 AND date = 2010-05-05 THEN 1
               WHEN user_id = 17 AND date = 2222-02-22 THEN 1
               ...
          END
WHERE
     (user_id = 16 AND date = 2010-05-05) OR
     (user_id = 17 AND date = 2222-02-22) OR
     ...

Sizin örnekte tüm durumlarda = 1 görevi vardır, ama CASE deyimi ile size her durum için gerekenleri olmalarını değiştirebilirsiniz. Sana dize binayı terk edeceğiz.

Ben (bir işlem içinde gerekirse) veriler üzerinde hazırlanmış sorgu ve döngü kullanmayı tercih ediyorum. İşte bu basit Düzeltilebilirlik için daha iyi olduğunu anlamak için yapar.

Sizin kod sorguları ortadan kaldırmak olacaktır hazırlanan çok sql injection güvensizlik, kokuyor.

Bkz: http://www.php.net/manual/en/mysqli.prepare.php ya da daha iyisi ile PDO prepare:

Bunu arıyoruz:

UPDATE tasks_tbl 
   SET task = 1 
 WHERE (user_id = 16 AND date = 2010-05-05) 
       OR (user_id = 17 AND date = 2222-02-22)

Or you are trying to set 'task' to different values in different rows with a single statement? The latter is just not possible

Ben bu deyimi ile mümkün olduğunu sanmıyorum. Sen ayrı UPDATE deyimleri oluşturmak gerekir:

UPDATE tasks_tbl SET task = 1 WHERE user_id = 16 AND date = 2010-05-05;
UPDATE tasks_tbl SET task = 1 WHERE user_id = 17 AND date = 2222-02-22

Sen ayrılmış bir dize olarak () mysql_query içine geçebilir ';' Eğer kabul mysql ayarlarsanız multiple queries:

Multiple queries seem to be supported. You just have to pass flag 65536 as mysql_connect's 5 parameter (client_flags)