I have a table like this:
I receive an array like this:
$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)
);
My question is how I can update the table just with one query like this:
$query = "UPDATE tbl_name SET available='".$data[0]['available']."'" WHERE conditon1";
I mean update table once instead of 5 query.
Possible duplicate of this one. In a nutshell - you need to use either CASE
conditional or INSERT ... ON DUPLICATE KEY UPDATE
construct.
In pure MySQL, you could use a CASE
expression in the UPDATE
to handle this:
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)
If, on the other hand, you wanted to iterate over your array of arrays and then issue UPDATE
statements, you could try the following:
foreach ($data as $entry) {
$query = "UPDATE tbl_name SET available=".$entry['available']." WHERE d_id=".$entry['d_id'];
// execute $query ...
}
Based on the data you have provided, where all rows reference the same columns, and always update the same column, you can create a simple CASE
expression:
/* 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`
SET `available` =
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
";
}
/* Never forget the ELSE clause! */
$sql .= "ELSE `available`
END
";
}
return $sql;
}
This test program:
$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);
outputs:
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
Note:
Never forget the ELSE
clause in a CASE WHEN
update. If you do, then all the non-matching rows will be overwritten with a blank value.
This code blindly assumes that the data contains the expected indexes, and that the data is of the appropriate type.
Some say that you should include a WHERE
clause to limit the number of rows to be updated for performance reasons. I haven't seen any data to back this up, but if it is a concern, then a simple improvement might be to narrow it down using the d_id
column. Just add the follow at the end of the CASE WHEN
query:
$ids = array_column ($data, 'd_id');
$sql .= ' WHERE `d_id` IN (' . implode (', ', $ids) . ")
";
You still need the ELSE
in the CASE
expression because this WHERE
clause is not guaranteed to exclude all the unwanted rows. Writing a complete WHERE
clause will probably be much more complicated, depending on the exact nature of your data.