Replace pattern with value - sql

How can I replace the $SV### value in this string example if I don't know what the numbers following will be? Or even just get the 1234544 into another string variable.
I tried this but it doesn't replace anything:
declare #string varchar(100) = 'F4 Obstructed reach beyond. [$SV1234544" provided.]'
SELECT REPLACE(#string,PATINDEX('%$SV[0-9+]%',#string),'test')
Thank you!

The below code will work with the expectation that the number will always be prefixed with "$SV". It goes through a series of iterations to locate the numeric value after "$SV" and then replaces the "$SV" and the numeric number with whatever text you want it replaced with. This code uses the substring, patindex, concat, and replace functions.
DECLARE #string varchar(100) = 'F4 Obstructed reach beyond. [$SV1234544" provided.]'
DECLARE #SubString Varchar(100) = SUBSTRING(#string, PATINDEX('%$SV[0-9]%', #string), LEN(#string))
SELECT REPLACE(#string,CONCAT('$SV',LEFT(SUBSTRING(#SubString, PATINDEX('%[0-9.-]%', #SubString), 8000),PATINDEX('%[^0-9.-]%', SUBSTRING(#SubString, PATINDEX('%[0-9.-]%', #SubString), 8000) + 'X') -1)),'test')

Related

sql Return string between two characters

I want to know a flexible way to extract the string between two '-'. The issue is that '-' may or may not exist in the source string. I have the following code which works fine when '-' exists twice in the source string, marking the start and end of the extracted string. But it throws an error "Invalid length parameter passed to the LEFT or SUBSTRING function" when there is only one '-' or none at all or if the string is blank. Can someone please help? Thanks
declare #string varchar(100) = 'BLAH90-ExtractThis-WOW'
SELECT SUBSTRING(#string,CHARINDEX('-',#string)+1, CHARINDEX('-',#string,CHARINDEX('-',#string)+1) -CHARINDEX('-',#string)-1) as My_String
Desired Output: ExtractThis
If there is one dash only e.g. 'BLAH90-ExtractThisWOW' then the output should be everything after the first dash i.e. ExtractThisWOW. If there are no dashes then the string will have a blank space instead e.g. 'BLAH90 ExtractThisWOW' and should return everything after the blank space i.e. ExtractThisWOW.
You can try something like this.
When there is no dash, it starts at the space if there is one or take the whole string if not.
Then I look if there is only one dash or 2
declare #string varchar(100) = 'BLAH90-ExtractThis-WOW'
declare #dash_pos integer = CHARINDEX('-',#string)
SELECT CASE
WHEN #dash_pos = 0 THEN
RIGHT(#string,LEN(#string)-CHARINDEX(' ',#string))
ELSE (
CASE
WHEN #dash_pos = LEN(#string)-CHARINDEX('-',REVERSE(#string))+1
THEN RIGHT(#string,LEN(#string)-#dash_pos)
ELSE SUBSTRING(#string,#dash_pos+1, CHARINDEX('-',#string,#dash_pos+1) -
#dash_pos -1)
END
)
END as My_String
Try this. If there are two dashes, it'll take what is inside. If there is only one or none, it'll keep the original string.
declare #string varchar(100) = 'BLAH-90ExtractThisWOW'
declare #dash_index1 int = case when #string like '%-%' then CHARINDEX('-', #string) else -1 end
declare #dash_index2 int = case when #string like '%-%'then len(#string) - CHARINDEX('-', reverse(#string)) + 1 else -1 end
SELECT case
when #dash_index1 <> #dash_index2 then SUBSTRING(#string,CHARINDEX('-',#string)+1, CHARINDEX('-',#string,CHARINDEX('-',#string)+1) -CHARINDEX('-',#string)-1)
else #string end
as My_String
Take your existing code:
declare #string varchar(100) = 'BLAH90-ExtractThis-WOW'
SELECT SUBSTRING(#string,CHARINDEX('-',#string)+1, CHARINDEX('-',#string,CHARINDEX('-',#string)+1) -CHARINDEX('-',#string)-1) as My_String
insert one line, like so:
declare #string varchar(100) = 'BLAH90-ExtractThis-WOW'
SET #string = #string + '--'
SELECT SUBSTRING(#string,CHARINDEX('-',#string)+1, CHARINDEX('-',#string,CHARINDEX('-',#string)+1) -CHARINDEX('-',#string)-1) as My_String
and you're done. (If NULL, you will get NULL returned. Also, this will return all data based on the FIRST dash found in the string, regardless of however many dashes are in the string.)

Remove characters before and after string SQL

I would like to remove all characters before and after a string in the select statement.
In the example below I would like to remove everything before and including /Supply> and after and including >/
Note the remaining part will be a fixed number of characters.
Any help would be much appreciated
Eg.
abs/Supply>hhfhjgglldppprrr>/llllllldsfsjhfhhhfdhudfhfhdhdfhfsd
Would become:
hhfhjgglldppprrr
If your input always has exactly two instances of ">" you could use PARSENAME.
declare #SomeValue varchar(100) = 'abs/Supply>hhfhjgglldppprrr>/llllllldsfsjhfhhhfdhudfhfhdhdfhfsd'
select PARSENAME(replace(#SomeValue, '>', '.'), 2)
This will not work correctly if your data also contains any periods (.). We can deal with that if needed with a couple of replace statements. Still very simple and easy to maintain with the same caveat of exactly 2 >.
declare #SomeOtherValue varchar(100) = 'abs/Supply>hhfhjgg.lldppprrr>/llllllldsfsjhfhhhfdhudfhfhdhdfhfsd'
select replace(PARSENAME(replace(replace(#SomeOtherValue, '.', '~!##'), '>', '.'), 2), '~!##', '.')
You can use PATINDEX() to identify the position of the patterns you are looking for (/Supply> and >/) then remove them based on the length of the string:
SELECT LEFT(RIGHT(col,LEN(col) - PATINDEX('%/Supply>%',col) -7), PATINDEX('%>/%', RIGHT(col,LEN(col) - PATINDEX('%Supply>%',col) -7))-1)
Simply replace col in the above with your column name.
Example below with test string abs/Supply>keep>/remove
First remove everything before and including /Supply>:
SELECT RIGHT('abs/Supply>keep>/remove',LEN('abs/Supply>keep>/remove') - PATINDEX('%/Supply>%','abs/Supply>keep>/remove') -7)
This will give keep>/remove
Then remove everything after and including >/:
SELECT LEFT('keep>/remove',PATINDEX('%>/%','keep>/remove') - 1)
This will give keep, the part of the string you want.
Here is the combined version, same as above, just includes the test string instead of col so you can run it easily:
SELECT LEFT(RIGHT('abs/Supply>keep>/remove',LEN('abs/Supply>keep>/remove') - PATINDEX('%/Supply>%','abs/Supply>keep>/remove') -7), PATINDEX('%>/%', RIGHT('abs/Supply>keep>/remove',LEN('abs/Supply>keep>/remove') - PATINDEX('%/Supply>%','abs/Supply>keep>/remove') -7))-1)
This will give keep. You can also replace the string above with the one in your question, I just used a different test string because it is shorter and makes the code more readable.
try this:
DECLARE #inputStr VARCHAR(max)= 'abs/Supply>hhfhjgglldppprrr>/llllllldsfsjhfhhhfdhudfhfhdhdfhfsd'
DECLARE #startString VARCHAR(100)='/Supply>'
DECLARE #EndString VARCHAR(100)='>/'
DECLARE #LenStartString INT = LEN(#startString)
DECLARe #TempInputString VARCHAR(max)='';
DECLARE #StartIndex INT
DECLARE #EndIndex INT
SELECT #StartIndex = CHARINDEX(#startString,#inputStr)+#LenStartString
SELECT #TempInputString = STUFF(#inputStr, 1, #StartIndex, '')
SELECT SUBSTRING(#TempInputString,0,CHARINDEX(#EndString,#TempInputString))
In Single Line
DECLARE #inputStr VARCHAR(max)= 'abs/Supply>hhfhjgglldppprrr>/llllllldsfsjhfhhhfdhudfhfhdhdfhfsd'
DECLARE #startString VARCHAR(100)='/Supply>'
DECLARE #EndString VARCHAR(100)='>/'
SELECT SUBSTRING(STUFF(#inputStr, 1, CHARINDEX(#startString,#inputStr)+LEN(#startString), ''),0,CHARINDEX(#EndString,STUFF(#inputStr, 1,CHARINDEX(#startString,#inputStr)+LEN(#startString), '')))

Why does replace fail using PATINDEX for certain special characters?

We are trying to strip certain special characters from a string using the (simplified) command below, which is the most common solution we've seen after searching.
But, the results are inconsistent when using certain special characters. Can anyone explain why? And, better, can anyone offer a solution that works?
SQL Server 2014
In the first case below, the '#' is removed, but in all the other cases where it is included (2+5) it is not removed. Same for the 3rd case: the spaces are removed, but not the '&'; and in the 5th case, the spaces are removed, but not the '#'. Other combinations have similar issues.
Thanks.
declare #str varchar(50) = '1st Ave # 1st St FL-3 Rm 323& New York NY'
declare #Pindex1 varchar(10) = '%[#]%'
declare #Pindex2 varchar(10) = '%[#& ]%'
declare #Pindex3 varchar(10) = '%[& ]%'
declare #Pindex4 varchar(10) = '%[ ]%'
declare #Pindex5 varchar(10) = '%[# ]%'
Select #str as String, #Pindex1 as Pattern ,Replace(#str, Substring(#str, PatIndex(#Pindex1,#str), 1), '') as PIndex1_result
Select #str as String, #Pindex2 as Pattern ,Replace(#str, Substring(#str, PatIndex(#Pindex2,#str), 1), '') as PIndex2_result
Select #str as String, #Pindex3 as Pattern ,Replace(#str, Substring(#str, PatIndex(#pindex3,#str), 1), '') as PIndex3_result
Select #str as String, #Pindex4 as Pattern ,Replace(#str, Substring(#str, PatIndex(#Pindex4,#str), 1), '') as PIndex4_result
Select #str as String, #Pindex5 as Pattern,Replace(#str, Substring(#str, PatIndex(#pindex5,#str), 1), '') as PIndex5_result
I think you might have a misunderstanding of SQL Servers patterns. Consider the second pattern:
declare #Pindex2 varchar(10) = '%[#- ]%'
This can match no pattern. Why? The ASCII value of '#' is 64 and for a space it is 32. Nothing occurs between these values. It is similar to '%[b-a]%', which would also match nothing.
I think the issue is your understanding of SQL Server string patterns.

SQL Replace all characters in a string

Is there any SQL statements to replace everything in a string with an 'X'. The strings aren't all the same length so it makes it a bit tricky. I haven't been able to find anything that does this except the function below but it takes a long time when I pass in 'a-z0-9' since I have to search on all of those but I really just want to replace everything no matter what it is.
[dbo].[cfn_StripCharacters]
(
#String NVARCHAR(MAX),
#MatchExpression VARCHAR(255)='a-z0-9'
)
RETURNS NVARCHAR(MAX)
AS
BEGIN
SET #MatchExpression = '%['+#MatchExpression+']%'
WHILE PatIndex(#MatchExpression, #String) > 0
SET #String = Stuff(#String, PatIndex(#MatchExpression, #String), 1, 'X')
RETURN #String
For example the data column looks like this and I want to replace the whole string with x's:
975g -> XXXX
ryth5 -> XXXXX
1234vvsdf5 -> XXXXXXXXXX
test1234 -> XXXXXXXX
If this is SQL Server, you can use the REPLICATE function and simply replicate x the LEN() of the string.
SELECT REPLICATE('x', LEN(#String))
sqlFiddle
Edit - Looks like this is also available in MySQL via REPEAT() but I haven't tested
You can use Replicate and Len functions to replace all characters.
declare #str varchar(20)
set #str = 'abc'
select #str = REPLICATE('X', len(#str))
select #str
There are no built in functions to do it. You can write a CLR function that does a regex replace, though.

T-SQL SUBSTRING at certain places

I have the following example.
DECLARE #String varchar(100) = 'GAME_20131011_Set - SET_20131012_Game'
SELECT SUBSTRING(#String,0,CHARINDEX('_',#String))
SELECT SUBSTRING(#String,CHARINDEX('- ',#STRING),CHARINDEX('_',#STRING))
I want to get the words 'GAME' and 'SET' (the first word before the first '_' from both sides of ' - '.
I am getting 'GAME' but having trouble with 'SET'
UPDATE: 'GAME' and 'SET' are just examples, those words may vary.
DECLARE #String1 varchar(100) = 'GAMEE_20131011_Set - SET_20131012_Game' -- Looking for 'GAME' and 'SET'
DECLARE #String2 varchar(100) = 'GAMEE_20131011_Set - SETT_20131012_Game' -- Looking for 'GAMEE' and 'SETT'
DECLARE #String2 varchar(100) = 'GAMEEEEE_20131011_Set - SETTEEEEEEEE_20131012_Game' -- Looking for 'GAMEEEEE' and 'SETTEEEEEEEE'
As long as your two parts will always be separated be a specific character (- in your example), you could try splitting on that value:
DECLARE #String varchar(100) = 'GAME_20131011_Set - SET_20131012_Game'
DECLARE #Left varchar(100),
#Right varchar(100)
-- split into two strings based on a delimeter
SELECT #Left = RTRIM(SUBSTRING(#String, 0, CHARINDEX('-',#String)))
SELECT #Right = LTRIM(SUBSTRING(#String, CHARINDEX('-',#String)+1, LEN(#String)))
-- handle the strings individually
SELECT SUBSTRING(#Left, 0, CHARINDEX('_', #Left))
SELECT SUBSTRING(#Right, 0, CHARINDEX('_', #Right))
-- Outputs:
-- GAME
-- SET
Here's a SQLFiddle example of this: http://sqlfiddle.com/#!3/d41d8/22594
The issue that you are running into with your original query is that you are specifying CHARINDEX('- ', #String) for your start index, which will include - in any substring starting at that point. Also, with CHARINDEX('_',#STRING) for your length parameter, you will always end up with the index of the first _ character in the string.
By splitting the original string in two, you avoid these problems.
Try this
SELECT SUBSTRING(#String,0,CHARINDEX('_',#String))
SELECT SUBSTRING(#String,CHARINDEX('- ',#STRING)+1, CHARINDEX('_',#STRING)-1)
charindex takes an optional third parameter that says which poistion in the string to start the search from. You could roll this into one statement, but it's easier to read with three
Declare #start int = charindex('-', #string) + 2;
Declare #end int = charindex('_', #string, #start);
Select substring(#string, #start, #end - #start);
Example SQLFiddle