Я хотел бы обновить несколько записей в таблице MySQL, используя один запрос. В принципе, это таблица задач, которая имеет назначения для разных людей в разные даты. Когда эти присвоения изменяются и отправляются через форму онлайн, есть много данных POST, которые отправляются (в значительной степени все ожидающие назначения). Я написал алгоритм, который сортирует всю эту информацию и получает то, что я хочу от нее, но я застрял в написании запроса для обновления таблицы MySQL:
// 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";
}
}
Это запрос, который сгенерирован:
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
Любые предложения будут оценены. Спасибо.
Спасибо за предложения, все. Я закончил с несколькими запросами, поскольку, по-моему, это было не так просто, как я надеялся.
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;
Вы можете создать такой запрос:
UPDATE tasks_tbl SET task=1 WHERE
(user_id=16 AND date='2010-05-05') OR
(user_id=17 AND date='2010-02-22')
Есть хаки, чтобы избежать использования конструкций (... and ...) or (... and ...)
(конкатенировать поля и параметры: "concat(user_id, date) = '". $user_id. $date. "'"
, но они работают немного медленнее.
Код PHP:
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). ')';
Изменить: Я не совсем понимаю, зачем вам нужно это делать в одном запросе. Сколько значений task
может иметь? 1, 2, 3 или еще много? С 3 значениями вы можете использовать вложенные функции IF(...)
:
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 */
Или вы можете поместить простой цикл в код, который я дал:
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). ')');
Я не согласен с вашей архитектурой здесь, но следующее должно работать. Используйте на свой страх и риск:
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
...
В вашем примере у вас есть задача = 1 во всех случаях, но с оператором CASE вы можете изменить их, чтобы быть тем, что вам нужно для каждого случая. Я оставлю вам строковое здание.
Я предпочел бы использовать подготовленный запрос и цикл над данными (внутри транзакции, если необходимо). Это упрощает понимание, что лучше для ремонтопригодности.
В вашем коде пахнет sql injection, безопасность, которую подготовленные запросы будут устранены.
Смотрите: http://www.php.net/manual/en/mysqli.prepare.php или даже лучше с PDO подготовить:
Вы ищете:
UPDATE tasks_tbl
SET task = 1
WHERE (user_id = 16 AND date = 2010-05-05)
OR (user_id = 17 AND date = 2222-02-22)
Или вы пытаетесь установить "задание" на разные значения в разных строках с одним выражением? Последнее просто невозможно
Я не думаю, что это возможно с одним утверждением. Вам нужно будет создать отдельные инструкции UPDATE:
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
Вы можете передать их в mysql_query() как одну строку, разделенную ';' если вы установите mysql для принятия нескольких запросов:
Кажется, что несколько запросов поддерживаются. Вам просто нужно передать флаг 65536 как Параметр mysql_connect 5 (Client_flags)