Convert CAP_FIRST Function from MySQL to PostgreSQL - mysql

A couple of years ago, I found this CAP_FIRST function for MySQL:
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;
I have used this function extensively to convert people's names to proper capitalization for reports, like so:
UPDATE DataImport
SET FirstName = CAP_FIRST(FirstName);
UPDATE DataImport
SET LastName = CAP_FIRST(LastName);
Now I am migrating to PostgreSQL, and need this same functionality there. Do I need to convert this function to PostgreSQL, or is there a better way to get the same results? If I do need to convert, can someone help me?

It turns out that PostgreSQL has a builtin function initcap() that does this for me like so:
UPDATE DataImport
SET FirstName = initcap(FirstName);
UPDATE DataImport
SET LastName = initcap(LastName);

Related

mysql delimit and search column data

MySQL version = 5.7.29
I want to do a MySQL search on a column which has delimited data. For example:
'field_black:1, field_white:2, field1_black:5, field_green:3'
I want a function which takes input the color and returns only the delimited values which do not have the input color.
func(input, color, delimiter)
func('field_black:1, field_white:2, field1_black:5, field1_green:3', 'black', ',') = 'field_white:2, field1_green:3'
This is pretty easy to implement in python using string split on delimiter and returning result set where the color is not in the given input.
def func(inp, col, delim):
inp = inp.split(delim)
res = []
for data in inp:
if col not in data:
res.append(data)
return (','.join(res))
Can anyone help me with an equivalent implementation in MySQL.
Thank you for the help!
CREATE FUNCTION func (input TEXT, color TEXT, delimiter CHAR(1))
RETURNS TEXT
DETERMINISTIC
BEGIN
DECLARE piece TEXT;
DECLARE result TEXT DEFAULT '';
/* SET color = CONCAT('field_', color); */ /* uncomment if needed */
REPEAT
SET piece = SUBSTRING_INDEX(input, delimiter, 1);
SET input = SUBSTRING(input FROM 2 + LENGTH(piece) FOR LENGTH(input));
IF NOT LOCATE(color, piece) THEN
SET result = CONCAT(result, delimiter, TRIM(piece));
END IF;
UNTIL input = ''
END REPEAT;
RETURN TRIM(BOTH delimiter FROM result);
END
fiddle
PS. Of course you may use multi-char delimiter if needed - alter input parameter type simply.
Just cracked this after a few iterations due to unfamiliarity with MySQL syntax. This is unnecessarily complicated though.
Answer by Akina is more simple and elegant: mysql delimit and search column data
CREATE FUNCTION `new_function`(input longtext, col TEXT, delim CHAR(1)) RETURNS longtext CHARSET utf8
DETERMINISTIC
BEGIN
declare result longtext default '';
declare piece longtext default '';
declare inptext longtext default '';
set inptext = input;
while (substring_index(inptext,delim,1) = '') = 0 DO
set piece = substring_index(inptext,delim,1);
IF NOT LOCATE(col, piece) THEN
set result = concat(result, piece, delim);
END IF;
set inptext = substr(inptext, length(SUBSTRING_INDEX(inptext, '|', 1) ) + 2);
END WHILE;
set result = left(result, length(result) -1);
RETURN result;
END

Bitwise operating issue

I'm trying to rebuild a function for generating GUIDs used by the game Arma 3 in a MySQL function. There are some examples in various languages over here: https://gist.github.com/Fank/11127158
Basicially this is what I tried so far:
CREATE DEFINER=`root`#`localhost` FUNCTION `generateGUID`(playerid varchar(17)) RETURNS varchar(32) CHARSET latin1
BEGIN
DECLARE temp bigint;
DECLARE i int;
SET i = 0;
SET temp = 0;
WHILE i < 8 DO
SET temp = temp + CHAR(playerid & 0xFF);
SET playerid = playerid >> 8;
SET i = i + 1;
END WHILE;
RETURN MD5("BE" + temp);
END
What I understood so far orientating at the php example:
First of all we have the steamid given as a varchar.
Afterwards we are iterating 8 times and adding the char of the bitwise addition of the playerid and the value of 0xFF. Then we are performing a 8 bitwise right shift on the playerid.
Afterwards the string "BE" is added the temp result and a md5 is generated of this and returned.
However I'm facing the issue that this function always returns 0. I tried many things so far, like using a blob instead of an int for the temp var.
Edit: After the hint to use CONCAT instead of the + operator the result is still not matching with the guid calculators out there.
The code looks now like this:
CREATE DEFINER=`root`#`localhost` FUNCTION `generateGUID`(playerid varchar(17)) RETURNS varchar(32) CHARSET latin1
BEGIN
DECLARE temp bigint;
DECLARE i int;
SET i = 0;
SET temp = "";
WHILE i < 8 DO
SET temp = CONCAT(temp, CHAR(playerid & 0xFF));
SET playerid = playerid >> 8;
SET i = i + 1;
END WHILE;
RETURN MD5(CONCAT("BE", temp));
END
However, using the playerid 76561197996545192 the function returns 2a0f7ebed67e04afaf7ea032e1ed22e3 instead of cd97cc68c1038b485b081ba2aa3ea6fa which should be the expected output.
This works for me:
DROP FUNCTION IF EXISTS `generateGUID`;
DELIMITER //
CREATE DEFINER=`root`#`localhost` FUNCTION `generateGUID`(`playerid` BIGINT UNSIGNED) RETURNS varchar(32) CHARSET latin1
DETERMINISTIC
BEGIN
DECLARE temp text CHARSET ascii;
DECLARE i int;
SET i = 0;
SET temp = "";
WHILE i < 8 DO
SET temp = CONCAT(temp, CHAR(playerid & 0xFF));
SET playerid = playerid >> 8;
SET i = i + 1;
END WHILE;
RETURN MD5(CONCAT("BE", temp));
END//
DELIMITER ;
http://sqlfiddle.com/#!9/6cc709/1

MySQL: Change case for compound names

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

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);