我有一个表格字段membername
,其中包含用户的名字和姓氏。是否可以将它们拆分成两个字段memberfirst
和memberlast
?
所有记录都具有此格式“名字 姓氏”(不带引号且中间有一个空格)。
不幸的是,MySQL没有拆分字符串的函数。但是你可以创建一个自定义函数来实现此功能,例如下面文章中描述的那个函数:
使用这个函数:
DELIMITER $$
CREATE FUNCTION SPLIT_STR(
x VARCHAR(255),
delim VARCHAR(12),
pos INT
)
RETURNS VARCHAR(255) DETERMINISTIC
BEGIN
RETURN REPLACE(SUBSTRING(SUBSTRING_INDEX(x, delim, pos),
LENGTH(SUBSTRING_INDEX(x, delim, pos -1)) + 1),
delim, '');
END$$
DELIMITER ;
你可以按照以下方式构建你的查询:
SELECT SPLIT_STR(membername, ' ', 1) as memberfirst,
SPLIT_STR(membername, ' ', 2) as memberlast
FROM users;
如果您不想使用用户定义函数,并且您不介意查询语句有些冗长,您也可以执行以下操作:
SELECT SUBSTRING_INDEX(SUBSTRING_INDEX(membername, ' ', 1), ' ', -1) as memberfirst,
SUBSTRING_INDEX(SUBSTRING_INDEX(membername, ' ', 2), ' ', -1) as memberlast
FROM users;
LENGTH
函数的使用是否支持多字节字符安全性?“LENGTH(str)
:返回字符串 str
的长度,以字节为单位。多字节字符会被计算为多个字节。这意味着,对于一个包含五个2字节字符的字符串,LENGTH()
返回10,而 CHAR_LENGTH()
返回5。” - Erk选择变体(不使用用户定义函数):
SELECT IF(
LOCATE(' ', `membername`) > 0,
SUBSTRING(`membername`, 1, LOCATE(' ', `membername`) - 1),
`membername`
) AS memberfirst,
IF(
LOCATE(' ', `membername`) > 0,
SUBSTRING(`membername`, LOCATE(' ', `membername`) + 1),
NULL
) AS memberlast
FROM `user`;
这种方法还可以处理以下情况:
UPDATE 版本如下:
UPDATE `user` SET
`memberfirst` = IF(
LOCATE(' ', `membername`) > 0,
SUBSTRING(`membername`, 1, LOCATE(' ', `membername`) - 1),
`membername`
),
`memberlast` = IF(
LOCATE(' ', `membername`) > 0,
SUBSTRING(`membername`, LOCATE(' ', `membername`) + 1),
NULL
);
现有的回答似乎过于复杂或者不能严格回答特定的问题。
我认为,简单的回答就是以下的查询:
SELECT
SUBSTRING_INDEX(`membername`, ' ', 1) AS `memberfirst`,
SUBSTRING_INDEX(`membername`, ' ', -1) AS `memberlast`
;
我认为在这种特定情况下,处理两个以上单词的名称并不是必要的。如果您想做到正确,拆分有时可能非常困难甚至不可能:
如果您计划将此作为查询的一部分来执行,请不要这样做(a)。严肃地说,这会降低性能。也许有一些情况您并不在意性能(例如仅需进行一次性迁移作业以拆分字段,从而实现未来更好的性能),但是,如果您定期这样做,除了用于小型数据库之外,那么您就是在浪费资源。
如果您发现自己需要以某种方式仅处理列的一部分,那么您的数据库设计就有缺陷。它可能在家庭通讯录、食谱应用程序或其他无数小型数据库中运行良好,但不适用于“真正”的系统。
将名称组件存储在单独的列中。使用简单的连接操作(当您需要完整的名称时)几乎总是比使用字符搜索将它们拆分要快得多。
如果由于某种原因您无法拆分该字段,请至少添加额外的列并使用插入/更新触发器来填充它们。虽然不符合第三范式,但这将确保数据仍然一致,并显著加速您的查询。同时,您还可以确保这些额外列的小写形式(如果您在搜索它们,则进行索引),以便无需处理大小写问题。
而且,如果您甚至无法添加这些列和触发器,请注意(如果是为客户提供服务的话),这是不可扩展的。
(a) 当然,如果您的意图是使用此查询在表中将名称放入单独的列中而不是查询中执行此操作,我认为这是一个有效的用途。但是,我再次强调,在查询中这样做并不是一个好主意。
SELECT SUBSTRING_INDEX(SUBSTRING_INDEX( `membername` , ' ', 2 ),' ',1) AS b,
SUBSTRING_INDEX(SUBSTRING_INDEX( `membername` , ' ', -1 ),' ',2) AS c FROM `users` WHERE `userid`='1'
SELECT Substring(nameandsurname, 1, Locate(' ', nameandsurname) - 1) AS
firstname,
Substring(nameandsurname, Locate(' ', nameandsurname) + 1) AS lastname
FROM emp
虽然没有直接回答这个问题,但面对同样的问题,我最终做了这个:
UPDATE people_exit SET last_name = SUBSTRING_INDEX(fullname,' ',-1)
UPDATE people_exit SET middle_name = TRIM(SUBSTRING_INDEX(SUBSTRING_INDEX(fullname,last_name,1),' ',-2))
UPDATE people_exit SET middle_name = '' WHERE CHAR_LENGTH(middle_name)>3
UPDATE people_exit SET first_name = SUBSTRING_INDEX(fullname,concat(middle_name,' ',last_name),1)
UPDATE people_exit SET first_name = middle_name WHERE first_name = ''
UPDATE people_exit SET middle_name = '' WHERE first_name = middle_name
我有一列数据,其中名字和姓氏都在同一个列中,用逗号隔开。下面的代码可以实现分离。这里没有进行任何错误检查/纠正,只是简单地使用了split函数。使用phpMyAdmin执行SQL语句。
UPDATE tblAuthorList SET AuthorFirst = SUBSTRING_INDEX(AuthorLast,',',-1) , AuthorLast = SUBSTRING_INDEX(AuthorLast,',',1);
唯一需要使用这样一个函数的情况是 UPDATE 查询将更改您的表以将名字和姓氏存储到不同字段中。
数据库设计必须遵循某些规则,数据库规范化是其中最重要的规则之一。
这将从这里获取smhg并从 MySQL中给定子字符串的最后一个索引中获取curt,并将它们组合起来。这是针对mysql的,我所需要的只是得到一个名字拆分为名和姓的合理方式,其中姓氏是一个单词,名字前面是所有单词,其中名字可以为空、1个单词、2个单词或多于2个单词。例如:Null;Mary;Mary Smith;Mary A. Smith;Mary Sue Ellen Smith;
因此,如果名字是一个单词或为空,则姓氏为空。如果名字有超过1个单词,则姓氏是最后一个单词,名字是最后一个单词之前的所有单词。
请注意,我已经手动修剪了Joe Smith Jr.;Joe Smith Esq.等内容,这当然很痛苦,但是它足够小,可以这样做,因此您需要确保在决定使用哪种方法之前仔细查看名称字段中的数据。
请注意,这也会修剪输出结果,因此您不会在姓名前面或后面得到空格。
我只是为了其他可能通过谷歌搜索而来的人所发表这篇文章,他们也需要我所需的内容。当然,首先要用选择进行测试。这只是一次性的事情,所以我不在意效率。SELECT TRIM(
IF(
LOCATE(' ', `name`) > 0,
LEFT(`name`, LENGTH(`name`) - LOCATE(' ', REVERSE(`name`))),
`name`
)
) AS first_name,
TRIM(
IF(
LOCATE(' ', `name`) > 0,
SUBSTRING_INDEX(`name`, ' ', -1) ,
NULL
)
) AS last_name
FROM `users`;
UPDATE `users` SET
`first_name` = TRIM(
IF(
LOCATE(' ', `name`) > 0,
LEFT(`name`, LENGTH(`name`) - LOCATE(' ', REVERSE(`name`))),
`name`
)
),
`last_name` = TRIM(
IF(
LOCATE(' ', `name`) > 0,
SUBSTRING_INDEX(`name`, ' ', -1) ,
NULL
)
);