Come aggiornare una tabella in base ai valori di un'altra tabella al volo?


41

Ho una tabella nel nome di ips come di seguito:

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

Supponiamo di avere un countryidcampo su questa tabella dalla tabella dei paesi che è il seguente:

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

Ci sono circa 100.000 record nella tabella ips. Esiste una query per il seguente scenario:
Controlla se ips.isoè uguale a country.iso, se è uguale, quindi aggiungi country.coutryid a quel record. Non riuscivo a pensare a nessun modo per farlo. Hai idea di come farlo?

Risposte:


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

Utilizzando MySQL aggiorna la sintassi di più tabelle:

14.2.11 Sintassi di AGGIORNAMENTO

Nota che hai due diverse lunghezze e tipi di dati nelle tue colonne ISO. Esistono, infatti, due serie separate di codici ISO, 2 e 3 lettere, quindi potresti non essere in grado di unire queste colonne:

ISO 3166-1

Anche la condizione di join USING (iso)invece ON ips.iso = country.isofunziona.


Sei un genio a cui rispondi mi ha salvato il tempo
Humphrey,

Mi stupisce quanto poco codice sia necessario per eseguire questa azione!
Matt Cremeens,

32

La soluzione di @Cade Roux mi dà un errore di sintassi, quello corretto per mysql 5.5.29 è:

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

senza la parola chiave "FROM".


1
Da allora è stato risolto, sembra ...
rogerdpack

10

Questa sintassi potrebbe essere meglio leggibile

UPDATE country p, ips pp
SET pp.countryid = p.countryid
WHERE pp.iso = p.iso

4

grazie @Cade, ma ho trovato una soluzione semplice per questo:

update ips set countryid=(select countryid from country where ips.iso=country.iso )

5
C'è una differenza di comportamento con la mia versione: la tua versione lo imposterà su NULL se non viene trovata, la mia non modificherà un valore esistente se non corrisponde. Questo può o meno essere desiderabile. Inoltre, il piano di esecuzione può variare in base all'ottimizzatore.
Cade Roux,

@CadeRoux Non ho pensato alla parte NULL, grazie.
ALH,

1
@ john.locke Probabilmente non è un problema - quando aggiungi la nuova colonna, suppongo che sarà NULL e anche una chiave esterna, quindi le voci non valide non sarebbero comunque consentite. Ma è difficile dire da ciò che è stato esplicitamente indicato nella tua domanda.
Cade Roux,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.