MySQL: Change case for compound names - mysql

I have a dataset where names are in all uppercase, and need to convert them to proper case for reports. I found here in Stackoverflow the following code:
SET LastName = CONCAT(UPPER(SUBSTRING(LastName, 1, 1)),LOWER(SUBSTRING(LastName, 2)));
This works great for simple last names:
SMITH --> Smith
JONES --> Jones
But not so good for compound names:
VAN DYKE --> Van dyke
CARTER-SMITH --> Carter-smith
Has anyone developed some MySQL code that can do the following:
VAN DYKE --> Van Dyke
CARTER-SMITH --> Carter-Smith
I know that we will not be able to catch every possible situation, but I hope someone has at least tackled converting names that are separated by dashes or spaces.

I saw this problem on another site, check it out: http://www.thingy-ma-jig.co.uk/blog/30-09-2010/mysql-how-upper-case-words
He uses a function. So I hope you have the rights to create one.

You guys are so helpful! The answer I came up with was:
CREATE FUNCTION CAP_FIRST (input VARCHAR(255))
RETURNS VARCHAR(255)
DETERMINISTIC
BEGIN
DECLARE len INT;
DECLARE i INT;
SET len = CHAR_LENGTH(input);
SET input = LOWER(input);
SET i = 0;
WHILE (i < len) DO
IF (MID(input,i,1) = ' ' OR MID(input,i,1) = '-' OR i = 0) THEN
IF (i < len) THEN
SET input = CONCAT(
LEFT(input,i),
UPPER(MID(input,i + 1,1)),
RIGHT(input,len - i - 1)
);
END IF;
END IF;
SET i = i + 1;
END WHILE;
RETURN input;
END;
And it works beautifully!

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 LastName = properword(LastName)
or
select proper( LastName ) as properLastName
from table

Related

How to get only Digits from String in mysql?

I have some string output which contain alphanumeric value. I want to get only Digits from that string. how can I fetch this by query? which MySql function can I Use?
My query is like :
select DISTINCT SUBSTRING(referrerURL,71,6)
from hotshotsdblog1.annonymoustracking
where advertiserid = 10
limit 10;
Output :
100683
101313
19924&
9072&h
12368&
5888&h
10308&
100664
1&hash
101104
And I Want output like :
100683
101313
19924
9072
12368
5888
10308
100664
1
101104
If the string starts with a number, then contains non-numeric characters, you can use the CAST() function or convert it to a numeric implicitly by adding a 0:
SELECT CAST('1234abc' AS UNSIGNED); -- 1234
SELECT '1234abc'+0; -- 1234
To extract numbers out of an arbitrary string you could add a custom function like this:
DELIMITER $$
CREATE FUNCTION `ExtractNumber`(in_string VARCHAR(50))
RETURNS INT
NO SQL
BEGIN
DECLARE ctrNumber VARCHAR(50);
DECLARE finNumber VARCHAR(50) DEFAULT '';
DECLARE sChar VARCHAR(1);
DECLARE inti INTEGER DEFAULT 1;
IF LENGTH(in_string) > 0 THEN
WHILE(inti <= LENGTH(in_string)) DO
SET sChar = SUBSTRING(in_string, inti, 1);
SET ctrNumber = FIND_IN_SET(sChar, '0,1,2,3,4,5,6,7,8,9');
IF ctrNumber > 0 THEN
SET finNumber = CONCAT(finNumber, sChar);
END IF;
SET inti = inti + 1;
END WHILE;
RETURN CAST(finNumber AS UNSIGNED);
ELSE
RETURN 0;
END IF;
END$$
DELIMITER ;
Once the function is defined, you can use it in your query:
SELECT ExtractNumber("abc1234def") AS number; -- 1234
To whoever is still looking, use regex:
select REGEXP_SUBSTR(name,"[0-9]+") as amount from `subscriptions`
Here I got success with this function:
select REGEXP_REPLACE('abc12.34.56-ghj^-_~##!', '[^0-9]+', '')
output: 123456
Explaining: basically I'm asking for mysql replace all 'not numbers' in interval from 0 to 9 to ''.
Based on Eugene Yarmash Answer. Here is a version of the custom function that extracts a decimal with two decimal places. Good for price extraction.
DELIMITER $$
CREATE FUNCTION `ExtractDecimal`(in_string VARCHAR(255))
RETURNS decimal(15,2)
NO SQL
BEGIN
DECLARE ctrNumber VARCHAR(255);
DECLARE in_string_parsed VARCHAR(255);
DECLARE digitsAndDotsNumber VARCHAR(255) DEFAULT '';
DECLARE finalNumber VARCHAR(255) DEFAULT '';
DECLARE sChar VARCHAR(1);
DECLARE inti INTEGER DEFAULT 1;
DECLARE digitSequenceStarted boolean DEFAULT false;
DECLARE negativeNumber boolean DEFAULT false;
-- FIX FIND_IN_SET cannot find a comma ","
SET in_string_parsed = replace(in_string,',','.');
IF LENGTH(in_string_parsed) > 0 THEN
-- extract digits and dots
WHILE(inti <= LENGTH(in_string_parsed)) DO
SET sChar = SUBSTRING(in_string_parsed, inti, 1);
SET ctrNumber = FIND_IN_SET(sChar, '0,1,2,3,4,5,6,7,8,9,.');
IF ctrNumber > 0 AND (sChar != '.' OR LENGTH(digitsAndDotsNumber) > 0) THEN
-- add first minus if needed
IF digitSequenceStarted = false AND inti > 1 AND SUBSTRING(in_string_parsed, inti-1, 1) = '-' THEN
SET negativeNumber = true;
END IF;
SET digitSequenceStarted = true;
SET digitsAndDotsNumber = CONCAT(digitsAndDotsNumber, sChar);
ELSEIF digitSequenceStarted = true THEN
SET inti = LENGTH(in_string_parsed);
END IF;
SET inti = inti + 1;
END WHILE;
-- remove dots from the end of number list
SET inti = LENGTH(digitsAndDotsNumber);
WHILE(inti > 0) DO
IF(SUBSTRING(digitsAndDotsNumber, inti, 1) = '.') THEN
SET digitsAndDotsNumber = SUBSTRING(digitsAndDotsNumber, 1, inti-1);
SET inti = inti - 1;
ELSE
SET inti = 0;
END IF;
END WHILE;
-- extract decimal
SET inti = 1;
WHILE(inti <= LENGTH(digitsAndDotsNumber)-3) DO
SET sChar = SUBSTRING(digitsAndDotsNumber, inti, 1);
SET ctrNumber = FIND_IN_SET(sChar, '0,1,2,3,4,5,6,7,8,9');
IF ctrNumber > 0 THEN
SET finalNumber = CONCAT(finalNumber, sChar);
END IF;
SET inti = inti + 1;
END WHILE;
SET finalNumber = CONCAT(finalNumber, RIGHT(digitsAndDotsNumber, 3));
IF negativeNumber = true AND LENGTH(finalNumber) > 0 THEN
SET finalNumber = CONCAT('-', finalNumber);
END IF;
IF LENGTH(finalNumber) = 0 THEN
RETURN 0;
END IF;
RETURN CAST(finalNumber AS decimal(15,2));
ELSE
RETURN 0;
END IF;
END$$
DELIMITER ;
Tests:
select ExtractDecimal("1234"); -- 1234.00
select ExtractDecimal("12.34"); -- 12.34
select ExtractDecimal("1.234"); -- 1234.00
select ExtractDecimal("1,234"); -- 1234.00
select ExtractDecimal("1,111,234"); -- 11111234.00
select ExtractDecimal("11,112,34"); -- 11112.34
select ExtractDecimal("11,112,34 and 123123"); -- 11112.34
select ExtractDecimal("-1"); -- -1.00
select ExtractDecimal("hello. price is 123"); -- 123.00
select ExtractDecimal("123,45,-"); -- 123.45
Here is my improvement over ExtractNumber function by Eugene Yarmash.
It strips not only non-digit characters, but also HTML entities like &#[0-9];, which should be considered as non-digit unicode characters too.
Here is the code without UDP on pure MySQL <8.
CREATE DEFINER = 'user'#'host' FUNCTION `extract_number`(
str CHAR(255)
)
RETURNS char(255) CHARSET utf8mb4 COLLATE utf8mb4_unicode_ci
DETERMINISTIC
NO SQL
SQL SECURITY DEFINER
COMMENT ''
BEGIN
DECLARE tmp VARCHAR(255);
DECLARE res VARCHAR(255) DEFAULT "";
DECLARE chr VARCHAR(1);
DECLARE len INTEGER UNSIGNED DEFAULT LENGTH(str);
DECLARE i INTEGER DEFAULT 1;
IF len > 0 THEN
WHILE i <= len DO
SET chr = SUBSTRING(str, i, 1);
/* remove &#...; */
IF "&" = chr AND "#" = SUBSTRING(str, i+1, 1) THEN
WHILE (i <= len) AND (";" != SUBSTRING(str, i, 1)) DO
SET i = i + 1;
END WHILE;
END IF;
SET tmp = FIND_IN_SET(chr, "0,1,2,3,4,5,6,7,8,9");
IF tmp > 0 THEN
SET res = CONCAT(res, chr);
END IF;
SET i = i + 1;
END WHILE;
RETURN res;
END IF;
RETURN 0;
END;
But if you are using UDP's PREG_REPLACE, you can use just following line:
RETURN PREG_REPLACE("/[^0-9]/", "", PREG_REPLACE("/&#[0-9]+;/", "", str));
I have rewritten this for MemSQL Syntax:
DROP FUNCTION IF EXISTS GetNumeric;
DELIMITER //
CREATE FUNCTION GetNumeric(str CHAR(255)) RETURNS CHAR(255) AS
DECLARE i SMALLINT = 1;
DECLARE len SMALLINT = 1;
DECLARE ret CHAR(255) = '';
DECLARE c CHAR(1);
BEGIN
IF str IS NULL
THEN
RETURN "";
END IF;
WHILE i < CHAR_LENGTH( str ) + 1 LOOP
BEGIN
c = SUBSTRING( str, i, 1 );
IF c BETWEEN '0' AND '9' THEN
ret = CONCAT(ret,c);
END IF;
i = i + 1;
END;
END LOOP;
RETURN ret;
END //
DELIMITER ;
SELECT GetNumeric('abc123def456xyz789') as test;
Based on Eugene Yarmash and Martins Balodis answers.
In my case, I didn't know whether the source string contains dot as a decimal separator. Although, I knew how the specific column should be treated. E.g. in case value came up as "10,00" hours but not as "1.00" we know that the last delimiter character should be treated as a dot decimal separator. For this purposes, we can rely on a secondary boolean param that specifies how the last comma separator should behave.
DELIMITER $$
CREATE FUNCTION EXTRACT_DECIMAL(
inString VARCHAR(255)
, treatLastCommaAsDot BOOLEAN
) RETURNS varchar(255) CHARSET utf8mb4
NO SQL
DETERMINISTIC
BEGIN
DECLARE ctrNumber VARCHAR(255);
DECLARE inStringParsed VARCHAR(255);
DECLARE digitsAndDotsNumber VARCHAR(255) DEFAULT '';
DECLARE digitsBeforeDotNumber VARCHAR(255) DEFAULT '';
DECLARE digitsAfterDotNumber VARCHAR(255) DEFAULT '';
DECLARE finalNumber VARCHAR(255) DEFAULT '';
DECLARE separatorChar VARCHAR(1) DEFAULT '_';
DECLARE iterChar VARCHAR(1);
DECLARE inti INT DEFAULT 1;
DECLARE digitSequenceStarted BOOLEAN DEFAULT false;
DECLARE negativeNumber BOOLEAN DEFAULT false;
-- FIX FIND_IN_SET cannot find a comma ","
-- We need to separate entered dot from another delimiter characters.
SET inStringParsed = TRIM(REPLACE(REPLACE(inString, ',', separatorChar), ' ', ''));
IF LENGTH(inStringParsed) > 0 THEN
-- Extract digits, dots and delimiter character.
WHILE(inti <= LENGTH(inStringParsed)) DO
-- Might contain MINUS as the first character.
SET iterChar = SUBSTRING(inStringParsed, inti, 1);
SET ctrNumber = FIND_IN_SET(iterChar, CONCAT('0,1,2,3,4,5,6,7,8,9,.,', separatorChar));
-- In case the first extracted character is not '.' and `digitsAndDotsNumber` is set.
IF ctrNumber > 0 AND (iterChar != '.' OR LENGTH(digitsAndDotsNumber) > 0) THEN
-- Add first minus if needed. Note: `inti` at this point will be higher than 1.
IF digitSequenceStarted = FALSE AND inti > 1 AND SUBSTRING(inStringParsed, inti - 1, 1) = '-' THEN
SET negativeNumber = TRUE;
END IF;
SET digitSequenceStarted = TRUE;
SET digitsAndDotsNumber = CONCAT(digitsAndDotsNumber, iterChar);
ELSEIF digitSequenceStarted = true THEN
SET inti = LENGTH(inStringParsed);
END IF;
SET inti = inti + 1;
END WHILE;
-- Search the left part of string until the separator.
-- https://stackoverflow.com/a/43699586
IF (
-- Calculates the amount of delimiter characters.
CHAR_LENGTH(digitsAndDotsNumber)
- CHAR_LENGTH(REPLACE(digitsAndDotsNumber, separatorChar, SPACE(LENGTH(separatorChar)-1)))
) + (
-- Calculates the amount of dot characters.
CHAR_LENGTH(digitsAndDotsNumber)
- CHAR_LENGTH(REPLACE(digitsAndDotsNumber, '.', SPACE(LENGTH(separatorChar)-1)))
) > 0 THEN
-- If dot is present in the string. It doesn't matter for the other characters.
IF LOCATE('.', digitsAndDotsNumber) != FALSE THEN
-- Replace all special characters before the dot.
SET inti = LOCATE('.', digitsAndDotsNumber) - 1;
-- Return the first half of numbers before the last dot.
SET digitsBeforeDotNumber = SUBSTRING(digitsAndDotsNumber, 1, inti);
SET digitsBeforeDotNumber = REPLACE(digitsBeforeDotNumber, separatorChar, '');
SET digitsAfterDotNumber = SUBSTRING(digitsAndDotsNumber, inti + 2, LENGTH(digitsAndDotsNumber) - LENGTH(digitsBeforeDotNumber));
SET digitsAndDotsNumber = CONCAT(digitsBeforeDotNumber, '.', digitsAfterDotNumber);
ELSE
IF treatLastCommaAsDot = TRUE THEN
-- Find occurence of the last delimiter within the string.
SET inti = CHAR_LENGTH(digitsAndDotsNumber) - LOCATE(separatorChar, REVERSE(digitsAndDotsNumber));
-- Break the string into left part until the last occurrence of separator character.
SET digitsBeforeDotNumber = SUBSTRING(digitsAndDotsNumber, 1, inti);
SET digitsBeforeDotNumber = REPLACE(digitsBeforeDotNumber, separatorChar, '');
SET digitsAfterDotNumber = SUBSTRING(digitsAndDotsNumber, inti + 2, LENGTH(digitsAndDotsNumber) - LENGTH(digitsBeforeDotNumber));
-- Remove any dot occurence from the right part.
SET digitsAndDotsNumber = CONCAT(digitsBeforeDotNumber, '.', REPLACE(digitsAfterDotNumber, '.', ''));
ELSE
SET digitsAndDotsNumber = REPLACE(digitsAndDotsNumber, separatorChar, '');
END IF;
END IF;
END IF;
SET finalNumber = digitsAndDotsNumber;
IF negativeNumber = TRUE AND LENGTH(finalNumber) > 0 THEN
SET finalNumber = CONCAT('-', finalNumber);
END IF;
IF LENGTH(finalNumber) = 0 THEN
RETURN 0;
END IF;
RETURN CAST(finalNumber AS DECIMAL(25,5));
ELSE
RETURN 0;
END IF;
END$$
DELIMITER ;
Here are some examples of usage:
--
-- SELECT EXTRACT_DECIMAL('-711,712,34 and 123123', FALSE); -- -71171234.00000
-- SELECT EXTRACT_DECIMAL('1.234', FALSE); -- 1.23400
-- SELECT EXTRACT_DECIMAL('1,234.00', FALSE); -- 1234.00000
-- SELECT EXTRACT_DECIMAL('14 9999,99', FALSE); -- 14999999.00000
-- SELECT EXTRACT_DECIMAL('-149,999.99', FALSE); -- -149999.99000
-- SELECT EXTRACT_DECIMAL('3 536 500.53', TRUE); -- 3536500.53000
-- SELECT EXTRACT_DECIMAL('3,536,500,53', TRUE); -- 3536500.53000
-- SELECT EXTRACT_DECIMAL("-1"); -- -1.00000
-- SELECT EXTRACT_DECIMAL('2,233,536,50053', TRUE); -- 2233536.50053
-- SELECT EXTRACT_DECIMAL('13.01666667', TRUE); -- 13.01667
-- SELECT EXTRACT_DECIMAL('1,00000000', FALSE); -- 100000000.00000
-- SELECT EXTRACT_DECIMAL('1000', FALSE); -- 1000.00000
-- ==================================================================================
Try,
Query level,
SELECT CAST('1&hash' AS UNSIGNED);
for PHP,
echo intval('13213&hash');
For any newcomers with a similar request this should be exactly what you need.
select DISTINCT CONVERT(SUBSTRING(referrerURL,71,6), SIGNED) as `foo`
from hotshotsdblog1.annonymoustracking
where advertiserid = 10
limit 10;
I suggest using a pivot table (e.g., a table that only contains a vector of ordered numbers from 1 to at least the length of the string) and then doing the following:
SELECT group_concat(c.elem separator '')
from (
select b.elem
from
(
select substr('PAUL123f3211',iter.pos,1) as elem
from (select id as pos from t10) as iter
where iter.pos <= LENGTH('PAUL123f3211')
) b
where b.elem REGEXP '^[0-9]+$') c
It can be done in PHP instead.
foreach ($query_result as &$row) {
$row['column_with_numbers'] = (int) filter_var($query_result['column_with_numbers'], FILTER_SANITIZE_NUMBER_INT);
}
Try this in php
$string = '9072&h';
echo preg_replace("/[^0-9]/", '', $string);// output: 9072
or follow this link to do this in MySql
Refer the link

SQL: I need to explode a string by ">" and want to remove the last thread and Replace the (-) by space in CamelCase

The string i have is as below and i need the output in camel case as below
For example:
compact-cameras>ixus>digital-ixus-160
compact-cameras>ixus>digital-ixus-160>DSLR
scanners>document-scanners>dr-6030c
Output:
Compact cameras>ixus
Compact Cameras>Ixus>Digital Ixus 160
Scanners>Document Scanner
You can remove last part of string and remove "-" by below statement and then use camel case function as provided link-- camel case function
SELECT REPLACE(REPLACE('compact-cameras>ixus>digital-ixus-160>DSLR',SUBSTRING_INDEX('compact-cameras>ixus>digital-ixus-160>DSLR','>',-1),''),'-',' ');
Is there a simple way to convert MySQL data into Title Case?
I tried with this and works fine for me
DROP FUNCTION IF EXISTS UC_Words;
DELIMITER ||
CREATE FUNCTION `UC_Words`( str VARCHAR(255) ) RETURNS VARCHAR(255)
BEGIN
DECLARE c CHAR(1);
DECLARE s VARCHAR(255);
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 ;
SELECT UC_Words(REPLACE(SUBSTRING_INDEX('compact-cameras>ixus>digital-ixus-160>xyz>pqr', '>', LENGTH(SUBSTRING_INDEX('compact-cameras>ixus>digital-ixus-160>xyz>pqr>khanasim', '>',-1))+1), '-',' '));

Mysql , spaces in REGEXP

I have a problem.
This function of mine does all I want except one thing, it also removes the spaces from the string, this I don't want.
I've been trying all different tips and ideas from here but it doesn't work. The documentation says I'm using it correctly, maybe I misunderstood. Can someone please help me?
CREATE DEFINER=`user`#`%` FUNCTION `fn_RemoveNumbers`(str varchar(8000)) RETURNS varchar(767) CHARSET latin1
BEGIN
DECLARE i, len SMALLINT DEFAULT 1;
DECLARE ret varchar(767) DEFAULT '';
DECLARE c CHAR(1);
SET len = CHAR_LENGTH( str );
REPEAT
BEGIN
SET c = MID( str, i, 1 );
IF (c REGEXP '[[:alpha:]]') OR (c REGEXP '[[:space:]]') THEN
SET ret=CONCAT(ret,c);
END IF;
SET i = i + 1;
END;
UNTIL i > len END REPEAT;
RETURN ret;
END
The (c REGEXP '[[:space:]]') should in my eyes append the char to the final string but it doesn't.
I've also tried ' ', '[ ]' etc etc, without success.
I'm using mysql version 5.6. I used this doc: http://dev.mysql.com/doc/refman/5.6/en/regexp.html
I can't test UDF's here but try to make it 1 regexp like so:
IF c REGEXP '[[:alpha:]]|[[:space:]]' THEN
Is it possible that you're dealing with non-standard spaces? Like non-line-breaking spaces? In that case, maybe this works to catch all white-space:
IF c REGEXP '[[:alpha:]]|[[:blank:]]' THEN
Or if you're only trying to remove the digits, like so:
IF c NOT REGEXP '[[:digit:]]' THEN
I found the solutino on this page: MySQL REGEXP - Removing white space and non-numeric characters
CREATE DEFINER=`user`#`localhost` FUNCTION `fn_RemoveNumerics`(str VARCHAR(1000)) RETURNS varchar(1000) CHARSET latin1
BEGIN
DECLARE counter INT DEFAULT 0;
DECLARE strLength INT DEFAULT 0;
DECLARE strChar VARCHAR(1000) DEFAULT '' ;
DECLARE retVal VARCHAR(1000) DEFAULT '';
SET strLength = LENGTH(str);
WHILE strLength > 0 DO
SET counter = counter+1;
SET strChar = SUBSTRING(str,counter,1);
IF strChar REGEXP('[0-9]+') = 0
THEN SET retVal = CONCAT(retVal,strChar);
END IF;
SET strLength = strLength -1;
SET strChar = NULL;
END WHILE;
RETURN retVal;
END
I simply just changed 'IF strChar REGEXP('[0-9]+') = 1' to 'IF strChar REGEXP('[0-9]+') = 0'
I still cant figure out why it doesnt work. Maybe it has something to do whit the repeater? This one uses a while to get the job don3e.....and it works!

Convert mysql data from uppercase

How can I convert and update all my data in one colum from uppercase to uppercase just for the first letter of each word?
Need to update the database with the new values.
Thanks
Looks like someone created a function for this,
CREATE FUNCTION CAP_FIRST (input VARCHAR(255))
RETURNS VARCHAR(255)
DETERMINISTIC
BEGIN
DECLARE len INT;
DECLARE i INT;
SET len = CHAR_LENGTH(input);
SET input = LOWER(input);
SET i = 0;
WHILE (i < len) DO
IF (MID(input,i,1) = ' ' OR i = 0) THEN
IF (i < len) THEN
SET input = CONCAT(
LEFT(input,i),
UPPER(MID(input,i + 1,1)),
RIGHT(input,len - i - 1)
);
END IF;
END IF;
SET i = i + 1;
END WHILE;
RETURN input;
END;
SELECT CAP_FIRST(
'this is totally like # TEST 1 right!'
)
Which returns: "This Is Totally Like # Test 1 Right!"
Link: http://joezack.com/index.php/2008/10/20/mysql-capitalize-function/
this may help...
http://joezack.com/index.php/2008/10/20/mysql-capitalize-function/
As per FAngel comment, I have completely plagiarized the content here in case the link dies:
CREATE FUNCTION CAP_FIRST (input VARCHAR(255))
RETURNS VARCHAR(255)
DETERMINISTIC
BEGIN
DECLARE len INT;
DECLARE i INT;
SET len = CHAR_LENGTH(input);
SET input = LOWER(input);
SET i = 0;
WHILE (i < len) DO
IF (MID(input,i,1) = ' ' OR i = 0) THEN
IF (i < len) THEN
SET input = CONCAT(
LEFT(input,i),
UPPER(MID(input,i + 1,1)),
RIGHT(input,len - i - 1)
);
END IF;
END IF;
SET i = i + 1;
END WHILE;
RETURN input;
END;
So running the following code...
SELECT CAP_FIRST(
'this is totally like # TEST 1 right!'
)
You can do the following:
http://www.thingy-ma-jig.co.uk/blog/30-09-2010/mysql-how-upper-case-words
first define the function as shown, and then run an update statement:
UPDATE table SET someColumn = UC_FIRST(someColumn);

How do you extract a numerical value from a string in a MySQL query?

I have a table with two columns: price (int) and price_display (varchar).
price is the actual numerical price, e.g. "9990"
price_display is the visual representation, e.g. "$9.99" or "9.99Fr"
I've been able to confirm the two columns match via regexp:
price_display not regexp
format(price/1000, 2)
But in the case of a mismatch, I want to extract the value from the price_display column and set it into the price column, all within the context of an update statement. I've not been able to figure out how.
Thanks.
This function does the job of only returning the digits 0-9 from the string, which does the job nicely to solve your issue, regardless of what prefixes or postfixes you have.
http://www.artfulsoftware.com/infotree/queries.php?&bw=1280#815
Copied here for reference:
SET GLOBAL log_bin_trust_function_creators=1;
DROP FUNCTION IF EXISTS digits;
DELIMITER |
CREATE FUNCTION digits( str CHAR(32) ) RETURNS CHAR(32)
BEGIN
DECLARE i, len SMALLINT DEFAULT 1;
DECLARE ret CHAR(32) DEFAULT '';
DECLARE c CHAR(1);
IF str IS NULL
THEN
RETURN "";
END IF;
SET len = CHAR_LENGTH( str );
REPEAT
BEGIN
SET c = MID( str, i, 1 );
IF c BETWEEN '0' AND '9' THEN
SET ret=CONCAT(ret,c);
END IF;
SET i = i + 1;
END;
UNTIL i > len END REPEAT;
RETURN ret;
END |
DELIMITER ;
SELECT digits('$10.00Fr');
#returns 1000
One approach would be to use REPLACE() function:
UPDATE my_table
SET price = replace(replace(replace(price_display,'Fr',''),'$',''),'.','')
WHERE price_display not regexp format(price/1000, 2);
This works for the examples data you gave:
'$9.99'
'9.99Fr'
Both result in 999 in my test. With an update like this, it's important to be sure to back up the database first, and be cognizant of the formats of the items. You can see all the "baddies" by doing this query:
SELECT DISTINCT price_display
FROM my_table
WHERE price_display not regexp format(price/1000, 2)
ORDER BY price_display;
For me CASTING the field did the trick:
CAST( price AS UNSIGNED ) // For positive integer
CAST( price AS SIGNED ) // For negative and positive integer
IF(CAST(price AS UNSIGNED)=0,REVERSE(CAST(REVERSE(price) AS UNSIGNED)),CAST(price AS UNSIGNED)) // Fix when price starts with something else then a digit
For more details see:
https://dev.mysql.com/doc/refman/5.0/en/cast-functions.html
This is a "coding horror", relational database schemas should NOT be written like this!
Your having to write complex and unnecessary code to validate the data.
Try something like this:
SELECT CONCAT('$',(price/1000)) AS Price FROM ...
In addition, you can use a float, double or real instead of a integer.
If you need to store currency data, you might consider adding a currency field or use the systems locale functions to display it in the correct format.
I create a procedure that detect the first number in a string and return this, if not return 0.
DROP FUNCTION IF EXISTS extractNumber;
DELIMITER //
CREATE FUNCTION extractNumber (string1 VARCHAR(255)) RETURNS INT(11)
BEGIN
DECLARE position, result, longitude INT(11) DEFAULT 0;
DECLARE string2 VARCHAR(255);
SET longitude = LENGTH(string1);
SET result = CONVERT(string1, SIGNED);
IF result = 0 THEN
IF string1 REGEXP('[0-9]') THEN
SET position = 2;
checkString:WHILE position <= longitude DO
SET string2 = SUBSTR(string1 FROM position);
IF CONVERT(string2, SIGNED) != 0 THEN
SET result = CONVERT(string2, SIGNED);
LEAVE checkString;
END IF;
SET position = position + 1;
END WHILE;
END IF;
END IF;
RETURN result;
END //
DELIMITER ;
Return last number from the string:
CREATE FUNCTION getLastNumber(str VARCHAR(255)) RETURNS INT(11)
DELIMETER //
BEGIN
DECLARE last_number, str_length, position INT(11) DEFAULT 0;
DECLARE temp_char VARCHAR(1);
DECLARE temp_char_before VARCHAR(1);
IF str IS NULL THEN
RETURN -1;
END IF;
SET str_length = LENGTH(str);
WHILE position <= str_length DO
SET temp_char = MID(str, position, 1);
IF position > 0 THEN
SET temp_char_before = MID(str, position - 1, 1);
END IF;
IF temp_char BETWEEN '0' AND '9' THEN
SET last_number = last_number * 10 + temp_char;
END IF;
IF (temp_char_before NOT BETWEEN '0' AND '9') AND
(temp_char BETWEEN '0' AND '9') THEN
SET last_number = temp_char;
END IF;
SET position = position + 1;
END WHILE;
RETURN last_number;
END//
DELIMETER;
Then call this functions:
select getLastNumber("ssss111www222w");
print 222
select getLastNumber("ssss111www222www3332");
print 3332