Jak na bieżąco aktualizować jedną tabelę na podstawie wartości innej tabeli?

40

Mam tabelę na imię ips, jak poniżej:

CREATE TABLE `ips` (
 `id` int(10) unsigned NOT NULL DEFAULT '0',
 `begin_ip_num` int(11) unsigned DEFAULT NULL,
 `end_ip_num` int(11) unsigned DEFAULT NULL,
 `iso` varchar(3) DEFAULT NULL,
 `country` varchar(150) DEFAULT NULL
) ENGINE=InnoDB

Załóżmy, że mam countryidpole na tej tabeli z tabeli kraju, która jest jak poniżej:

CREATE TABLE `country` (
 `countryid` tinyint(3) unsigned NOT NULL AUTO_INCREMENT,
 `name` varchar(50) CHARACTER SET utf8 COLLATE utf8_unicode_ci NOT NULL,
 `ordering` smallint(5) unsigned NOT NULL DEFAULT '0',
 `iso` char(2) NOT NULL,
 PRIMARY KEY (`countryid`)
) ENGINE=InnoDB

Tabela IPS zawiera około 100 000 rekordów. Czy istnieje zapytanie dotyczące następującego scenariusza:
Sprawdź, czy ips.isojest równe country.iso, czy jest równe, a następnie dodaj country.coutryid do tego rekordu. Nie mogłem wymyślić żadnego sposobu, aby to zrobić. Czy masz jakiś pomysł, jak to zrobić?

ALH
źródło

Odpowiedzi:

72
UPDATE ips INNER JOIN country
    ON ips.iso = country.iso
SET ips.countryid = country.countryid

Za pomocą MySQL zaktualizuj składnię wielu tabel:

14.2.11 Składnia aktualizacji

Pamiętaj, że masz dwie różne długości i typy danych w kolumnach ISO. W rzeczywistości istnieją dwa oddzielne zestawy kodów ISO, 2-literowe i 3-literowe, więc w rzeczywistości możesz nie być w stanie dołączyć do tych kolumn:

ISO 3166-1

Warunek łączenia USING (iso)zamiast ON ips.iso = country.isodziała również.

Cade Roux
źródło
Jesteś geniuszem, na który odpowiadasz, oszczędzając mi czas
humphrey
Dziwi mnie, jak mało kodu jest potrzebne do wykonania tej akcji!
Matt Cremeens
32

Rozwiązanie @Cade Roux daje mi błąd składniowy, poprawny dla mysql 5.5.29 to:

UPDATE ips 
INNER JOIN country
    ON ips.iso = country.iso
SET ips.countryid = country.countryid

bez słowa kluczowego „FROM”.

linuxatico
źródło
1
Od tego czasu został naprawiony, wydaje się ...
rogerdpack
10

Ta składnia może być lepiej czytelna

UPDATE country p, ips pp
SET pp.countryid = p.countryid
WHERE pp.iso = p.iso
SebastianLasse
źródło
4

dzięki @Cade, ale znalazłem proste rozwiązanie:

update ips set countryid=(select countryid from country where ips.iso=country.iso )
ALH
źródło
5
Istnieje różnica w zachowaniu mojej wersji - twoja wersja ustawi ją na NULL, jeśli nie zostanie znaleziona, moja nie zmieni istniejącej wartości, jeśli nie zostanie dopasowana. To może, ale nie musi być pożądane. Również plan wykonania może się różnić w zależności od optymalizatora.
Cade Roux,
@CadeRoux Nie pomyślałem o części NULL, dzięki.
ALH
1
@ john.locke Prawdopodobnie nie stanowi to problemu - po dodaniu nowej kolumny zakładam, że będzie to NULL, a także klucz obcy, więc nieprawidłowe wpisy i tak nie będą dozwolone. Trudno jednak odróżnić od tego, co zostało wyraźnie podane w twoim pytaniu.
Cade Roux,