将现有表格中每个单词的第一个字母大写

36

我有一个已存在的表'people_table',其中有一个字段full_name

许多记录中,'full_name'字段中的大小写是错误的。例如:'fred Jones''fred jones''Fred jones'

我可以使用以下代码找到这些错误的条目:

SELECT * FROM people_table WHERE full_name REGEXP BINARY '^[a-z]';

我该如何将每个单词的首字母大写?例如:'fred jones' 变成 'Fred Jones'

15个回答

67

MySQL没有这样的函数,你需要自己编写。在下面的链接中有一个实现:

http://joezack.com/index.php/2008/10/20/mysql-capitalize-function/

为了使用它,首先需要在数据库中创建该函数。例如,您可以使用MySQL Query Browser(右键单击数据库名称并选择创建新函数)来执行此操作。

创建函数后,可以使用以下查询更新表中的值:

UPDATE users SET name = CAP_FIRST(name);

1
谢谢你的帮助。我不确定如何使用这个函数来更新我已经拥有的记录。(我是一个MySQL新手,我很害怕。) - SirRatty
1
我编辑了这篇文章,添加了如何使用该函数的信息。 - Vinicius Braz Pinto
非常感谢Vinicius!我将尝试这种方法。 - SirRatty
在我的情况下,我必须像这样声明一个DELIMITER,并编写以下代码: DELIMITER $$ CREATE FUNCTION... BEGIN... END$$ DELIMITER; - Phemelo Khetho

51

如果您只需要运行一次,又不想创建一个函数,可以采用硬编码的方式:

UPDATE people_table SET full_name = LOWER(full_name);
UPDATE people_table SET full_name = CONCAT(UPPER(SUBSTR(full_name,1,1)),LOWER(SUBSTR(full_name,2)));
UPDATE people_table SET full_name = REPLACE(full_name,' a',' A');
UPDATE people_table SET full_name = REPLACE(full_name,' b',' B');
UPDATE people_table SET full_name = REPLACE(full_name,' c',' C');
UPDATE people_table SET full_name = REPLACE(full_name,' d',' D');
UPDATE people_table SET full_name = REPLACE(full_name,' e',' E');
UPDATE people_table SET full_name = REPLACE(full_name,' f',' F');
UPDATE people_table SET full_name = REPLACE(full_name,' g',' G');
UPDATE people_table SET full_name = REPLACE(full_name,' h',' H');
UPDATE people_table SET full_name = REPLACE(full_name,' i',' I');
UPDATE people_table SET full_name = REPLACE(full_name,' j',' J');
UPDATE people_table SET full_name = REPLACE(full_name,' k',' K');
UPDATE people_table SET full_name = REPLACE(full_name,' l',' L');
UPDATE people_table SET full_name = REPLACE(full_name,' m',' M');
UPDATE people_table SET full_name = REPLACE(full_name,' n',' N');
UPDATE people_table SET full_name = REPLACE(full_name,' o',' O');
UPDATE people_table SET full_name = REPLACE(full_name,' p',' P');
UPDATE people_table SET full_name = REPLACE(full_name,' q',' Q');
UPDATE people_table SET full_name = REPLACE(full_name,' r',' R');
UPDATE people_table SET full_name = REPLACE(full_name,' s',' S');
UPDATE people_table SET full_name = REPLACE(full_name,' t',' T');
UPDATE people_table SET full_name = REPLACE(full_name,' u',' U');
UPDATE people_table SET full_name = REPLACE(full_name,' v',' V');
UPDATE people_table SET full_name = REPLACE(full_name,' w',' W');
UPDATE people_table SET full_name = REPLACE(full_name,' x',' X');
UPDATE people_table SET full_name = REPLACE(full_name,' y',' Y');
UPDATE people_table SET full_name = REPLACE(full_name,' z',' Z');

9
这是最佳答案。简单明了。不需要创建函数。 - Emerson Rocha
10
people_table表中full_name字段的内容进行更新,将其中的小写字母转换成大写字母。具体操作为:使用REPLACE函数依次替换所有小写字母,将其转换为相应的大写字母,然后使用CONCAT函数将首字母转换为大写字母,最终得到更新后的全名。 - Benj F
3
@BenjF 不能停止笑 - tom10271
1
糟糕的代码。 如果我在使用Unicode时包含了像西里尔文、中文等字符会发生什么??? - Nikolay Ivanov
2
那么,如果这种快速解决方案无法解决您的问题,您必须使用一个函数,但这并不意味着这是“可怕的代码”。 如果您的真正问题仅涉及西里尔或拉丁文,您可以添加这些大写字符,因为它们并不多见,并且对于中文,大写字母在常规单词上是可交换的。 - glerendegui
1
我同意,如果您不想创建函数,这是一次性使用的最简单解决方案。但是,它没有考虑连字符名称。例如,“peter smith-thompson”将变为“Peter Smith-thompson”。因此,您需要运行另一轮更新,使用UPDATE people_table SET full_name = REPLACE(full_name,'-a','-A');等等。 - user10425889

19

如果您想使所有单词大写,就需要调用自定义函数

-- may help:
-- DROP function if exists capitalize;

DELIMITER $$
CREATE FUNCTION `capitalize`(s varchar(255)) RETURNS varchar(255) 
BEGIN
  declare c int;
  declare x varchar(255);
  declare y varchar(255);
  declare z varchar(255);

  set x = UPPER( SUBSTRING( s, 1, 1));
  set y = SUBSTR( s, 2);
  set c = instr( y, ' ');

  while c > 0
    do
      set z = SUBSTR( y, 1, c);
      set x = CONCAT( x, z);
      set z = UPPER( SUBSTR( y, c+1, 1));
      set x = CONCAT( x, z);
      set y = SUBSTR( y, c+2);
      set c = INSTR( y, ' ');     
  end while;
  set x = CONCAT(x, y);
  return x;
END$$

DELIMITER ;

现在您可以这样做:

 UPDATE mytable SET thefield = capitalize(thefield);

7
这只会修复第一个单词,而不是整个字符串。例如,“fred jones”变成“Fred jones”。应该修改为“Fred Jones”。 - jamesthollowell

5

以下是由Nicholas Thompson提供的两个有用函数。您可以将UC_DELIMITER的第3个变量设置为false,第二个变量设置为“ ”以使多个单词大写。

UC_FIRST 将给定字符串的第一个字母大写 - 此函数是PHP中ucfirst函数的克隆。

DROP FUNCTION IF EXISTS UC_FIRST;
CREATE FUNCTION UC_FIRST(oldWord VARCHAR(255)) RETURNS VARCHAR(255)
RETURN CONCAT(UCASE(SUBSTRING(oldWord, 1, 1)),SUBSTRING(oldWord, 2));

UC_DELIMITER:将单词首字母大写,并在单词间添加分隔符

DROP FUNCTION IF EXISTS UC_DELIMITER;
DELIMITER //
CREATE FUNCTION UC_DELIMITER(
   oldName VARCHAR(255), delim VARCHAR(1), trimSpaces BOOL
) 
  RETURNS VARCHAR(255)
BEGIN
SET @oldString := oldName;
SET @newString := "";

tokenLoop: LOOP
    IF trimSpaces THEN SET @oldString := TRIM(BOTH " " FROM @oldString);          END IF;

SET @splitPoint := LOCATE(delim, @oldString);

IF @splitPoint = 0 THEN
  SET @newString := CONCAT(@newString, UC_FIRST(@oldString));
  LEAVE tokenLoop;
END IF;

   SET @newString := CONCAT(@newString, UC_FIRST(SUBSTRING(@oldString, 1, @splitPoint)));
   SET @oldString := SUBSTRING(@oldString, @splitPoint+1);
END LOOP tokenLoop;

RETURN @newString;
END//
DELIMITER ;

例子:

SELECT UC_DELIMITER('eric-leroy','-',TRUE);
Eric-Leroy  

Function's Webpage


这是一个很棒的解决方案。 - Chad Cache

4

我尝试使用上面的代码,但是在函数部分出现了语法错误,因此无法创建。如果有帮助的话,我为最新版本的MySQL编写了这篇文章。

CREATE FUNCTION  `CAP_FIRST`(input VARCHAR(255)) RETURNS varchar(255) CHARSET latin1
    DETERMINISTIC
BEGIN
    DECLARE len INT;
    DECLARE i INT;
    DECLARE charnum INT;
    declare SortedName varchar(255);

    SET len   = CHAR_LENGTH(input);
    SET input = LOWER(input);
    SET i = 1;
    set charnum = 1;
    set SortedName = '';


    WHILE (i <= len) DO
        if charnum = 1 then
            set SortedName = concat(SortedName,upper(mid(input,i,1)));
            set charnum = charnum + 1;
        else
            if mid(input,i,1) = ' ' then
                set SortedName = concat(SortedName,' ');
                set charnum = 1;
            else
                set SortedName = concat(SortedName,mid(input,i,1));
                set charnum = charnum + 1;
            end if;

        end if;


        SET i = i + 1;
    END WHILE;

    RETURN SortedName;
END

谢谢大家,这真的很有帮助。 - Scott
我仍然收到以下错误信息:“您的SQL语法有误,请检查与您的MySQL服务器版本相对应的手册,以获取正确的语法使用方法,在第4行附近。” - Jester

4

DELIMITER $$
CREATE FUNCTION `capitalize`(s varchar(255)) RETURNS varchar(255) 
BEGIN
  declare c int;
  declare x varchar(255);
  declare y varchar(255);
  declare z varchar(255);

  set x = UPPER( SUBSTRING( s, 1, 1));
  set y = lower(SUBSTR( s, 2));
  set c = instr( y, ' ');

  while c > 0
    do
      set z = SUBSTR( y, 1, c);
      set x = CONCAT( x, z);
      set z = UPPER( SUBSTR( y, c+1, 1));
      set x = CONCAT( x, z);
      set y = SUBSTR( y, c+2);
      set c = INSTR( y, ' ');     
  end while;
  set x = CONCAT(x, y);
  return x;
END$$

DELIMITER ;

Create above function to set First character to capital of each words


3

简单来说:

SELECT
CONCAT(UCASE(LEFT(firstname, 1)), LCASE(SUBSTRING(firstname, 2))) as firstname
FROM PEOPLE

2
这将仅大写名字的第一个字母(而不是每个单词,如所要求的)。 - mathiasfk

0

可以使用LOWER、UPPER和SUBSTRING函数来实现,参见下面的示例查询

Select CONCAT(UPPER(SUBSTRING(name,1,1)),LOWER(SUBSTRING(name,2))) AS Name from table;

在UPDATE查询中,这将是:
UPDATE table1 SET name = CONCAT(UPPER(SUBSTRING(name,1,1)),LOWER(SUBSTRING(name,2))) WHERE 1

0

Eric Leroy的回答是最有趣的,但它遗漏了两个问题:

  • UC_FIRST函数中的小写字母:如果您想将单词的第一个字母大写,这意味着您也希望其他字母变为小写。它适用于完全小写的输入,但如果输入中出现混合大小写(例如“wOrD”),则会得到“WOrD”,而您想要的是“Word”。
  • 根据mysql版本和配置,您可能需要在函数定义中使用确定性关键字。

以下是更新后的代码以创建函数:

DROP FUNCTION IF EXISTS UC_FIRST;
CREATE FUNCTION UC_FIRST(oldWord VARCHAR(255)) RETURNS VARCHAR(255) DETERMINISTIC
RETURN CONCAT(UCASE(SUBSTRING(oldWord, 1, 1)),LCASE(SUBSTRING(oldWord, 2)));

DROP FUNCTION IF EXISTS UC_DELIMITER;
DELIMITER //
CREATE FUNCTION UC_DELIMITER(
   oldName VARCHAR(255), delim VARCHAR(1), trimSpaces BOOL
) 
  RETURNS VARCHAR(255) DETERMINISTIC
BEGIN
SET @oldString := oldName;
SET @newString := "";

tokenLoop: LOOP
    IF trimSpaces THEN SET @oldString := TRIM(BOTH " " FROM @oldString);          END IF;

SET @splitPoint := LOCATE(delim, @oldString);

IF @splitPoint = 0 THEN
  SET @newString := CONCAT(@newString, UC_FIRST(@oldString));
  LEAVE tokenLoop;
END IF;

   SET @newString := CONCAT(@newString, UC_FIRST(SUBSTRING(@oldString, 1, @splitPoint)));
   SET @oldString := SUBSTRING(@oldString, @splitPoint+1);
END LOOP tokenLoop;

RETURN @newString;
END//
DELIMITER ;

使用以下请求:

SELECT UC_DELIMITER('ThIs IS an ExAMplE oF MIxeD CaseS sTRing',' ',TRUE);

您将获得:

This Is An Example Of Mixed Cases String

0

如果只需要执行一次,就不需要创建一个函数。下面的代码可以正常工作:

-- Capitalize first letter of each word in r.name field
SELECT TRIM(CONCAT(
   CONCAT(UPPER(SUBSTRING(cname1,1,1)),SUBSTRING(cname1,2)) , " ",
   CONCAT(UPPER(SUBSTRING(cname2,1,1)),SUBSTRING(cname2,2)) , " ",
   CONCAT(UPPER(SUBSTRING(cname3,1,1)),SUBSTRING(cname3,2))))
FROM (
   SELECT
     @num_spaces := 1 + LENGTH(c_name) - LENGTH(REPLACE(c_name, ' ', '')) AS 
     num_spaces,
     SUBSTRING_INDEX(CONVERT(c_name,CHAR), ' ', 1) AS cname1,
     IF(@num_spaces > 1, SUBSTRING_INDEX(SUBSTRING_INDEX(c_name, ' ', 2), ' ', -1), '') AS cname2,
     IF(@num_spaces > 2, SUBSTRING_INDEX(SUBSTRING_INDEX(c_name, ' ', 3), ' ', -1), '') AS cname3
     FROM (SELECT (CASE 
        WHEN UPPER(r.name)COLLATE latin1_general_cs =r.name THEN LOWER(TRIM(r.name))
        ELSE TRIM(r.name)
        END) AS c_name,r.name
        FROM table r) cr) ncr;

注意:IF子句应该等于或大于@num_spaces的值。当前的SQL最多处理3个单词。如果需要,您可以添加更多。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接