fetch first occurrence of numbers from a table column - mysql

I want to fetch first occurrence of numbers from a table column.
To illustrate:
For column value 'C 62/3,Industrial Area, Phase 2', I should get '62/3'
For column value 'B-5 dummy, (dummy)', I should get 'B-5'
For column value '21 dummy - 2, dummy' I should get '21'.
I tried:
select address,SUBSTRING(address, 1, LOCATE(' ', address) - 1) AS str
from items;

Well, I'm not a MySQL expert but I think you have to use a library like mysql-udf-regexp. Using this you can get the first digit-containing sub string with REGEXP_SUBSTR:
SELECT
address,
REGEXP_SUBSTR(address, '[[^:space:]]*[[:digit:]]+[[^:space:]]*', 1, 1) AS str
FROM items;
This is untested code but should give you an idea how to proceed. It means that you get any positive number of digits ([[:digit:]]+) followed and succeeded by any number of non-white spaces ([[^:space:]]*); starting search from first character and return first occurrence (,1 ,1).

Related

how to randomize column data and mask data using mysql

DISCLAIMER: NONE OF THESE VALUES ARE TRUE/REAL, ITS JUST A PRACTICE ASSIGNMENT
how to randomize the last 6 digits of the DBS account and obscuring the first 4 digits of the NRIC number with x using mysql. All values were keyed in manually and do not relate to each other.
Current
Desired Result
Just use substring operations:
SELECT
CONCAT('XXXX', SUBSTRING(NRIC, 5, 4)) AS NRIC,
Name,
Contact,
Salary,
CONCAT(SUBSTRING(DBS_Account, 1, 3), '-XXXXX-X') AS DBS_Account
FROM yourTable;
mysql rand function - https://dev.mysql.com/doc/refman/5.7/en/mathematical-functions.html#function_round
using substring and concat
SELECT CONCAT(SUBSTRING(RAND(),3,5),'-',SUBSTRING(RAND(),3,1))
will give something like 40033-8
then concat with substring
set #a ='038-12645-6';
SELECT CONCAT(substring_index(#a,'-',1),'-',SUBSTRING(RAND(),3,5),'-',SUBSTRING(RAND(),3,1));
'038-63475-5'

replace a character in mysql with a random character from a list

i would like to perform Mysql search & replace with random characters, taken from a list. I cannot use regex, since my version is way prior to 8.
instead of the below,
i would like to change for instance the letter u with one out of (a,e,i,f,k) randomly.
UPDATE products
SET
productDescription = REPLACE(productDescription,
'abuot',
'about');
Is there a mysql command for this task?
Actually my goal is to get in the lastnames column, new names that are not exactly like the real ones, so one could work on "anonymous" data.
I would like to replace all rows in a certain column. Say in table products, in column description, we have data like:
abcud
ieruie
kjuklkllu
uiervfd
With the replace function, we would not want to create something like: replace e with i,
but replace e with one of (a,e,i,f,k)
example desired output:
abced
ierfie
kjiklkllk
aiervfd
like i said, we plan to use this into last names, we plan to replace many characters with random ones from a list, in an effort to create anonymous data in the column that contains last names.
On a next step, i would like to do the same, in order to make anonymous telephone numbers.
example
726456273
827364878
347823472
replace 3 with one of 0-9,
output:
726456279
827664878
547821472
SELECT REPLACE('product abuot Description',
SUBSTRING('product abuot Description', CHARINDEX('abuot', 'product abuot Description') ,5) , 'about')
CREATE FUNCTION smart_replace ( argument TEXT,
search_for CHAR(1),
replace_with TEXT )
RETURNS TEXT
NO SQL
BEGIN
SET argument = REPLACE(argument, search_for, CHAR(0));
REPEAT
SET argument = CONCAT( SUBSTRING_INDEX(argument, CHAR(0), 1),
SUBSTRING(replace_with FROM CEIL(RAND() * LENGTH(replace_with)) FOR 1),
SUBSTRING(argument FROM 2 + LENGTH(SUBSTRING_INDEX(argument, CHAR(0), 1))));
UNTIL NOT LOCATE(CHAR(0), argument) END REPEAT;
RETURN argument;
END
replace e with one of (a,e,i,f,k)
SELECT smart_replace(table.column, 'e', 'aeifk')
replace 3 with one of 0-9
SELECT smart_replace(table.phone, 'e', '0123456789')

Searching a string in a column

can anyone help me. i have a DB in mysql, and need to search for a string in a particular column.
the field is var char, and contains various serial number, divided by the character "/".
example
613003593/8876572/TJMC49
the problem is searching in the string. If i use like, it will work most of the times, but not always, because if i do a like '%13003593%' it will return one row, when that is not true, the saved value is 613003593. how can i search, the string.
on the example there are 3 strings divided, and i need to search all of them.
apologies for my english
For the first part of the serial number,
SELECT * FROM table_name
WHERE SUBSTRING_INDEX(serial_number, '/', 1) = '613003593';
For the 2nd part,
SELECT * FROM table_name
WHERE SUBSTRING_INDEX(SUBSTRING_INDEX(serial_number, '/', 2), '/', -1)='8876572';
For the last part,
SELECT * FROM table_name
WHERE SUBSTRING_INDEX(SUBSTRING_INDEX(serial_number, '/', 3), '/', -1)='TJMC49';
Check How to split and search in comma-separated string in MySQL

How do I covert some column's value by using SQL on MYSQL?

I have a table named Employee in my database, the structure is as shown below:
Id email phone name
1 user#gmail.com +7845690001 Jonney
2 Nortex.zone#gmail.com +7845690781 North
I have some data that I want to mask, for example +7845690001 to +7845690***. Full version as below.
Id email phone name
1 u**r#gmail.com +7845690*** J****y
2 N*********e#gmail.com +7845690*** N***h
I managed to do this for name and phone:
Select CONCAT(MID(phone, 1, LENGTH(phone) - 3), '***') as new_phone,
CONCAT(LEFT(name,1),REPEAT("*",LENGTH(name)-2),RIGHT(name,1)) as new_name from employee.
How can I do this for email?
Finally found the answer:
Select CONCAT(MID(phone, 1, LENGTH(phone) - 3), '***') as new_phone,
CONCAT(LEFT(name,1),REPEAT("*",LENGTH(name)-2),RIGHT(name,1)) as new_name,CONCAT(CONCAT(left(email,1),REPEAT("*",LENGTH(SUBSTRING_INDEX(email, "#", 1))-2),RIGHT(SUBSTRING_INDEX(email, "#", 1),1)),'#',SUBSTRING_INDEX(email,'#',-1)) as new_email from employee
Thanks all. :)
You can work with MySQL's string functions: LEFT(),RIGHT(),LENGTH(), REPEAT(), and SUBSTRING_INDEX() .
I'll just do it for email:
WITH
input(Id,email,phone,name) AS (
SELECT 1 , 'user#gmail.com' ,'+7845690001','Jonney'
UNION ALL SELECT 2 , 'Nortex.zone#gmail.com' ,'+7845690781','North'
)
SELECT
id
, -- the leftmost single character or "email"
LEFT(email,1)
-- repeat "*" for the length of the part of "email" before "#" minus 2
|| REPEAT('*',LENGTH(SUBSTRING_INDEX(email,'#',1))-2)
-- the rightmost single character of the part of "email" before "#"
|| RIGHT(SUBSTRING_INDEX(email,'#',1),1)
-- hard-wire "#"
||'#'
-- the part of "email" from the end of the string back to "#"
||SUBSTRING_INDEX(email,'#',-1)
AS email
FROM input
-- out id | email
-- out ----+-----------------------
-- out 1 | u**r#gmail.com
-- out 2 | N*********e#gmail.com
-- out (2 rows)
You can use CONCAT and SubSTRING functions in mysql.
The email and name has the same feature, use the same thing for name and change digits based your requirement.
SELECT CONCAT(LEFT(`name`, 1),"***",RIGHT(`name`, 1)) as cname, CONCAT(LEFT(`email `, 1),"***",SUBSTRING(`email `, LOCATE("#", `email `)-1, LENGTH(`email `)-LOCATE("#", `email `)-1)) as cemail , CONCAT(LEFT(`phone`, 8),"***") as cphone FROM `test4`
EDITTED -----------------
To fill by the exact number of characters you can use LPAD function. For name you can do:
SELECT CONCAT(LEFT(`name `,1),LPAD(RIGHT(`name `,1),LENGTH(`name `)-1,'*')) FROM `test4`
Use LOCATE and change indexes based on upper query for email.
A REGEXP_REPLACE can also do the trick. Here is how to do it for the email:
SELECT REGEXP_REPLACE(email, '(?!^).(?=[^#]+#)', '*') AS masked_email
FROM Employee;
Explanation:
(?!^) we make sure that the matching character is not at the beginning of the string and that way we skip the first character.
. matches the character to be replaced
(?=[^#]+#) we will stop at a sequence which is any character that is NOT #, then followed by #.
Every single character which is matched between the two will then be replaced with a * (the third parameter) by the function.
For the phone number I will show a much simpler solution:
SELECT REGEXP_REPLACE(phone, '[0-9]{3}$', '***') AS masked_phone
FROM Employee;
[0-9]{3} matches exactly three digits
$ tells that they must be at the end of the string.
We then replace them with three stars. Please note that this solution is assuming that you always store the phone numbers in a way that they always end with three digits. So for example if I enter a phone like "555-55-55-55", nothing will be masked. If you do not always insert the phones normalized in the same format, then you must think about something more complicated (like fetch digit - fetch zero or more non digits - fetch digit - fetch zero or more non digits - fetch digit - end of string, then replace whatever is matched with three *-s). Like this:
SELECT REGEXP_REPLACE(phone, '[0-9][^0-9]*[0-9][^0-9]*[0-9][^0-9]*$', '***') AS masked_phone
FROM Employee;
Here [0-9] means a single digit and [^0-9]* means zero or more non-digits. And of course the same thing can be simplified by grouping the digit and the zero or more non-digits in one group which is then repeated exactly three times:
SELECT REGEXP_REPLACE(phone, '([0-9][^0-9]*){3}$', '***') AS masked_phone
FROM Employee;
And for the name, we can do the following:
SELECT REGEXP_REPLACE(name, '(?!^).(?=.+$)', '*') AS masked_name
FROM Employee;
So again we skip the first character, than match and replace every character until the last character of the string.
IMPORTANT: In the above examples we preserve the length of the strings. If you want higher anonymity, you can fetch the data in groups and then replace a desired group with a single *. For example for the e-mail:
SELECT REGEXP_REPLACE(email, '^(.)(.)+([^#]#.+)$', '\\1*\\3') AS masked_email
FROM Employee;
This will replace john#gmail.dom to j*n#gmail.dom and margareth#gmail.dom to m*h#gmail.dom. So it masked the length as well. Explanation:
^ is the start of the string
(.) is our first group. It it s single character
(.)+ is the second group. It's one or more characters.
([^#]#.+) is our third group. It is a single character which is NOT #, followed by #, then followed by one or more characters (any).
We replace that with \1 (the first group), followed by a single *, followed by \3 (the third group).

Getting first part from the Postcode?

Using MySQL how to grab first part of the data.postcode field?
For example:
M40 1JY
M8 8NW
I want to display like this:
M40
M8
select substring(postcode, 1, locate (' ', postcode) - 1) from data;
locate (' ', postcode) returns the position of the space (), the first input, out of the second input (your column), you don't want to display the space so subtract 1 from this number.
substring(data, start, length) takes the substring of the data (your column) from the number of start, you want to start at the beginning, so this is 1, and displays the number of letters you enter in length, this is the result of locate.
Use substring and locate:
select substring(postalcode,1,LOCATE(" ",postalcode)) from `data`
locate will find the index of blank and substring gives you the substrung until this Position.
The SUBSTRING_INDEX(str,delim,count) function is what you need. This function return the substring from string str before count occurrences of the delimiter delim. You can go the this link for more details. http://dev.mysql.com/doc/refman/5.0/en/string-functions.html#function_substring-index
For your problem,
SELECT SUBSTRING_INDEX(postcode, ' ', 1) from YourTable;
will return
M40
M8