MySQL字段在两个单独的字段中爆炸

时间:2015-06-16 08:54:00

标签: mysql

我有一个MySQL表,其结构如下:

CREATE TABLE `info` (
  `id` int(10) unsigned NOT NULL AUTO_INCREMENT,
  `name` varchar(70) NOT NULL,
  `email` varchar(128) NOT NULL,
  `country` varchar(80) NOT NULL,
  `state` varchar(50) NOT NULL,
  `city` varchar(40) NOT NULL,
  `address` varchar(256) NOT NULL,
  `phone` varchar(15) NOT NULL,
  `regdate` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
  PRIMARY KEY (`id`),
  UNIQUE KEY `id` (`id`),
) ENGINE=MyISAM  DEFAULT CHARSET=utf8;

问题是,我有 国家 列,其中包含国家/地区和州信息,如下所示:

  

美国/加州

但我想在他们的专栏中将它们分开(通过/展开它们并更新 country 字段中的第一个结果,而不是在 字段)。

这可以只使用MySQL吗? (我在表中有超过4 500 000个条目)

4 个答案:

答案 0 :(得分:3)

要更新所有行,但要避免列为空的行,您可以使用:

UPDATE info
SET 
country = SUBSTRING_INDEX(country, "/", 1),
state = SUBSTRING_INDEX(country, "/", -1)
WHERE country <> "" AND state = ""

做了一些轻微的尝试,似乎确保现有数据受到保护的更好方法是仅在状态 为空且国家不是的情况下应用更改空。这可以防止已经填充的状态被更改(即使当状态具有“TX”(或“CA”或“Bluegrass Home”)值时,该状态将离开具有“美国/ TX”值的国家/地区。

另外,我的涉猎发现了

SELECT SUBSTRING_INDEX("United States", "/", -1);
SELECT SUBSTRING_INDEX("United States", "/",  1);

将返回“United States”,因此要么检查“/”存在(使用某种索引检查),要么具有复杂的逻辑,确认temp_country和temp_state的派生值不相等。

我确信有更优雅,更不易出错的东西。仍然在寻找原生功能。我认为一组域规则会很好。类似的东西:

  1. 国家/地区可以包含“国家/地区”或“国家/地区”或“”
  2. 州可以包含“州”或“”
  3. 如果州包含“”且国家/地区包含“国家/州/州”,请将国家/地区更新为国家/地区,并将状态更新为国家/地区中的州。
  4. 如果州包含“”且国家/地区包含“国家/地区”,则单独保留
  5. 如果州包含“州”且国家/地区包含“国家/州”&gt;这是您的困境:您是赞成国家/地区列中的“/ State”值还是州列中的“State”值?如果你赞成离开状态,你是否消除了国家列中的“/ State”值,以便它只是“国家”或者您是否支持国家/地区列中的“/ State”值并清除现有的“State”值州专栏?
  6. 这将更新状态当前为空且状态为Country / State的状态:

    UPDATE info
    SET 
    state = IF(SUBSTRING_INDEX(country, "/", -1) = country, state, SUBSTRING_INDEX(country, "/", -1)),
    country = IF(SUBSTRING_INDEX(country, "/", -1) = country, country, SUBSTRING_INDEX(country, "/", 1))
    WHERE state = ""
    

    如果删除state =“”条件,它会变得更加大胆和笨拙,因为它会强制您添加逻辑以确定状态中的当前值是应该保持还是被来自country字段的状态覆盖。

答案 1 :(得分:1)

您可以尝试此功能:

SUBSTRING_INDEX(country, '/', 1) -- returns country i.e. before slash
SUBSTRING_INDEX(country, '/', -1) -- returns state i.e. after slash

答案 2 :(得分:1)

试试这个:

 update info
    set 
    state = case when locate('/', country) = 0 then state
    else substr(country,locate('/', country)+1) end,
    country = case when locate('/', country) = 0 then country
    else substr(country,1,locate('/', country)-1) end

由于最多只能有一个斜杠,因此只需将字符串拆分为斜杠并更新相应的列。

Demo

然而,在应用程序级别修复此问题非常重要,因为应用程序在插入数据时不尊重表结构。

答案 3 :(得分:0)

此数据库未规范化。如果你将它们分成两个单独的列,你会变得更好。

这种做法具有误导性:它不是一个国家;它是一个国家/州。

您不能轻易地在WHERE或ORDER BY子句中拥有国家/地区或州。

我认为以这种方式做事并没有赎回价值,除了&#34;我已经有了450万行&#34;和&#34;我必须更改使用此数据库的所有应用程序&#34;。

在拥有9M行之前立即更改它。您可以根据自己的需要调整this之类的内容。