¿Cómo actualizar una tabla en función de los valores de otra tabla sobre la marcha?

41

Tengo una tabla a nombre de ips como a continuación:

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

Supongamos que tengo un countryidcampo en esta tabla de la tabla del país que es el siguiente:

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

Hay alrededor de 100,000 registros en la tabla ips. ¿Hay alguna consulta para el siguiente escenario?
Compruebe si ips.isoes igual a country.iso, si es igual, luego agregue country.coutryid a ese registro. No se me ocurrió ninguna forma de hacerlo. ¿Tienes alguna idea de cómo hacer eso?

ALH
fuente

Respuestas:

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

Usando la sintaxis de múltiples tablas de actualización de MySQL:

14.2.11 Sintaxis de ACTUALIZACIÓN

Tenga en cuenta que tiene dos longitudes y tipos de datos diferentes en sus columnas iso. De hecho, hay dos conjuntos separados de códigos ISO, de 2 letras y de 3 letras, por lo que en realidad es posible que no pueda unir estas columnas:

ISO 3166-1

La condición de unión en USING (iso)lugar de ON ips.iso = country.isofunciona también.

Cade Roux
fuente
Eres un genio, tu respuesta me ahorró tiempo
humphrey
¡Me sorprende lo poco que se necesita código para realizar esta acción!
Matt Cremeens
32

La solución de @Cade Roux me da un error de sintaxis, el correcto para mysql 5.5.29 es:

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

sin la palabra clave "DE".

linuxatico
fuente
1
Desde entonces se ha solucionado, parece ...
rogerdpack
10

Esta sintaxis podría ser mejor legible

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

gracias @Cade, pero encontré una solución simple para ello:

update ips set countryid=(select countryid from country where ips.iso=country.iso )
ALH
fuente
55
Hay una diferencia en el comportamiento de mi versión: su versión la establecerá en NULL si no se encuentra, la mía no alterará un valor existente si no coincide. Esto puede o no ser deseable. Además, el plan de ejecución puede diferir según el optimizador.
Cade Roux
@CadeRoux No pensé en la parte NULL, gracias.
ALH
1
@ john.locke Probablemente no sea un problema: cuando agrega la nueva columna, supongo que será NULL y también una clave foránea, por lo que no se permitirán entradas no válidas de todos modos. Pero es difícil saber de lo que se ha dado explícitamente en su pregunta.
Cade Roux