Я начал с поиска в Google и нашел эту статью, в которой говорится о таблицах мьютексов.
У меня есть таблица с ~ 14 миллионами записей. Если я хочу добавить больше данных в том же формате, есть ли способ убедиться, что запись, которую я хочу вставить, еще не существует без использования пары запросов (т. Е. Один запрос для проверки и один для вставки - это набор результатов пустой)?
unique
Гарантирует ли ограничение на поле insert
провал, если он уже там?
Кажется, что с простым ограничением, когда я запускаю вставку через php, скрипт скрипит.
mysql
sql
primary-key
sql-insert
кроличий садок
источник
источник
Ответы:
использование
INSERT IGNORE INTO table
см. http://bogdan.org.ua/2007/10/18/mysql-insert-if-not-exists-syntax.html
Есть также
INSERT … ON DUPLICATE KEY UPDATE
синтаксис, вы можете найти объяснения на dev.mysql.comСообщение от bogdan.org.ua в соответствии с веб-кэшем Google :
источник
INSERT … ON DUPLICATE KEY UPDATE
лучше, так как он не удаляет строки, сохраняя любыеauto_increment
столбцы и другие данные.INSERT … ON DUPLICATE KEY UPDATE
метода действительно увеличивает любой столбец AUTO_INCREMENT с ошибочной вставкой. Вероятно, потому что это не совсем не удалось, но ОБНОВЛЕНИЕ.Решение:
Объяснение:
Самый внутренний запрос
используется как
WHERE NOT EXISTS
-условие, определяет, существует ли уже строка с данными для вставки. После того, как одна строка такого типа найдена, запрос может остановиться, поэтомуLIMIT 1
(микрооптимизация может быть опущена).Промежуточный запрос
представляет значения для вставки.
DUAL
ссылается на специальную одну строку, одну таблицу столбцов, присутствующую по умолчанию во всех базах данных Oracle (см. https://en.wikipedia.org/wiki/DUAL_table ). На MySQL-сервере версии 5.7.26 я получил действительный запрос, когда опускалFROM DUAL
, но более старые версии (например, 5.5.60), кажется, требуютFROM
информацию. При использованииWHERE NOT EXISTS
промежуточного запроса возвращается пустой набор результатов, если самый внутренний запрос нашел совпадающие данные.Внешний запрос
вставляет данные, если таковые возвращены промежуточным запросом.
источник
INSERT IGNORE
иINSERT ON DUPLICATE KEY
требуются ограничения уникального ключа)stuff for value1
иstuff for value2
идентичны? Это бросило быDuplicate column name
SELECT 1
вместоSELECT *
подзапросов. Гораздо более вероятно, что это может быть удовлетворено индексом.при повторном обновлении ключа или вставке игнорировать могут быть жизнеспособные решения с MySQL.
Пример обновления дубликата ключа на основе mysql.com
Пример игнорирования вставки, основанный на mysql.com
Или:
Или:
источник
Любое простое ограничение должно выполнять работу, если исключение допустимо. Примеры :
Извините, это кажется обманчиво простым. Я знаю, что это плохо смотрится со ссылкой, которую вы нам предоставляете. ;-(
Но я все же даю этот ответ, потому что он, кажется, удовлетворяет ваши потребности. (Если нет, это может привести к тому, что вы обновите свои требования, что также будет «хорошая вещь» (TM)).
Отредактировано : если вставка нарушит ограничение уникальности базы данных, исключение - выброс на уровне базы данных, ретранслируемый драйвером. Это, безусловно, остановит ваш сценарий с ошибкой. В PHP должно быть возможно решить этот случай ...
источник
INSERT IGNORE
в основном все ошибки превращаются в предупреждения, чтобы ваш сценарий не прерывался. Затем вы можете просмотреть любые предупреждения с помощью командыSHOW WARNINGS
. И еще одно важное замечание : уникальные ограничения не работают со значениями NULL, т.е. row1 (1, NULL) и row2 (1, NULL) оба будут вставлены (если не нарушено другое ограничение, такое как первичный ключ). Несчастная.Вот функция PHP, которая вставит строку, только если все указанные значения столбцов еще не существуют в таблице.
Если один из столбцов отличается, строка будет добавлена.
Если таблица пуста, строка будет добавлена.
Если существует строка, в которой все указанные столбцы имеют указанные значения, строка не будет добавлена.
Пример использования:
источник
mysql_*
расширение устарело с PHP 5.5.0 и удалено с PHP 7.0.0. Вместо этого следует использовать расширение mysqli или PDO_MySQL . Смотрите также MySQL API Overview для получения дополнительной помощи при выборе MySQL API.Если запись существует, она будет перезаписана; если он еще не существует, он будет создан.
источник
REPLACE
может удалить строку, а затем вставить вместо обновления. Побочным эффектом является то, что ограничения могут удалять другие объекты и запускать триггеры удаления.Попробуйте следующее:
источник
Есть несколько ответов, которые охватывают, как решить эту проблему, если у вас есть
UNIQUE
индекс, который вы можете проверить с помощьюON DUPLICATE KEY
илиINSERT IGNORE
. Это не всегда так, и посколькуUNIQUE
имеет ограничение длины (1000 байт), вы не сможете изменить это. Например, мне пришлось работать с метаданными в WordPress (wp_postmeta
).Я наконец решил это двумя запросами:
Запрос 1 - это обычный
UPDATE
запрос, который не действует, если соответствующего набора данных там нет. Запрос 2 является a,INSERT
который зависит от aNOT EXISTS
, тоINSERT
есть выполняется только тогда, когда набор данных не существует.источник
Стоит отметить, что INSERT IGNORE по-прежнему будет увеличивать первичный ключ независимо от того, был ли оператор успешным или нет, как обычный INSERT.
Это вызовет пробелы в ваших первичных ключах, что может сделать программиста психически нестабильным. Или, если ваше приложение плохо спроектировано и зависит от совершенных добавочных первичных ключей, оно может стать головной болью.
Загляните в
innodb_autoinc_lock_mode = 0
(настройка сервера и имеет небольшое снижение производительности) или сначала используйте SELECT, чтобы убедиться, что ваш запрос не потерпит неудачу (что также сопровождается снижением производительности и дополнительным кодом).источник
SELECT
поражений, вся цель состоит в том, чтобы передать большую партиюINSERT
и не беспокоиться о дубликатах.Обновить или вставить без известного первичного ключа
Если у вас уже есть уникальный или первичный ключ, другой отвечает либо либо,
INSERT INTO ... ON DUPLICATE KEY UPDATE ...
либоREPLACE INTO ...
должен работать нормально (обратите внимание, что заменить на удаляет, если существует, а затем вставить - таким образом, частично не обновлять существующие значения).Но если у вас есть значения для
some_column_id
иsome_type
, комбинация которых, как известно, уникальна. И вы хотите обновить,some_value
если существует, или вставить, если не существует. И вы хотите сделать это всего за один запрос (чтобы избежать использования транзакции). Это может быть решением:По сути, запрос выполняется следующим образом (менее сложным, чем может показаться):
WHERE
предложения соответствия.s
Объедините полученный результат с потенциальной новой строкой (таблицей ), в которой значения столбца заданы явно (s.id равен NULL, поэтому он сгенерирует новый идентификатор автоинкремента).s
отбрасывается (из-за LIMIT 1 в таблицеt
), и она всегда будет вызывать тот,ON DUPLICATE KEY
который будетUPDATE
вsome_value
столбце.s
).Примечание. Каждая таблица в реляционной базе данных должна иметь хотя бы основной
id
столбец автоинкремента . Если у вас этого нет, добавьте, даже если вам это не нужно с первого взгляда. Это определенно необходимо для этой «хитрости».источник
INSERT INTO ... SELECT FROM
формат. Почему ты тоже?INSERT INTO... SELECT FROM...
решение. Пожалуйста, обратитесь ко мне по ссылке на тот же ответ, если вы сможете найти его, я удалю этот ответ, в противном случае вы проголосуете за мой ответ (сделка?). Убедитесь, что в ответе, который вы собираетесь связать, используется только 1 запрос (для обновления + вставка), нет транзакции, и он может быть нацелен на любую комбинацию столбцов, которые, как известно, являются уникальными (поэтому отдельно столбцы не должен быть уникальным).