33

Is it possible in mysql to format a column in Proper Case?

Example: Proper("ABSALOM") = "Absalom"

I have searched a lot and I think MySQL doesn't have any inbuilt function to do this. Is it possible to do this any other way in MySQL?

Cœur
  • 37,241
  • 25
  • 195
  • 267

5 Answers5

58

You can combine CONCAT and SUBSTRING:

CONCAT(UCASE(SUBSTRING(`fieldName`, 1, 1)), LOWER(SUBSTRING(`fieldName`, 2)))
Dave Maple
  • 8,102
  • 4
  • 45
  • 64
  • 16
    This works for single words, but for something like "NEW YORK" you get "New york" – Ray Mar 26 '13 at 21:25
  • 1
    Yeah for that use case it's probably best to look at doing this is the presentation tier of your application or possibly normalizing the data BEFORE storing it. Database queries aren't ideal for formatting strings in an application though manipulations are possible. – Dave Maple Mar 26 '13 at 22:01
22

You would think that the world’s most popular open source database, as MySQL like to call itself, would have a function for making items title case (where the first letter of every word is capitalized). Sadly it doesn’t.

This is the best solution i found Just create a stored procedure / function that will do the trick

mysql> 
DROP FUNCTION IF EXISTS proper;
SET GLOBAL  log_bin_trust_function_creators=TRUE;
DELIMITER |
CREATE FUNCTION proper( str VARCHAR(128) )
RETURNS VARCHAR(128)
BEGIN
DECLARE c CHAR(1);
DECLARE s VARCHAR(128);
DECLARE i INT DEFAULT 1;
DECLARE bool INT DEFAULT 1;
DECLARE punct CHAR(17) DEFAULT ' ()[]{},.-_!@;:?/';
SET s = LCASE( str );
WHILE i <= LENGTH( str ) DO   
    BEGIN
SET c = SUBSTRING( s, i, 1 );
IF LOCATE( c, punct ) > 0 THEN
SET bool = 1;
ELSEIF bool=1 THEN
BEGIN
IF c >= 'a' AND c <= 'z' THEN
BEGIN
SET s = CONCAT(LEFT(s,i-1),UCASE(c),SUBSTRING(s,i+1));
SET bool = 0;
END;
ELSEIF c >= '0' AND c <= '9' THEN
SET bool = 0;
END IF;
END;
END IF;
SET i = i+1;
END;
END WHILE;
RETURN s;
END;
|
DELIMITER ;

then

update table set col = proper(col)

or

select proper( col ) as properCOl 
from table 

Tada Your are welcome

Pascal
  • 2,377
  • 3
  • 25
  • 40
6

@Pascal's solution works on latin characters. Any meddling with different collations messes things up.

I think what @Pascal really meant goes more like this:

DELIMITER |

CREATE or replace FUNCTION func_proper( str VARCHAR(255) )
RETURNS VARCHAR(255)
BEGIN
  DECLARE chr VARCHAR(1);
  DECLARE lStr VARCHAR(255);
  DECLARE oStr VARCHAR(255) DEFAULT '';
  DECLARE i INT DEFAULT 1;
  DECLARE bool INT DEFAULT 1;
  DECLARE punct CHAR(17) DEFAULT ' ()[]{},.-_!@;:?/';

  WHILE i <= LENGTH( str ) DO
    BEGIN
      SET chr = SUBSTRING( str, i, 1 );
      IF LOCATE( chr, punct ) > 0 THEN
        BEGIN
          SET bool = 1;
          SET oStr = concat(oStr, chr);
        END;
      ELSEIF bool=1 THEN
        BEGIN
          SET oStr = concat(oStr, UCASE(chr));
          SET bool = 0;
        END;
      ELSE
        BEGIN
          SET oStr = concat(oStr, LCASE(chr));
        END;
      END IF;
      SET i = i+1;
    END;
  END WHILE;

  RETURN oStr;
END;

|
DELIMITER ;
michelek
  • 2,380
  • 1
  • 13
  • 15
2

In case there are only words in a single column ie. FirstName and LastName. We can concatenate the substrings.

select customer_name, concat(   
  upper(substring(substring_index(customer_name,' ',1),1,1)),   
  lower(substring(substring_index(customer_name,' ',1),2)) , ' ',
  upper(substring(substring_index(customer_name,' ',-1),1,1)),
  lower(substring(substring_index(customer_name,' ',-1),2)) 
) from customer;
Paul Roub
  • 36,322
  • 27
  • 84
  • 93
Atishay3d
  • 21
  • 2
1
-- set upper case the first char of every word in a string
DROP FUNCTION IF EXISTS PROPER;
DELIMITER $$
CREATE FUNCTION PROPER(inputStr varchar(1500)) 
RETURNS VARCHAR(1500)
DETERMINISTIC
BEGIN
    DECLARE x, y, result VARCHAR(1500);
    SET result = '';
    SET x = '';
    SET y = LOWER(TRIM(inputStr));
    WHILE CHAR_LENGTH(y) > 0 DO
        -- get next word
        SET x = SUBSTRING_INDEX(y, ' ', 1);
        -- set upper case the first char
        SET x = CONCAT(UPPER(SUBSTRING(x, 1, 1)), SUBSTRING(x, 2));
        -- the final s (greek language)               
        IF RIGHT(x,1) = 'σ' THEN
            SET x = CONCAT(left(x, CHAR_LENGTH(x) - 1),'ς');
        END IF;
        -- add word to result
        SET result = CONCAT(result, ' ', x);
        -- prepare y for next loop
        SET y = TRIM(SUBSTRING(y, CHAR_LENGTH(x) + 1));
    END WHILE;
    RETURN (TRIM(result));
END$$
DELIMITER;
thanoskam
  • 11
  • 1