Я знаю, что вы можете вставить несколько строк одновременно, есть ли способ обновить несколько строк одновременно (как в одном запросе) в MySQL?
Изменить: например, у меня есть следующее
Name id Col1 Col2
Row1 1 6 1
Row2 2 2 3
Row3 3 9 5
Row4 4 16 8
Я хочу объединить все следующие обновления в один запрос
UPDATE table SET Col1 = 1 WHERE id = 1;
UPDATE table SET Col1 = 2 WHERE id = 2;
UPDATE table SET Col2 = 3 WHERE id = 3;
UPDATE table SET Col1 = 10 WHERE id = 4;
UPDATE table SET Col2 = 12 WHERE id = 4;
mysql
sql
sql-update
Teifion
источник
источник
Поскольку у вас есть динамические значения, вам нужно использовать IF или CASE для обновляемых столбцов. Это немного уродливо, но это должно сработать.
Используя ваш пример, вы можете сделать это следующим образом:
источник
$commandTxt = 'UPDATE operations SET chunk_finished = CASE id '; foreach ($blockOperationChecked as $operationID => $operationChecked) $commandTxt .= " WHEN $operationID THEN $operationChecked "; $commandTxt .= 'ELSE id END WHERE id IN ('.implode(', ', array_keys(blockOperationChecked )).');';
Вопрос старый, но я бы хотел расширить тему другим ответом.
Моя точка зрения заключается в том, что самый простой способ добиться этого - просто заключить несколько запросов в транзакцию. Принятый ответ
INSERT ... ON DUPLICATE KEY UPDATE
- хороший взлом, но нужно помнить о его недостатках и ограничениях:"Field 'fieldname' doesn't have a default value"
предупреждение MySQL, даже если вы вообще не вставляете ни одной строки. Это может привести к неприятностям, если вы решите быть строгим и превратите предупреждения mysql в исключения времени выполнения в вашем приложении.Я сделал несколько тестов производительности для трех из предложенных вариантов, включая
INSERT ... ON DUPLICATE KEY UPDATE
вариант, вариант с предложением «case / when / then» и наивный подход с транзакцией. Вы можете получить код Python и результаты здесь . Общий вывод заключается в том, что вариант с оператором case оказывается в два раза быстрее, чем два других варианта, но написать для него правильный и безопасный для инъекций код довольно сложно, поэтому я лично придерживаюсь самого простого подхода: использования транзакций.Редактировать: Выводы Дакусана доказывают, что мои оценки производительности не совсем верны. Пожалуйста, посмотрите этот ответ для другого, более сложного исследования.
источник
Не уверен, почему еще одна полезная опция еще не упомянута:
источник
Все следующее относится к InnoDB.
Я чувствую, что знание скорости 3 различных методов очень важно.
Есть 3 метода:
Я только что проверил это, и метод INSERT был для меня в 6,7 раза быстрее, чем метод TRANSACTION. Я примерил набор из 3000 и 30000 строк.
Метод TRANSACTION по-прежнему должен запускать каждый отдельный запрос, который занимает время, хотя и выполняет результаты в памяти или что-то еще во время выполнения. Метод TRANSACTION также довольно дорог в журналах репликации и запросов.
Хуже того, метод CASE был в 41,1 раза медленнее, чем метод INSERT, с 30 000 записей (в 6,1 раза медленнее, чем TRANSACTION). И в 75 раз медленнее в MyISAM. Методы INSERT и CASE не превышают 1000 записей. Даже при 100 записях метод CASE БЫСТРО быстрее.
В общем, я считаю, что метод INSERT является лучшим и простым в использовании. Запросы меньше и их легче читать, и они занимают только 1 запрос действия. Это относится как к InnoDB, так и к MyISAM.
Бонусные вещи:
Решение задачи не по умолчанию поля INSERT, чтобы временно отключить соответствующие режимы SQL:
SET SESSION sql_mode=REPLACE(REPLACE(@@SESSION.sql_mode,"STRICT_TRANS_TABLES",""),"STRICT_ALL_TABLES","")
. Обязательно сохранитеsql_mode
первый, если вы планируете его вернуть.Что касается других комментариев, которые я видел, что, скажем, auto_increment увеличивается с использованием метода INSERT, похоже, это имеет место в InnoDB, но не в MyISAM.
Код для запуска тестов выглядит следующим образом. Он также выводит файлы .SQL для удаления накладных расходов интерпретатора php
источник
Использовать временную таблицу
источник
Это должно работать для тебя.
В руководстве MySQL есть ссылка для нескольких таблиц.
источник
Почему никто не упоминает несколько операторов в одном запросе ?
В php вы используете
multi_query
метод экземпляра mysqli.Из руководства по PHP
Вот результат по сравнению с другими 3 методами в обновлении 30000 raw. Код можно найти здесь, который основан на ответе @Dakusan
Транзакция: 5.5194580554962
Вставка: 0.20669293403625
Дело: 16.474853992462
Мульти: 0.0412278175354
Как видите, запрос с несколькими утверждениями более эффективен, чем самый высокий ответ.
Если вы получаете сообщение об ошибке, подобное этому:
Вам может понадобиться увеличить
max_allowed_packet
конфигурационный файл в mysql, который есть на моем компьютере,/etc/mysql/my.cnf
а затем перезапустить mysqld.источник
$mysqli->multi_query($sql)
заняло «0» секунд. Однако последующие запросы завершились неудачно, из-за чего я сделал это отдельной «программой».Существует параметр, который вы можете изменить, называемый «multi оператор», который отключает «механизм безопасности» MySQL, реализованный для предотвращения (более одной) команды внедрения. Типичный для «блестящей» реализации MySQL, он также не позволяет пользователю выполнять эффективные запросы.
Здесь ( http://dev.mysql.com/doc/refman/5.1/en/mysql-set-server-option.html ) приведена некоторая информация о реализации параметра в C.
Если вы используете PHP, вы можете использовать mysqli для нескольких операторов (я думаю, что php уже поставляется с mysqli)
Надеюсь, это поможет.
источник
mysqli::begin_transaction(..)
до отправки запроса иmysql::commit(..)
после. Или используйтеSTART TRANSACTION
как первый иCOMMIT
как последний оператор в самом запросе.Вы можете создать псевдоним той же таблицы, чтобы получить идентификаторы, по которым вы хотите вставить (если вы обновляете строку за строкой:
Кроме того, должно показаться очевидным, что вы также можете обновлять данные из других таблиц. В этом случае обновление удваивается как оператор «SELECT», предоставляя вам данные из таблицы, которую вы указываете. Вы явно указываете в своем запросе значения обновления, поэтому вторая таблица не изменяется.
источник
Вы также можете быть заинтересованы в использовании обновлений, что также возможно.
Изменить: если значения, которые вы обновляете, не поступают откуда-то еще из базы данных, вам нужно будет выполнить несколько запросов на обновление.
источник
И теперь легкий путь
источник
использование
Пожалуйста, обратите внимание:
источник
Следующее обновит все строки в одной таблице
Следующая обновит все строки, где значение Column2 больше 5
Существует весь пример Unkwntech по обновлению более чем одной таблицы.
источник
Да .. это возможно с помощью оператора INSERT ON DUPLICATE KEY UPDATE sql .. синтаксис: INSERT INTO table_name (a, b, c) ЗНАЧЕНИЯ (1,2,3), (4,5,6) ON DUPLICATE KEY UPDATE a = ЗНАЧЕНИЯ (а), б = ЗНАЧЕНИЯ (б), с = ЗНАЧЕНИЯ (с)
источник
Это должно достичь того, что вы ищете. Просто добавьте больше идентификаторов. Я проверил это.
источник
// Вы просто строите это как php
Таким образом, вы можете обновить таблицу отверстий одним запросом
источник
something
кsomething
)