Comment mettre à jour une table en fonction des valeurs d'une autre table à la volée?

41

J'ai une table au nom d'ips comme ci-dessous:

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

Supposons que j'ai un countryidchamp sur cette table à partir de la table de pays qui est comme ci-dessous:

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

Il y a environ 100 000 enregistrements dans la table ips. Existe-t-il une requête pour le scénario suivant:
Vérifiez si ips.isoest égal à country.iso, puis ajoutez country.coutryid à cet enregistrement. Je ne pouvais penser à aucun moyen de le faire. Avez-vous une idée de comment faire ça?

ALH
la source

Réponses:

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

Avec MySQL, mettez à jour la syntaxe à plusieurs tables:

14.2.11 Syntaxe UPDATE

Notez que vous avez deux longueurs et types de données différents sur vos colonnes iso. Il existe en fait deux ensembles distincts de codes ISO, à 2 lettres et à 3 lettres, de sorte que vous ne pourrez peut-être pas joindre ces colonnes:

ISO 3166-1

La condition de jointure USING (iso)au lieu de ON ips.iso = country.isofonctionne également.

Cade Roux
la source
Vous êtes un génie, vous répondez a sauvé mon temps
humphrey
Je suis étonné de voir combien de code est nécessaire pour effectuer cette action!
Matt Cremeens
32

La solution de @Cade Roux me donne une erreur de syntaxe, la bonne pour mysql 5.5.29 est:

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

sans le mot clé "FROM".

linuxatico
la source
1
Il a depuis été corrigé, semble ...
rogerdpack
10

Cette syntaxe pourrait être mieux lisible

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

Merci @ Cade, mais j'ai trouvé une solution simple pour cela:

update ips set countryid=(select countryid from country where ips.iso=country.iso )
ALH
la source
5
Il existe une différence de comportement par rapport à ma version: votre version la définira sur NULL si elle n’est pas trouvée, la mienne ne modifiera pas une valeur existante si elle ne correspond pas. Cela peut être souhaitable ou non. Le plan d'exécution peut également différer en fonction de l'optimiseur.
Cade Roux
@CadeRoux Je n'ai pas pensé à la partie NULL, merci.
ALH
1
@ john.locke Ce n'est probablement pas un problème - lorsque vous ajoutez la nouvelle colonne, je suppose que ce sera NULL et également une clé étrangère, afin que les entrées non valides ne soient pas autorisées de toute façon. Mais il est difficile de dire ce qui a été explicitement indiqué dans votre question.
Cade Roux