如何动态基于另一个表的值更新一个表?


40

我有一个以ips为名的表格,如下所示:

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

假设我countryid在国家表的此表上有一个字段,如下所示:

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

ips表中大约有100,000条记录。对于以下情况是否有任何查询:
检查是否ips.iso等于country.iso,如果相等,则将country.coutryid添加到该记录。我想不出任何办法。你有什么想法吗?

Answers:


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

使用MySQL更新多表语法:

14.2.11 UPDATE语法

请注意,iso列上有两种不同的长度和数据类型。实际上,有两组独立的ISO代码,即2个字母和3个字母,因此实际上您可能无法加入这些列:

ISO 3166-1

加入条件USING (iso)而不是ON ips.iso = country.iso工作原理。


您是天才,您的回答节省了我的时间
汉弗莱

令我惊讶的是执行此操作所需的代码很少!
Matt Cremeens

32

@Cade Roux的解决方案给了我一个语法错误,对于MySQL 5.5.29来说正确的是:

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

没有“ FROM”关键字。


1
自那以后,它已经得到修复,似乎……
rogerdpack '18


4

感谢@Cade,但是我找到了一个简单的解决方案:

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

5
我的版本在行为上有差异-如果找不到,您的版本会将其设置为NULL,如果不匹配,则我的版本不会更改现有值。这可能是理想的,也可能不是理想的。此外,执行计划可能会因优化程序而异。
Cade Roux 2012年

@CadeRoux我没想到NULL部分,谢谢。
ALH

1
@ john.locke可能不是问题-当您添加新列时,我假设它将为NULL以及外键,因此无论如何都将不允许输入无效。但是很难从您的问题中明确给出的内容中分辨出来。
Cade Roux
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.