Zacząłem od googlowania i znalazłem ten artykuł, który mówi o tabelach mutex.
Mam stolik z ~ 14 milionami rekordów. Jeśli chcę dodać więcej danych w tym samym formacie, czy istnieje sposób, aby rekord, który chcę wstawić, już nie istniał bez użycia pary zapytań (tj. Jedno zapytanie do sprawdzenia i jedno do wstawienia to zestaw wyników to pusty)?
Czy unique
ograniczenie pola gwarantuje insert
niepowodzenie, jeśli już tam jest?
Wydaje się, że z ograniczonym ograniczeniem, gdy wydam wstawkę przez php, skrypt zaskrzecza.
mysql
sql
primary-key
sql-insert
królikarnia
źródło
źródło
Odpowiedzi:
posługiwać się
INSERT IGNORE INTO table
patrz http://bogdan.org.ua/2007/10/18/mysql-insert-if-not-exists-syntax.html
istnieje również
INSERT … ON DUPLICATE KEY UPDATE
składnia, wyjaśnienia znajdziesz na dev.mysql.comWpis z bogdan.org.ua zgodnie z webcache Google :
źródło
INSERT … ON DUPLICATE KEY UPDATE
jest lepszy, ponieważ nie usuwa wiersza, zachowując wszelkieauto_increment
kolumny i inne dane.INSERT … ON DUPLICATE KEY UPDATE
metody powoduje zwiększenie dowolnej kolumny AUTO_INCREMENT z błędnym wstawieniem. Prawdopodobnie dlatego, że tak naprawdę nie zawiódł, ale UPDATE.Rozwiązanie:
Wyjaśnienie:
Najbardziej wewnętrzne zapytanie
użyte jako
WHERE NOT EXISTS
-warunek wykrywa, czy istnieje już wiersz z danymi do wstawienia. Po znalezieniu jednego tego rodzaju wiersza zapytanie może zostać zatrzymane, dlatego teżLIMIT 1
(mikrooptymalizacja może zostać pominięta).Zapytanie pośrednie
reprezentuje wartości do wstawienia.
DUAL
odnosi się do specjalnego jednego wiersza, jednej tabeli kolumn domyślnie obecnych we wszystkich bazach danych Oracle (patrz https://en.wikipedia.org/wiki/DUAL_table ). Na serwerze MySQL w wersji 5.7.26 otrzymałem poprawne zapytanie, pomijającFROM DUAL
, ale wydaje się, że starsze wersje (jak 5.5.60) wymagają tychFROM
informacji. Za pomocąWHERE NOT EXISTS
zapytania pośredniego zwraca pusty zestaw wyników, jeśli najbardziej wewnętrzne zapytanie znalazło pasujące dane.Zewnętrzne zapytanie
wstawia dane, jeśli są zwracane przez zapytanie pośrednie.
źródło
INSERT IGNORE
iINSERT ON DUPLICATE KEY
wymagają unikalnych ograniczeń klucza)stuff for value1
istuff for value2
są identyczne? To rzuciłobyDuplicate column name
SELECT 1
zamiastSELECT *
w podkwerendach. Znacznie bardziej prawdopodobne, że indeks ten może spełnić.po zduplikowaniu aktualizacji klucza lub wstawieniu ignorowania mogą być wykonalne rozwiązania z MySQL.
Przykład podwójnej aktualizacji aktualizacji klucza na podstawie mysql.com
Przykład wstawienia zignoruj na podstawie mysql.com
Lub:
Lub:
źródło
Wszelkie proste ograniczenia powinny wykonać zadanie, jeśli wyjątek jest dopuszczalny. Przykłady:
Niestety, wydaje się to zwodniczo proste. Wiem, że wygląda źle w porównaniu do linku, który nam udostępniasz. ;-(
Ale nigdy nie daję tej odpowiedzi, ponieważ wydaje się, że zaspokaja twoją potrzebę. (Jeśli nie, może to spowodować aktualizację twoich wymagań, co byłoby również „dobrą rzeczą”).
Edytowane : Jeśli wstawka złamie unikalne ograniczenie bazy danych, na poziomie bazy danych zostanie zgłoszony wyjątek, przekazywany przez sterownik. Z pewnością zatrzyma twój skrypt z niepowodzeniem. W PHP musi być możliwe rozwiązanie tej sprawy ...
źródło
INSERT IGNORE
w zasadzie zamienia wszystkie błędy w ostrzeżenia, aby skrypt nie został przerwany. Następnie możesz wyświetlić wszelkie ostrzeżenia za pomocą poleceniaSHOW WARNINGS
. I kolejna ważna uwaga : ograniczenia UNIKALNE nie działają z wartościami NULL, tj. zarówno wiersz 1 (1, NULL), jak i wiersz 2 (1, NULL) zostaną wstawione (chyba że zostanie złamane inne ograniczenie, takie jak klucz podstawowy). Niefortunny.Oto funkcja PHP, która wstawi wiersz tylko wtedy, gdy wszystkie określone wartości kolumn nie istnieją jeszcze w tabeli.
Jeśli jedna z kolumn się różni, wiersz zostanie dodany.
Jeśli tabela jest pusta, wiersz zostanie dodany.
Jeśli istnieje wiersz, w którym wszystkie określone kolumny mają określone wartości, wiersz nie zostanie dodany.
Przykładowe użycie:
źródło
mysql_*
rozszerzenie jest przestarzałe od PHP 5.5.0 i zostało usunięte od PHP 7.0.0. Zamiast tego należy użyć rozszerzenia mysqli lub PDO_MySQL . Zobacz także Omówienie interfejsu API MySQL, aby uzyskać dalszą pomoc przy wyborze interfejsu API MySQL.Jeśli rekord istnieje, zostanie zastąpiony; jeśli jeszcze nie istnieje, zostanie utworzony.
źródło
REPLACE
może usunąć wiersz, a następnie wstawić zamiast aktualizacji. Efektem ubocznym jest to, że ograniczenia mogą usuwać inne obiekty i uruchamiać usuwanie wyzwalaczy.Spróbuj wykonać następujące czynności:
źródło
Istnieje kilka odpowiedzi, które obejmują sposób rozwiązania tego problemu, jeśli masz
UNIQUE
indeks, który możesz sprawdzić za pomocąON DUPLICATE KEY
lubINSERT IGNORE
. Nie zawsze tak jest, a ponieważUNIQUE
ma ograniczenie długości (1000 bajtów), możesz nie być w stanie tego zmienić. Na przykład musiałem pracować z metadanymi w WordPress (wp_postmeta
).W końcu rozwiązałem go za pomocą dwóch zapytań:
Zapytanie 1 jest zwykłym
UPDATE
zapytaniem, które nie działa, gdy nie ma danego zbioru danych. Zapytanie 2 jestINSERT
zależne od aNOT EXISTS
, tzn.INSERT
Jest wykonywane tylko wtedy, gdy zestaw danych nie istnieje.źródło
Warto zauważyć, że INSERT IGNORE będzie nadal zwiększał klucz podstawowy, niezależnie od tego, czy instrukcja zakończyła się sukcesem, czy nie, tak jak normalny INSERT.
Spowoduje to luki w kluczach podstawowych, które mogą spowodować, że programista będzie niestabilny psychicznie. Lub jeśli twoja aplikacja jest źle zaprojektowana i zależy od idealnych przyrostowych kluczy podstawowych, może to sprawić ból głowy.
Zajrzyj do
innodb_autoinc_lock_mode = 0
(ustawienie serwera i ma niewielki spadek wydajności) lub użyj najpierw SELECT, aby upewnić się, że twoje zapytanie nie zakończy się niepowodzeniem (co również obejmuje zwiększenie wydajności i dodatkowy kod).źródło
SELECT
porażki, chodzi przede wszystkim o to, aby przekazać dużą porcjęINSERT
s i nie chcieć martwić się o duplikaty.Zaktualizuj lub wstaw bez znanego klucza podstawowego
Jeśli masz już unikalny lub podstawowy klucz, inne odpowiedzi z jednym z nich
INSERT INTO ... ON DUPLICATE KEY UPDATE ...
lubREPLACE INTO ...
powinny działać poprawnie (pamiętaj, że zamień na usuwa, jeśli istnieje, a następnie wstawia - w ten sposób nie aktualizuje częściowo istniejących wartości).Ale jeśli masz wartości dla
some_column_id
isome_type
, których kombinacja jest znana jako unikalna. I chcesz zaktualizować,some_value
jeśli istnieje, lub wstaw, jeśli nie istnieje. I chcesz to zrobić za pomocą tylko jednego zapytania (aby uniknąć transakcji). To może być rozwiązanie:Zasadniczo zapytanie jest wykonywane w ten sposób (mniej skomplikowane niż mogłoby się wydawać):
WHERE
dopasowania klauzuli.s
), w którym wartości kolumn są jawnie podane (s.id ma wartość NULL, więc wygeneruje nowy identyfikator automatycznego przyrostu).s
odrzuca się (ze względu na ograniczenie nr 1 w tabelit
), a zawsze będzie wyzwalaćON DUPLICATE KEY
które będąUPDATE
some_value
kolumnę.s
).Uwaga: Każda tabela w relacyjnej bazie danych powinna mieć co najmniej podstawową
id
kolumnę automatycznego przyrostu . Jeśli go nie masz, dodaj go, nawet jeśli nie potrzebujesz go od pierwszego wejrzenia. Jest to zdecydowanie potrzebne do tej „sztuczki”.źródło
INSERT INTO ... SELECT FROM
format. Dlaczego ty teżINSERT INTO... SELECT FROM...
rozwiązanie. Proszę odnieść się do mnie link do takiej samej odpowiedzi, jeśli możesz ją znaleźć, usunę tę odpowiedź, w przeciwnym razie głosujesz za moją odpowiedzią (umowa?). Upewnij się, że odpowiedź, którą chcesz połączyć, używa tylko 1 zapytania (dla aktualizacji + wstaw), bez transakcji i jest w stanie kierować dowolną kombinację kolumn, o których wiadomo, że są unikalne (więc osobno kolumny nie muszą być unikalne).