只用一个查询更新一个包含数组的表

时间:2017-07-09 11:23:11

标签: php mysql

我有一张这样的表:

enter image description here

我收到这样的数组:

 $data = array(
   array('m_id'=>1,'d_id'=>101,'available'=>0),
   array('m_id'=>1,'d_id'=>102,'available'=>1),
   array('m_id'=>1,'d_id'=>103,'available'=>1),
   array('m_id'=>1,'d_id'=>104,'available'=>0),
   array('m_id'=>1,'d_id'=>105,'available'=>0)
 );

我的问题是如何使用以下一个查询来更新表:

  $query = "UPDATE tbl_name SET available='".$data[0]['available']."'" WHERE conditon1";

我的意思是更新表一次而不是5次查询。

3 个答案:

答案 0 :(得分:2)

在纯MySQL中,您可以在CASE中使用UPDATE表达式来处理此问题:

UPDATE tbl_name
SET available = CASE WHEN d_id = 101 THEN 0
                     WHEN d_id = 102 THEN 1
                     WHEN d_id = 103 THEN 1
                     WHEN d_id = 104 THEN 0
                     WHEN d_id = 105 THEN 0 END
WHERE d_id IN (101, 102, 103, 104, 105)

另一方面,如果您希望遍历数组数组然后发出UPDATE语句,则可以尝试以下操作:

foreach ($data as $entry) {
    $query = "UPDATE tbl_name SET available=".$entry['available']." WHERE d_id=".$entry['d_id'];
    // execute $query ...
}

答案 1 :(得分:1)

this one可能重复。简而言之 - 您需要使用CASE条件或INSERT ... ON DUPLICATE KEY UPDATE构造。

答案 2 :(得分:0)

根据您提供的数据,所有行引用相同的列,并始终更新同一列,您可以创建一个简单的CASE表达式:

/* Mostly untested */

function update_array ($data)
{
  if (empty ($data))
    return NULL;

  if (count ($data) === 1) {

    /* Simple query for single update */

    $mi = $data[0]['m_id'];
    $di = $data[0]['d_id'];
    $av = $data[0]['available'];

    $sql = <<<_
UPDATE `tbl_name`
   SET `available` = $av
 WHERE `m_id`= $mi AND `d_id`= $di

_;

  } else {

    /* CASE WHEN query for multiple updates */

    $sql = "UPDATE `tbl_name`\n   SET `available` = \n           CASE ";

    foreach ($data as $d) {
      $mi = $d['m_id'];
      $di = $d['d_id'];
      $av = $d['available'];
      $sql .= "WHEN `m_id`=$mi AND `d_id`=$di THEN $av\n                ";
    }

    /* Never forget the ELSE clause! */

    $sql .= "ELSE `available`\n           END\n";
  }

  return $sql;
}

此测试程序:

$data = array(
  array('m_id'=>1, 'd_id'=>101, 'available'=>0),
  array('m_id'=>1, 'd_id'=>102, 'available'=>1),
  array('m_id'=>1, 'd_id'=>103, 'available'=>1),
  array('m_id'=>1, 'd_id'=>104, 'available'=>0),
  array('m_id'=>1, 'd_id'=>105, 'available'=>0)
);

echo update_array ($data);

输出:

UPDATE `tbl_name`
   SET `available` =
           CASE WHEN `m_id`=1 AND `d_id`=101 THEN 0
                WHEN `m_id`=1 AND `d_id`=102 THEN 1
                WHEN `m_id`=1 AND `d_id`=103 THEN 1
                WHEN `m_id`=1 AND `d_id`=104 THEN 0
                WHEN `m_id`=1 AND `d_id`=105 THEN 0
                ELSE `available`
           END

注意:

  • 从不忘记ELSE更新中的CASE WHEN条款。如果这样做,那么所有不匹配的行都将被空值覆盖。

  • 此代码盲目地假设数据包含预期的索引,并且数据属于适当的类型。

  • 有人说你应该包含一个WHERE子句来限制因性能原因而要更新的行数。我还没有看到任何数据支持这一点,但如果这是一个问题,那么一个简单的改进可能使用d_id列来缩小范围。只需在CASE WHEN查询末尾添加以下内容:

    $ids = array_column ($data, 'd_id');
    $sql .= ' WHERE `d_id` IN (' . implode (', ', $ids) . ")\n";
    

    您仍然需要ELSE表达式中的CASE,因为不保证此WHERE子句不会排除所有不需要的行。编写完整的WHERE子句可能要复杂得多,具体取决于数据的确切性质。