How to insert space after each character in a string MySQL - mysql

I have a character string and for reporting/alignment purpose I need to insert a space after each character. Unfortunately I will have to do it in a SQL or I can write format function.
e.g. "abcd123" to be converted it to "a b c d 1 2 3 ".
Since it's for a considerable number of rows I was wondering how optimized it will be to parse each character and build a new string each time?
Any help is appreciated.
Thanks

Here's a quick & dirty mysql function which solves your problem:
delimiter ||
DROP FUNCTION IF EXISTS concat_whitespace||
CREATE FUNCTION concat_whitespace( x longtext) RETURNS longtext
LANGUAGE SQL NOT DETERMINISTIC READS SQL DATA
BEGIN
DECLARE len INT UNSIGNED;
DECLARE erg LONGTEXT;
SET len = LENGTH(x);
REPEAT
SET erg = CONCAT_WS(' ',SUBSTRING(x,len,1),erg);
SET len = len - 1;
UNTIL len < 1 END REPEAT;
return erg;
END;
||
Now try this:
Select concat_whitespace("abcd123")
which returns
"a b c d 1 2 3"
This function basically loops for each character and concats a space. Direction is from end to beginning, which saves a counter variable.
I havn't done any performance test, fur sure you somehow could optimize this..

I would not recommend storing unnecessary spaces in SQL. This will only waste space.
How about writing a custom retrieval method that will return all strings from your DB with spaces after each character?

update tablename set comment= trim(concat(substr(comment, 1,1),space(1),substr(comment, 2,1),space(1),substr(comment, 3,1),space(1),substr(comment, 4,1),space(1),substr(comment, 5,1),space(1),substr(comment, 6,1),substr(comment, 7)));
here comment is column name

Related

Oracle INSTR replacement in MySQL

Requirements: Before, I used instr() in Oracle to achieve the requirements, but now I want to use MySQL to achieve the same effect, and try to use the functions in MySQL to achieve it.
INSTR(A.SOME_THING.B,".",1,2)<>0 --ORACLE
As far as I can tell, that's not that difficult for simple cases. But, as number of parameters raises, MySQL "replacement" for the same Oracle functionality gets worse.
As your code:
instr(some_thing, '.', 1, 2)
means
search through some_thing
for a dot
starting from the first position
and find dot's second occurrence
you can't do that in a simple manner using MySQL, as you'll need a user-defined function. Something like this (source is INSTR Function - Oracle to MySQL Migration; I suggest you have a look at the whole document. I'm posting code here because links might get broken):
DELIMITER //
CREATE FUNCTION INSTR4 (p_str VARCHAR(8000), p_substr VARCHAR(255),
p_start INT, p_occurrence INT)
RETURNS INT
DETERMINISTIC
BEGIN
DECLARE v_found INT DEFAULT p_occurrence;
DECLARE v_pos INT DEFAULT p_start;
lbl:
WHILE 1=1
DO
-- Find the next occurrence
SET v_pos = LOCATE(p_substr, p_str, v_pos);
-- Nothing found
IF v_pos IS NULL OR v_pos = 0 THEN
RETURN v_pos;
END IF;
-- The required occurrence found
IF v_found = 1 THEN
LEAVE lbl;
END IF;
-- Prepare to find another one occurrence
SET v_found = v_found - 1;
SET v_pos = v_pos + 1;
END WHILE;
RETURN v_pos;
END;
//
DELIMITER ;
Use it as
SELECT INSTR4('abcbcb', 'b', 3, 2);
and get 6 as a result.
In OracleDB the code
INSTR(column, ".", 1, 2) <> 0 --ORACLE
checks does the column contains at least 2 point chars in the value.
In MySQL this can be replaced with, for example,
LENGTH(column) - LENGTH(REPLACE(column, '.', '')) >= 2

Update a column in table according to another column in same table

I have a Mysql table name xyz which has two columns tc_name and tc_path where tc_path is like /a/b/c/x/tc_name and tc_name is null .I want to insert the values in the column(tc_name) using this tc_path column values.
I know it would be something like we do with regular expressions in other languages.But i have no idea how to do this in Mysql.
I source the function:
DELIMITER $$
CREATE FUNCTION `regex_replace`(pattern VARCHAR(1000),replacement VARCHAR(1000),original VARCHAR(1000))
RETURNS VARCHAR(1000)
DETERMINISTIC
BEGIN
DECLARE temp VARCHAR(1000);
DECLARE ch VARCHAR(1);
DECLARE i INT;
SET i = 1;
SET temp = '';
IF original REGEXP pattern THEN
loop_label: LOOP
IF i>CHAR_LENGTH(original) THEN
LEAVE loop_label;
END IF;
SET ch = SUBSTRING(original,i,1);
IF NOT ch REGEXP pattern THEN
SET temp = CONCAT(temp,ch);
ELSE
SET temp = CONCAT(temp,replacement);
END IF;
SET i=i+1;
END LOOP;
ELSE
SET temp = original;
END IF;
RETURN temp;
END$$
I tried this:
update testplans set tc_name=regex_replace('.*/','',tc_path);
It should have given me tc_name=d if tc_path=/a/b/c/d
But instead it gave me abcd.
Am i using a wrong function or i don't know how to use it.
Please suggest some query for it.
Please help!!!
Thanks
In THIS particular case, where you are trying to get the last part of a path, you can skip regex and use simple string functions:
update testplans set tc_name=substr(tc_path, length(tc_path)-locate('/',reverse(tc_path))+2);
Doing search in reverse order
The proper regex expression would be
.*/([^/]*)
But you'd need to extract the last part, which MySQL really doesn't do. MariaDB 10 has a REGEXP_REPLACE that might help.
The function you have above will replace single characters that match a regex, but it's not a full regular expression replacement. Basically, wrong function.
Mysql isn't great at this right now -- you might want to consider another path, like the one that Jacques suggested, with a simple string replace.
If you really want a regex solution, maybe look at a more complete regex library for mysql:
https://github.com/mysqludf/lib_mysqludf_preg

How use FULLTEXT SEARCH in mysql without special tags(<html>,<p> and other)

I make sarch in mysql with help next code:
SELECT * FROM `articles` WHERE MATCH (title,body) AGAINST ('database');
How use search in mysql without special tags(<html>,<p> and other)?
There is a php function can do this
strip_tags($text);
You can find more information here
http://php.net/manual/en/function.strip-tags.php
If you still want to do this in mysql , you have to define your own function
delimiter ||
DROP FUNCTION IF EXISTS strip_tags||
CREATE FUNCTION strip_tags( x longtext) RETURNS longtext
LANGUAGE SQL NOT DETERMINISTIC READS SQL DATA
BEGIN
DECLARE sstart INT UNSIGNED;
DECLARE ends INT UNSIGNED;
SET sstart = LOCATE('<', x, 1);
REPEAT
SET ends = LOCATE('>', x, sstart);
SET x = CONCAT(SUBSTRING( x, 1 ,sstart -1) ,SUBSTRING(x, ends +1 )) ;
SET sstart = LOCATE('<', x, 1);
UNTIL sstart < 1 END REPEAT;
return x;
END;
||
delimiter ;
Call the function in your search query after you define the function
$q="CALL strip_tags(SELECT textarea FROM table where ....)"
Remove the HTML tags before you store text in the column which is FULLTEXT indexed. If you need the original text, store that in a different column.
Alternatively, use a real search indexer, like Lucene. MySQL FULLTEXT is kind of a toy.

MySQL selecting string with multi special characters

I'm having a problem selecting strings from database. The problem is if you have +(123)-4 56-7 in row and if you are searching with a string 1234567 it wouldn't find any results. Any suggestions?
You can use the REPLACE() method to remove special characters in mysql, don't know if it's very efficient though. But it should work.
There is already another thread in SO which covers a very similar question, see here.
If it is always this kind of pattern you're searching, and your table is rather large, I advice against REPLACE() or REGEX() - which ofc will do the job if tweaked properly.
Better add a column with the plain phone numbers, which doesn't contain any formatting character data at all - or even better, a hash of the phone numbers. This way, you could add an index to the new column and search against this. From a database perspective, this is much easier, and much faster.
You can use User Defined Function to get Numeric values from string.
CREATE FUNCTION GetNumeric (val varchar(255)) RETURNS tinyint
RETURN val REGEXP '^(-|\\+){0,1}([0-9]+\\.[0-9]*|[0-9]*\\.[0-9]+|[0-9]+)$';
CREATE FUNCTION GetNumeric (val VARCHAR(255))
RETURNS VARCHAR(255)
BEGIN
DECLARE idx INT DEFAULT 0;
IF ISNULL(val) THEN RETURN NULL; END IF;
IF LENGTH(val) = 0 THEN RETURN ""; END IF;
SET idx = LENGTH(val);
WHILE idx > 0 DO
IF IsNumeric(SUBSTRING(val,idx,1)) = 0 THEN
SET val = REPLACE(val,SUBSTRING(val,idx,1),"");
SET idx = LENGTH(val)+1;
END IF;
SET idx = idx - 1;
END WHILE;
RETURN val;
END;
Then
Select columns from table
where GetNumeric(phonenumber) like %1234567%;
Query using replace function as -
select * from phoneTable where replace(replace(replace(phone, '+', ''), '-', ''), ')', '(') LIKE '%123%'

using mysql string functions

I have a table with following Data in a table
abcd
abcd , pgw
ABcd , Pgw
I want output as
Abcd
Abcd , Pgw
Abcd , Pgw
the First letter in capitals and letter after ',' in capital.
to make first letter upper-case use this
select CONCAT(UPPER(LEFT(`field`, 1)), SUBSTRING(`field`, 2)) from mytable
to do it to also to word after comma declare a function like :
DELIMITER ||
CREATE FUNCTION `ucwords`( str VARCHAR(128) ) RETURNS VARCHAR(128) CHARSET latin1
BEGIN
DECLARE c CHAR(1);
DECLARE s VARCHAR(128);
DECLARE i INT DEFAULT 1;
DECLARE BOOL INT DEFAULT 1;
SET s = LCASE( str );
WHILE i < LENGTH( str ) DO
BEGIN
SET c = SUBSTRING( s, i, 1 );
IF c = ',' 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;
END IF;
END;
END IF;
SET i = i+1;
END;
END WHILE;
RETURN s;
END ||
DELIMITER ;
and use
select ucwords(`field`) from mytable
Please don't do this if you ever expect your database to scale well. If you're only ever going to be using this for your personal phone book application or equally tiny data sets, you can get away with doing this at select time, as you suggest.
But, if you want a robust scalable database, you should sacrifice space (disk storage) for time (speed). Per-row functions on select statement rarely scale well.
One time-honored and tested way of doing this is to add another column of identical specifications to the one you already have and use an insert/update trigger to populate it with the data in the format you desire.
Then the cost of the transformation is incurred only when you have to (when the data is updated), not every single time you read the data. This amortises the cost across the reads which, in the vast majority of databases, outweigh writes considerably.
This answer shows an SQL formula which seems close to what you want but I do strongly suggest that you use it in a trigger rather than inefficiently running it every select.
take a look at this solution mysql-update-script-problem-all-txt-is-lower-case-just-first-letter-is-upper-cas , it should give you enough information to adapt to what you're trying to do. Change update to SELECT, etc. etc.