How to find and replace string using REGEXP_REPLACE in postgresql - sql

I have a table of email addresses:
CREATE TABLE contacts(
email VARCHAR(255)
)
INSERT INTO contacts VALUES
('example.person#gmail.com'),
('example.person2#gmail.com'),
('example.person3#gmail.com');
How can I find and replace the email format so example.person#gmail.com -> example.person_gmailcom#test.com?
E.g:
UPDATE contacts
SET email = REGEXP_REPLACE(email, '#', '#test.com');
Results in example.person#test.comgmail.com
Playground here: https://dbfiddle.uk/GnIfomiO

This is probably most simply done by splitting the email address in two on the #, keeping the part before it and replacing . in the part after it with nothing. Then you can just append #test.com to the result:
UPDATE contacts
SET email = SPLIT_PART(email, '#', 1) || '_' || REPLACE(SPLIT_PART(email, '#', 2), '.', '') || '#test.com';
Output for your demo:
email
example.person_gmailcom#test.com
example.person2_gmailcom#test.com
example.person3_gmailcom#test.com
Demo on dbfiddle

demo: https://dbfiddle.uk/0KWPVeAI
UPDATE contacts
SET email = REGEXP_REPLACE(email, '#', '_gmailcom#');
UPDATE contacts
SET email = REGEXP_REPLACE(email, '#.*$', '#test.com');
The regex pattern is # follow all the chars to end of string

Related

Find a string inside a string and update in SQL Server

I have a table like this :
create table Fbank (id int, COCODE nvarchar(max))
insert into Fbank
values (1, '<row xml:space="preserve" id="174580000041250.040002">
<c1>HTG115960001</c1>
<c2>14013514,48</c2>
<c3>222</c3>
<c4>BAL MIGRATED</c4>
<c5>NULL</c5>
<c6>NULL</c6>
<c7>NULL</c7>
<c8>9900</c8>
<c9>11596</c9>
<c10>20151017</c10>
<c11>HTG</c11>
<c12>NULL</c12>
<c13>NULL</c13>
<c14>FT1529010083</c14>
<c15>1</c15>
<c16>FT1529010083</c16>
<c17>FT</c17>
<c18>20151017</c18>
<c19>NULL</c19>
<c20>0</c20>
<c21>5033_INPUTTER__OFS_AUTO.FT</c21>
<c22>5033_INPUTTER_OFS_AUTO.FT</c22>
<c23>1510181127</c23>
<c24>HG0010001</c24>
</row>')
I need to replace the string inside the tag c24 tag..
Excepted output: I need to replace the letter 'G' to be replaced with 'T' like this inside c24 tag - HT0010001 and all the rest should be same unchanged...
What I tired:
declare #searchText varchar(20) = (
select SUBSTRING(COCODE,CHARINDEX('<c24>', COCODE), 7)
from FBNK_EB_SFF_ACCT_HI000)
update Fbank
set cocode = STUFF(#searchText, CHARINDEX('<c24>', COCODE), 1, 'T')
If the code always begins with 'H', then I imagine it's easier to just have '<c24>H' be part of the string to replace, but then add it back again:
update Fbank
set COCODE = replace(cocode, '<c24>HG', '<c24>HT');
If it doesn't, then I'd say you're on the right track with charindex and substring. But use patindex instead, and update fbank directly, don't put the search term into any variable. If you're trying to split up your logic into parts, consider cross apply:
update fb
set cocode = stuff(cocode, ix, 1, 'T')
from Fbank fb
cross apply (select ix = patindex('%<c24>%', cocode) + 6) ap
where substring(cocode, ix, 1) = 'G'

Postgres generate a unique username

I have a requirement where I need to generate to unique usernames. I know how I would do it server side but want to make it as efficient as possible and do it on the database as part of a procedure but unsure where to start as I don't work with SQL too often.
I want to be able to create a username using the first letter of their forename and their surname plus some numbers and if a user already exists with that username then update it by 1. e.g.
I have users
Bob Jones bjones1
Bill Jones bjones2
If a user Beatrice Jones is added then that will be bjones3.
However users can choose to pick their username so someone may have already chosen bjones3 so I want it to automatically generate bjones4.
If there are no user B Jones then the first username created should be bjones
Ideally this would all happen as part of the user insert into the database so my Go code just executes a single database call and the user gets inserted.
Update:
When a user chooses their own username I check if it exists and block them from using it if it exists.
Hmmm . . . I think this will do:
select 'bjones' || coalesce(lpad( ((regexp_match(max(username), '[0-9]+$'))[1]::int + 1)::text, 5, '0'), '00000')
from t
where username ~ '^bjones[0-9]{5}$';
Here is a db<>fiddle.
More strict and parameterized, with 4-digit sequential number.
with
unp as -- user name prefix
(select left(lower(:givenname), 1) || lower(:surname) unp),
maxno as -- max existing seq.number for this username prefix
(
select coalesce(max((regexp_match(username, '(\d+)$'))[1]::integer), 0) maxno
from usernames
where username ~ ('^'||(select unp from unp)||'\d+$')
)
select (select unp from unp) || to_char((select maxno + 1 from maxno), 'FM0009') username;
I did something similar with the following code:
_username = left(lower(_firstname), 1) || lower(_lastname);
PERFORM id FROM users WHERE username = _username;
IF FOUND THEN
FOR i in 1 .. 999
LOOP
_username := _username || i;
PERFORM id FROM users WHERE username = _username;
IF NOT FOUND THEN
EXIT;
END IF;
END LOOP;
END IF;

how do I use OR operator in regular expression for sql

I've having problem with using OR operator in regular expression for updating the multiple set for email that doesn't work at all. I'm trying to update from:
alisonsmith#gmail.com
bobgraves#hotmail.com
smithers#yahoo.com
011013092949#bony.com
james#bony.com
result should look like this:
alisonsmith#dony.com
bobgraves#dony.com
smithers#dony.com
011013092949#bony.com
james#bony.com
I've tried that update procedure for using OR operator like this and it didn't work at all:
update dbo.Membership
set Email = left(Email, charindex('#', Email, 0)) + 'dony.com'
OR Email= left(Email, charindex('#', Email, 0)) + 'bony.com';
Is this what you want?:
update dbo.Membership
set Email = left(Email, charindex('#', Email, 0)) + 'dony.com'
WHERE Email NOT LIKE '%#bony.com'

firebird trigger string concatenation

anyone can help me with this. I created a trigger in firebird. I have this line that uses concatenation.
NEW.FIELDNAME = FIELD1 || FIELD2;
but it is not working, no record has been inserted. Is there any way for string concatenation? THANKS IN ADVANCE!
here is my full trigger
*query that initiate the variable PREV_STATUS:
SELECT FIRST 1 PREV_STATUSPERMINS FROM C3_EQUIPTSTATEPERMIN
WHERE TESTERID = NEW.TESTERID ORDER BY DATEMODIFIED DESC INTO :PREV_STATUS;
IF(PREV_STATUS IS NULL) THEN
BEGIN
NEW.PREV_STATUSPERMINS = '000';
END
ELSE
BEGIN
NEW.PREV_STATUSPERMINS = PREV_STATUS || NEW.STATUS;
END
You should use the "new" keyword to access the values of your fields within a trigger :
new.fieldname = new.field1 || new.field2;
Also, don't forget that if either of the fields is null, the concatenation will be null. If you want to avoid that, you could do something like this :
NEW.FIELDNAME = coalesce(new.FIELD1, '') || coalesce(new.FIELD2, '')

Running a query and displaying result it in a TEdit

I have a TComboBox containing a list of names gathered from my database. Next to it is a TEdit that I intend on using for the purposes for displaying the ID number associated to each person.
Since firstName and lastName are separate fields within the table, but displayed together in the TCombobox I have written a small section to split the firstName and lastName into two separate variables:
pos := AnsiPos(' ', cbStudents.Text);
firstName := Copy(cbStudents.Text, 0, pos-1);
lastName := Copy(cbStudents.Text, pos+1, Length(cbStudents.Text));
Then I execute the SQL code:
try
query.Open;
query.SQL.Add('Select studentID');
query.SQL.Add('From student');
query.SQL.Add('Where firstName = ' + StrToQuote(firstName));
query.SQL.Add('And lastName = ' + StrToQuote(lastName));
editID.Text := query
finally
query.Free;
end;
Note: StrToQuote encapsulates the variable firstName and lastName with double quotes (" ")
The error that I am receiving is:
Argument out of range
What am I doing wrong? Thank you in advanced for the help.
Your code can not work. It opens the query first, then it sets the SQL query string. Instead of
try
query.Open;
query.SQL.Add('Select studentID');
query.SQL.Add('From student');
query.SQL.Add('Where firstName = ' + StrToQuote(firstName));
query.SQL.Add('And lastName = ' + StrToQuote(lastName));
finally
query.Free;
end;
use
// create or reset query here
query := ...
try
query.SQL.Add('SELECT studentID');
query.SQL.Add('FROM student');
query.SQL.Add('WHERE firstName = :firstname');
query.SQL.Add('AND lastName = :lastName');
// set parameter values here
query.Open;
// now transfer data from fields to the user interface (TEdit)
finally
query.Free;
end;
Your approach does not seam optimal for me (splitting Displayed Name), but your problem here would be accessing query.Fields[0].AsString after freeing the query.