Replacing first occurrence of character with one character and the second with another character in SQL - sql

I have a table with a column Name that can contain substring surrounding with quotations ..."substring"...
For each row in this table I need to replace first occurrence of " with « and second one with »
Each row can contain only one quoted substring.
So if I have a record like this 'fgh"abc"sdf' I want to get this 'fgh«abc»sdf'
I can't come up with a solution for this.

First an example of how the syntax works
DECLARE #a varchar(max) = 'fgh"abc"sdf'
SELECT
stuff(stuff(#a, charindex('"', #a),1, '«'),
charindex('"', #a, charindex('"', #a) + 1), 1, '»')
Result:
fgh«abc»sdf
This is the query needed where col is the name of your column:
SELECT
stuff(stuff(col, charindex('"', col),1, '«'),
charindex('"', col, charindex('"', col) + 1), 1, '»')
FROM yourtable

You can do something like :
DECLARE #TmpVar VARCHAR(100)
SET #TmpVar = 'haha"substring"hehe'
SET #TmpVar = STUFF(#TmpVar, CHARINDEX('"', #TmpVar), 1, '«')
SET #TmpVar = REPLACE(#TmpVar, '"', '»')

Related

Extract value in between string in SQL

I have a sample string like below and this string always contains the word "Inventory Charge[0.00068]"
DECLARE #Text NVARCHAR(MAX) = 'Materials Discount[0] ) + Inventory Charge[0.00068] Second gfggfdgfd gfgfgfgf'
would like to get value in between brackets for Inventory Charge.
Required output: 0.00068
I have tried with substring but not able to get the desired result. Please help.
DECLARE #Text NVARCHAR(MAX) = 'Materials Discount[0] ) + Inventory Charge[0.00068] Second'
SELECT SUBSTRING(#Text, CHARINDEX('Inventory Charge[', #Text) +
LEN('Inventory Charge[') + 1, CHARINDEX(']',#Text)
- (CHARINDEX('Inventory Charge[', #Text) + 2 + LEN('Inventory Charge[')) )
I find this type of thing easier to work out when breaking it down. It also helps avoid repeating the initial search for the starting substring location:
declare #text NVARCHAR(MAX) = 'Materials Discount[0] ) + Inventory Charge[0.00068] Second'
declare #leftSearchStr nvarchar(20) = 'Inventory Charge['
declare #rightSearchStr nvarchar(20) = ']'
declare #startPos int = charindex(#leftSearchStr, #text, 1) + LEN(#leftSearchStr)
declare #endPos int = charindex(#rightSearchStr, #text, #startPos)
SELECT SUBSTRING(#text, #startPos, #endPos - #startPos)
I solved it like this. Surely there is a better way to solve this, but this works.
DECLARE #Text NVARCHAR(MAX) = 'Materials Discount[0] ) + Inventory Charge[0.00068] Second',
#Trim1 NVARCHAR(MAX),
#Trim2 NVARCHAR(MAX)
SET #Trim1 = SUBSTRING(#Text, CHARINDEX('[', #Text) + 1,LEN(#Text))
SET #Trim2 = SUBSTRING(#Trim1, CHARINDEX('[', #Trim1) + 1, LEN(#Trim1))
SELECT LEFT(#Trim2, LEN(#Trim2) - CHARINDEX(']', #Trim2) - 3)
If you know that the string you want to select is the Last bracketed selection, then we can simply use REVERSE and then find the first bracketed value.
If you have to do this in a single operation, I find it easier to incorporate a CROSS APPLY to calculate the steps in between:
DECLARE #Text NVARCHAR(MAX) = 'Materials Discount[0] ) + Inventory Charge[0.00068] Second'
SELECT Reverse(SubString(RevText, [RLeft], [RRight]-[RLeft]))
FROM ( SELECT REVERSE(#Text) as RevText) text
OUTER APPLY (SELECT CHARINDEX(']', RevText) + 1 as [RLeft],
CHARINDEX('[', revText) as [RRight]) Calcs
If you don't know for sure that the search term is the first or last bracket, then we just need to search on the prefix first, and use that as the start location for the CharIndex function:
SELECT SubString([Text], [Left], [Right]-[Left])
FROM ( SELECT #Text as [Text], 'Inventory Charge[' as prefix ) inputs
OUTER APPLY (SELECT CHARINDEX(prefix, [Text]) + LEN(prefix) as [Left]) Calcs1
OUTER APPLY (SELECT CHARINDEX(']', [Text], [Left]) as [Right]) Calcs2
You can get a little bit fancy using STRING_SPLIT to tokenize the input for you too, note that you need to split by the close bracket so that the value and the field prefix are in the same result:
This solution uses REVERSE again because we know the token is at the end of the line, so we can use LEFT logic to save an index lookup
SELECT Reverse(LEFT(REVERSE(value), CHARINDEX('[', REVERSE(value))-1))
FROM String_Split(#Text, ']') s
WHERE s.value LIKE '%Inventory Charge%'
Or you can use SUBSTRING again:
SELECT SUBSTRING(value,[LEFT],[Length] - [Left] + 1)
FROM String_Split(#Text, ']') s
CROSS APPLY (SELECT CHARINDEX('[', value) + 1 as [LEFT], LEN(value) as [Length]) calcs
WHERE s.value LIKE '%Inventory Charge%'

Find values in between two characters '(' and ')' in column that have nulls

I have a table name authors. I need to extract the values at the end of their names excluding '(' and ')'.
I have tried to use a substring with Charindex function.
select
isnull (SUBSTRING(name,CHARINDEX('(',name) +1 ,CHARINDEX(')',name) - CHARINDEX('(',name) - 1), '') as [Name]
from Authors
But I got an error message.
Msg 537, Level 16, State 3, Line 6
Invalid length parameter passed to the LEFT or SUBSTRING function.
Here is what I am expecting my results to be.
For your data, I would do something like this:
select coalesce(replace(stuff(name, 1, charindex('(', name + '(') + 1, ''), ')', ''),
'') as [Name]
This assumes that the parentheses are at the end of the string, as in the examples.
declare #string nvarchar(25)
set #string = '(asdfgh)'
select REPLACE( REPLACE(#string,'(',''),')','') where #string like '%[(]%%[)]%'
in above code i used regex to find string between ( and ) then replace them by empty
here you go, apply to your situation
declare #string varchar(25)
set #string = '(asdfgh)'
SELECT SUBSTRING(#string,
charindex('(', #string)+1,
charindex(')', #string)-
charindex('(', #string)-1)
You can use APPLY :
select substring(name, tt.startp + 1, (endp - startp) - 1) as Name
from Authors a cross apply
( values (charindex('(', name + ')'), charindex(')', name + ')'))
) tt(startp, endp);
Your Name column doesn't have a (...) in some places so, you can add either where clause or add explicitly (...) at the end of string.

Select only characters in SQL

I have strings in a database like this:
firstname.lastname#email.com
And I only need the characters that appear after the # symbol and before (.) symbol i.e. (email) from the above example
I am trying to find a simple way to do this in SQL.
Do this:
use [your_db_name];
go
create table dbo.test
(
string varchar(max) null
)
insert into dbo.test values ('firstname.lastname#email.com')
select
string,
substring(
string,
charindex('#', string, 0) + 1,
charindex('.', string, charindex('#', string, 0)) - charindex('#', string, 0) - 1
) as you_need
from dbo.test
String manipulations are such a pain in SQL Server. Here is one method:
select t.*,
left(en.emailname, charindex('.', en.emailname + '.') - 1)
from t outer apply
(select stuff(email, 1, charindex('#', email + '#'), '') as emailname) en;
That that in the charindex() calls, the character being searched for is placed at the end of the string. This allows the code to work even for malformed emails -- it returns an empty string when the email is not of the form '%#%.%'.
DECLARE #col char(200)
set #col = 'firstname.lastname#email.com'
SELECT SUBSTRING(#col, LEN(LEFT(#col, CHARINDEX ('#', #col))) + 1, LEN(#col) - LEN(LEFT(#col, CHARINDEX ('#', #col))) - LEN(RIGHT(#col, LEN(#col) - CHARINDEX ('.', #col))) - 4);
DECLARE #str varchar(50) = 'firstname.lastname#email.com';
SELECT LEFT(
RIGHT(#str, LEN(#str) - CHARINDEX('#', #str))
,CHARINDEX('.', RIGHT(#str, LEN(#str) - CHARINDEX('#', #str))
) - 1) AS OUTPUT
Above query gives only domain-name from Email. The query can be applied for column in a table
Try This:-
DECLARE #Text varchar(100)
SET #Text = 'firstname.lastname#email.com'
SELECT SUBSTRING(STUFF(#Text, 1, CHARINDEX('#',#Text), ''), 0,
CHARINDEX('.', STUFF(#Text, 1, CHARINDEX('#',#Text), '')))
Result:-
email
DECLARE #myStr varchar(100) = 'firstname.lastname#email.com'
SELECT
SUBSTRING(SUBSTRING(#myStr,CHARINDEX('#',#myStr)+1,LEN(#myStr)-CHARINDEX('#',#myStr)+1),0,CHARINDEX('.',SUBSTRING(#myStr,CHARINDEX('#',#myStr)+1,LEN(#myStr)-CHARINDEX('#',#myStr)+1)))
That can be useful but I really recommend you to build user defined function in C#/Visaul basic they could be much more faster that this.
Using charindex, len and reverse to search for the positions of the # and the last dot.
And substring to get the name based on those positions:
create table test (id int identity(1,1), email varchar(60));
insert into test (email) values
('jane.doe#email.com'),
('not an email'),
('#invalid.email.xxx'),
('john.doe#longer.domainname.net');
select *,
(case
when email like '[a-z]%#%.%'
then substring(email,
charindex('#',email)+1,
len(email) - charindex('#',email) - charindex('.',reverse(email))
)
end) as email_domain_without_extension
from test;
The CASE WHEN is used to return NULL when it's not an email (instead of an empty string).

Return a SUBSTRING with a known Prefix and Suffix Character

I have a table that has a Prefix of variable length that always ends with . and a suffix of variable length that always begins with -. The - can also be found in the string of text that I am looking for, so using REVERSE() is likely the best way to identify the suffix -.
ex: Prefix1.ABC-123-Suffix1
I'd like the SUBSTRING() result to look like: ABC-123
I was able to create both a SUBSTRING() to remove the Prefix and a SUBSTRING() to remove the suffix, but I'm having a hard time applying both. The returned text can be variable length.
I'm trying to avoid declaring a variable, but am open to it. I'd prefer to only use SUBSTRING(), REVERSE(), and CHARINDEX() if possible.
This is what I have so far:
SELECT [Col1]
,SUBSTRING((Col1),CHARINDEX('.', (Col1)) + 1, 999) AS [StrippedPrefix]
,REVERSE(SUBSTRING(REVERSE(Col1),CHARINDEX('-', REVERSE(Col1)) + 1, 999)) AS [StrippedSuffix]
--new SUBSTRING() with both Prefix and Suffix stripped
FROM [Table1]
Declare #YourTable table (Col1 varchar(50))
Insert Into #YourTable values
('Prefix1.ABC-123-Suffix1')
Select *
,String=Substring(Col1,charindex('.',Col1)+1,len(Col1)-charindex('.',Col1)-charindex('-',reverse(Col1)))
From #YourTable
Returns
Col1 String
Prefix1.ABC-123-Suffix1 ABC-123
As per M Ali's suggestion (Even better)
Select *
,String=PARSENAME(REPLACE(Col1 , '-', '.') , 3) + '-' + PARSENAME(REPLACE(Col1 , '-', '.') , 2)
From #YourTable
Here the varaiable is only used as demo - should work with your table as well:
DECLARE #s nvarchar(100) = 'Prefix1.ABC-123-Suffix1'
SELECT #s,
SUBSTRING(#s, 1, CHARINDEX('.', #s)-1) StrippedPrefix,
SUBSTRING(#s, LEN(#s)-CHARINDEX('-', REVERSE(#s))+2, CHARINDEX('-', REVERSE(#s))) StrippedSuffix,
SUBSTRING(#s, CHARINDEX('.', #s)+1, LEN(#s)-CHARINDEX('.', #s)-CHARINDEX('-', REVERSE(#s))) NewString
Here is one way
DECLARE #str VARCHAR(100)= 'Prefix1.ABC-123-Suffix'
SELECT Reverse(Stuff(intr_str, 1, Charindex('-', intr_str), ''))
FROM (SELECT Reverse(Stuff(#str, 1, Charindex('.', #str), '')) AS intr_str) a
Result : ABC-123

SQL Wildcards to RegExp replace certain text in a column content

I have got a table where one of the column has text mixed with HTML data. This was due to a bug (fixed) in a script, but the SQL data needs to be edited to reflect the changes. The column has a type nvarchar(max, null). All I need to do is find tags such as <a img="lkss">,<div attr=val> and replace them with empty string "". I looked into this, but the solution says how to replace the entire contents based on one pattern. My problem is that I need to replace contents partly, but preserve clean text (i.e. not HTML tags/attributes). Any suggestion/help is appreciated.
Test column data:
<div attr=val; color=somecolor>inside text<div some=val><a some=val>Inside anchor
Expected result:
inside textInside anchor
I use a CTE like this:
DECLARE #str nvarchar(max) = '<div attr=val; color=somecolor>inside text<div some=val><a some=val>Inside anchor';
WITH CTE(myStr) AS (
SELECT #str
UNION ALL
SELECT REPLACE(mystr, SUBSTRING(myStr, CHARINDEX('<', myStr, 1), CHARINDEX('>', myStr, 1) - CHARINDEX('<', myStr, 1) + 1), '')
FROM CTE
WHERE PATINDEX('%<%>%',myStr) > 0
)
SELECT myStr
FROM CTE
WHERE PATINDEX('%<%>%',myStr) = 0
I suggest you to use it in a SVF like this:
CREATE FUNCTION tagRemover
(
#str nvarchar(max)
)
RETURNS nvarchar(max)
AS
BEGIN
DECLARE #ResultVar nvarchar(max);
SELECT #ResultVar = #str;
;WITH CTE(myStr, id) AS (
SELECT #str, 1
UNION ALL
SELECT REPLACE(mystr, SUBSTRING(myStr, CHARINDEX('<', myStr, 1), CHARINDEX('>', myStr, 1) - CHARINDEX('<', myStr, 1) + 1), ''), id + 1
FROM CTE
WHERE PATINDEX('%<%>%',myStr) > 0
)
SELECT #ResultVar = myStr
FROM CTE
WHERE PATINDEX('%<%>%',myStr) = 0;
RETURN #ResultVar;
END
GO