T-SQL SUBSTRING at certain places - sql

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

Related

How to identify and redact all instances of a matching pattern in T-SQL

I have a requirement to run a function over certain fields to identify and redact any numbers which are 5 digits or longer, ensuring all but the last 4 digits are replaced with *
For example: "Some text with 12345 and 1234 and 12345678" would become "Some text with *2345 and 1234 and ****5678"
I've used PATINDEX to identify the the starting character of the pattern:
PATINDEX('%[0-9][0-9][0-9][0-9][0-9]%', TEST_TEXT)
I can recursively call that to get the starting character of all the occurrences, but I'm struggling with the actual redaction.
Does anyone have any pointers on how this can be done? I know to use REPLACE to insert the *s where they need to be, it's just the identification of what I should actually be replacing I'm struggling with.
Could do it on a program, but I need it to be T-SQL (can be a function if needed).
Any tips greatly appreciated!
You can do this using the built in functions of SQL Server. All of which used in this example are present in SQL Server 2008 and higher.
DECLARE #String VARCHAR(500) = 'Example Input: 1234567890, 1234, 12345, 123456, 1234567, 123asd456'
DECLARE #StartPos INT = 1, #EndPos INT = 1;
DECLARE #Input VARCHAR(500) = ISNULL(#String, '') + ' '; --Sets input field and adds a control character at the end to make the loop easier.
DECLARE #OutputString VARCHAR(500) = ''; --Initalize an empty string to avoid string null errors
WHILE (#StartPOS <> 0)
BEGIN
SET #StartPOS = PATINDEX('%[0-9][0-9][0-9][0-9][0-9]%', #Input);
IF #StartPOS <> 0
BEGIN
SET #OutputString += SUBSTRING(#Input, 1, #StartPOS - 1); --Seperate all contents before the first occurance of our filter
SET #Input = SUBSTRING(#Input, #StartPOS, 500); --Cut the entire string to the end. Last value must be greater than the original string length to simply cut it all.
SET #EndPos = (PATINDEX('%[0-9][0-9][0-9][0-9][^0-9]%', #Input)); --First occurance of 4 numbers with a not number behind it.
SET #Input = STUFF(#Input, 1, (#EndPos - 1), REPLICATE('*', (#EndPos - 1))); --#EndPos - 1 gives us the amount of chars we want to replace.
END
END
SET #OutputString += #Input; --Append the last element
SET #OutputString = LEFT(#OutputString, LEN(#OutputString))
SELECT #OutputString;
Which outputs the following:
Example Input: ******7890, 1234, *2345, **3456, ***4567, 123asd456
This entire code could also be made as a function since it only requires an input text.
A dirty solution with recursive CTE
DECLARE
#tags nvarchar(max) = N'Some text with 12345 and 1234 and 12345678',
#c nchar(1) = N' ';
;
WITH Process (s, i)
as
(
SELECT #tags, PATINDEX('%[0-9][0-9][0-9][0-9][0-9]%', #tags)
UNION ALL
SELECT value, PATINDEX('%[0-9][0-9][0-9][0-9][0-9]%', value)
FROM
(SELECT SUBSTRING(s,0,i)+'*'+SUBSTRING(s,i+4,len(s)) value
FROM Process
WHERE i >0) calc
-- we surround the value and the string with leading/trailing ,
-- so that cloth isn't a false positive for clothing
)
SELECT * FROM Process
WHERE i=0
I think a better solution it's to add clr function in Ms SQL Server to manage regexp.
sql-clr/RegEx
Here is an option using the DelimitedSplit8K_LEAD which can be found here. https://www.sqlservercentral.com/articles/reaping-the-benefits-of-the-window-functions-in-t-sql-2 This is an extension of Jeff Moden's splitter that is even a little bit faster than the original. The big advantage this splitter has over most of the others is that it returns the ordinal position of each element. One caveat to this is that I am using a space to split on based on your sample data. If you had numbers crammed in the middle of other characters this will ignore them. That may be good or bad depending on you specific requirements.
declare #Something varchar(100) = 'Some text with 12345 and 1234 and 12345678';
with MyCTE as
(
select x.ItemNumber
, Result = isnull(case when TRY_CONVERT(bigint, x.Item) is not null then isnull(replicate('*', len(convert(varchar(20), TRY_CONVERT(bigint, x.Item))) - 4), '') + right(convert(varchar(20), TRY_CONVERT(bigint, x.Item)), 4) end, x.Item)
from dbo.DelimitedSplit8K_LEAD(#Something, ' ') x
)
select Output = stuff((select ' ' + Result
from MyCTE
order by ItemNumber
FOR XML PATH('')), 1, 1, '')
This produces: Some text with *2345 and 1234 and ****5678

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), '')))

Extract number between two substrings in sql

I had a previous question and it got me started but now I'm needing help completing this. Previous question = How to search a string and return only numeric value?
Basically I have a table with one of the columns containing a very long XML string. There's a number I want to extract near the end. A sample of the number would be this...
<SendDocument DocumentID="1234567">true</SendDocument>
So I want to use substrings to find the first part = true so that Im only left with the number.
What Ive tried so far is this:
SELECT SUBSTRING(xml_column, CHARINDEX('>true</SendDocument>', xml_column) - CHARINDEX('<SendDocument',xml_column) +10087,9)
The above gives me the results but its far from being correct. My concern is that, what if the number grows from 7 digits to 8 digits, or 9 or 10?
In the previous question I was helped with this:
SELECT SUBSTRING(cip_msg, CHARINDEX('<SendDocument',cip_msg)+26,7)
and thats how I got started but I wanted to alter so that I could subtract the last portion and just be left with the numbers.
So again, first part of the string that contains the digits, find the two substrings around the digits and remove them and retrieve just the digits no matter the length.
Thank you all
You should be able to setup your SUBSTRING() so that both the starting and ending positions are variable. That way the length of the number itself doesn't matter.
From the sound of it, the starting position you want is right After the "true"
The starting position would be:
CHARINDEX('<SendDocument DocumentID=', xml_column) + 25
((adding 25 because I think CHARINDEX gives you the position at the beginning of the string you are searching for))
Length would be:
CHARINDEX('>true</SendDocument>',xml_column) - CHARINDEX('<SendDocument DocumentID=', xml_column)+25
((Position of the ending text minus the position of the start text))
So, how about something along the lines of:
SELECT SUBSTRING(xml_column, CHARINDEX('<SendDocument DocumentID=', xml_column)+25,(CHARINDEX('>true</SendDocument>',xml_column) - CHARINDEX('<SendDocument DocumentID=', xml_column)+25))
Have you tried working directly with the xml type? Like below:
DECLARE #TempXmlTable TABLE
(XmlElement xml )
INSERT INTO #TempXmlTable
select Convert(xml,'<SendDocument DocumentID="1234567">true</SendDocument>')
SELECT
element.value('./#DocumentID', 'varchar(50)') as DocumentID
FROM
#TempXmlTable CROSS APPLY
XmlElement.nodes('//.') AS DocumentID(element)
WHERE element.value('./#DocumentID', 'varchar(50)') is not null
If you just want to work with this as a string you can do the following:
DECLARE #SearchString varchar(max) = '<SendDocument DocumentID="1234567">true</SendDocument>'
DECLARE #Start int = (select CHARINDEX('DocumentID="',#SearchString)) + 12 -- 12 Character search pattern
DECLARE #End int = (select CHARINDEX('">', #SearchString)) - #Start --Find End Characters and subtract start position
SELECT SUBSTRING(#SearchString,#Start,#End)
Below is the extended version of parsing an XML document string. In the example below, I create a copy of a PLSQL function called INSTR, the MS SQL database does not have this by default. The function will allow me to search strings at a designated starting position. In addition, I'm parsing a sample XML string into a variable temp table into lines and only looking at lines that match my search criteria. This is because there may be many elements with the words DocumentID and I'll want to find all of them. See below:
IF EXISTS (select * from sys.objects where name = 'INSTR' and type = 'FN')
DROP FUNCTION [dbo].[INSTR]
GO
CREATE FUNCTION [dbo].[INSTR] (#String VARCHAR(8000), #SearchStr VARCHAR(255), #Start INT, #Occurrence INT)
RETURNS INT
AS
BEGIN
DECLARE #Found INT = #Occurrence,
#Position INT = #Start;
WHILE 1=1
BEGIN
-- Find the next occurrence
SET #Position = CHARINDEX(#SearchStr, #String, #Position);
-- Nothing found
IF #Position IS NULL OR #Position = 0
RETURN #Position;
-- The required occurrence found
IF #Found = 1
BREAK;
-- Prepare to find another one occurrence
SET #Found = #Found - 1;
SET #Position = #Position + 1;
END
RETURN #Position;
END
GO
--Assuming well formated xml
DECLARE #XmlStringDocument varchar(max) = '<SomeTag Attrib1="5">
<SendDocument DocumentID="1234567">true</SendDocument>
<SendDocument DocumentID="1234568">true</SendDocument>
</SomeTag>'
--Split Lines on this element tag
DECLARE #SplitOn nvarchar(25) = '</SendDocument>'
--Let's hold all lines in Temp variable table
DECLARE #XmlStringLines TABLE
(
Value nvarchar(100)
)
While (Charindex(#SplitOn,#XmlStringDocument)>0)
Begin
Insert Into #XmlStringLines (value)
Select
Value = ltrim(rtrim(Substring(#XmlStringDocument,1,Charindex(#SplitOn,#XmlStringDocument)-1)))
Set #XmlStringDocument = Substring(#XmlStringDocument,Charindex(#SplitOn,#XmlStringDocument)+len(#SplitOn),len(#XmlStringDocument))
End
Insert Into #XmlStringLines (Value)
Select Value = ltrim(rtrim(#XmlStringDocument))
--Now we have a table with multple lines find all Document IDs
SELECT
StartPosition = CHARINDEX('DocumentID="',Value) + 12,
--Now lets use the INSTR function to find the first instance of '">' after our search string
EndPosition = dbo.INSTR(Value,'">',( CHARINDEX('DocumentID="',Value)) + 12,1),
--Now that we know the start and end lets use substring
Value = SUBSTRING(value,(
-- Start Position
CHARINDEX('DocumentID="',Value)) + 12,
--End Position Minus Start Position
dbo.INSTR(Value,'">',( CHARINDEX('DocumentID="',Value)) + 12,1) - (CHARINDEX('DocumentID="',Value) + 12))
FROM
#XmlStringLines
WHERE Value like '%DocumentID%' --Only care about lines with a document id

A SQL Query to select a string between two known strings

I need a SQL query to get the value between two known strings (the returned value should start and end with these two strings).
An example.
"All I knew was that the dog had been very bad and required harsh punishment immediately regardless of what anyone else thought."
In this case the known strings are "the dog" and "immediately". So my query should return "the dog had been very bad and required harsh punishment immediately"
I've come up with this so far but to no avail:
SELECT SUBSTRING(#Text, CHARINDEX('the dog', #Text), CHARINDEX('immediately', #Text))
#Text being the variable containing the main string.
Can someone please help me with where I'm going wrong?
The problem is that the second part of your substring argument is including the first index.
You need to subtract the first index from your second index to make this work.
SELECT SUBSTRING(#Text, CHARINDEX('the dog', #Text)
, CHARINDEX('immediately',#text) - CHARINDEX('the dog', #Text) + Len('immediately'))
I think what Evan meant was this:
SELECT SUBSTRING(#Text, CHARINDEX(#First, #Text) + LEN(#First),
CHARINDEX(#Second, #Text) - CHARINDEX(#First, #Text) - LEN(#First))
An example is this: You have a string and the character $
String :
aaaaa$bbbbb$ccccc
Code:
SELECT SUBSTRING('aaaaa$bbbbb$ccccc',CHARINDEX('$','aaaaa$bbbbb$ccccc')+1, CHARINDEX('$','aaaaa$bbbbb$ccccc',CHARINDEX('$','aaaaa$bbbbb$ccccc')+1) -CHARINDEX('$','aaaaa$bbbbb$ccccc')-1) as My_String
Output:
bbbbb
You need to adjust for the LENGTH in the SUBSTRING. You were pointing it to the END of the 'ending string'.
Try something like this:
declare #TEXT varchar(200)
declare #ST varchar(200)
declare #EN varchar(200)
set #ST = 'the dog'
set #EN = 'immediately'
set #TEXT = 'All I knew was that the dog had been very bad and required harsh punishment immediately regardless of what anyone else thought.'
SELECT SUBSTRING(#Text, CHARINDEX(#ST, #Text), (CHARINDEX(#EN, #Text)+LEN(#EN))-CHARINDEX(#ST, #Text))
Of course, you may need to adjust it a bit.
I had a similar need to parse out a set of parameters stored within an IIS logs' csUriQuery field, which looked like this: id=3598308&user=AD\user&parameter=1&listing=No needed in this format.
I ended up creating a User-defined function to accomplish a string between, with the following assumptions:
If the starting occurrence is not found, a NULL is returned, and
If the ending occurrence is not found, the rest of the string is returned
Here's the code:
CREATE FUNCTION dbo.str_between(#col varchar(max), #start varchar(50), #end varchar(50))
RETURNS varchar(max)
WITH EXECUTE AS CALLER
AS
BEGIN
RETURN substring(#col, charindex(#start, #col) + len(#start),
isnull(nullif(charindex(#end, stuff(#col, 1, charindex(#start, #col)-1, '')),0),
len(stuff(#col, 1, charindex(#start, #col)-1, ''))+1) - len(#start)-1);
END;
GO
For the above question, the usage is as follows:
DECLARE #a VARCHAR(MAX) = 'All I knew was that the dog had been very bad and required harsh punishment immediately regardless of what anyone else thought.'
SELECT dbo.str_between(#a, 'the dog', 'immediately')
-- Yields' had been very bad and required harsh punishment '
Try this and replace '[' & ']' with your string
SELECT SUBSTRING(#TEXT,CHARINDEX('[',#TEXT)+1,(CHARINDEX(']',#TEXT)-CHARINDEX('[',#TEXT))-1)
I have a feeling you might need SQL Server's PATINDEX() function. Check this out:
Usage on Patindex() function
So maybe:
SELECT SUBSTRING(#TEXT, PATINDEX('%the dog%', #TEXT), PATINDEX('%immediately%',#TEXT))
SELECT
SUBSTRING( '123#yahoo.com', charindex('#','123#yahoo.com',1) + 1, charindex('.','123#yahoo.com',1) - charindex('#','123#yahoo.com',1) - 1 )
DECLARE #Text VARCHAR(MAX), #First VARCHAR(MAX), #Second VARCHAR(MAX)
SET #Text = 'All I knew was that the dog had been very bad and required harsh punishment immediately regardless of what anyone else thought.'
SET #First = 'the dog'
SET #Second = 'immediately'
SELECT SUBSTRING(#Text, CHARINDEX(#First, #Text),
CHARINDEX(#Second, #Text) - CHARINDEX(#First, #Text) + LEN(#Second))
You're getting the starting position of 'punishment immediately', but passing that in as the length parameter for your substring.
You would need to substract the starting position of 'the dog' from the charindex of 'punishment immediately', and then add the length of the 'punishment immediately' string to your third parameter. This would then give you the correct text.
Here's some rough, hacky code to illustrate the process:
DECLARE #text VARCHAR(MAX)
SET #text = 'All I knew was that the dog had been very bad and required harsh punishment immediately regardless of what anyone else thought.'
DECLARE #start INT
SELECT #start = CHARINDEX('the dog',#text)
DECLARE #endLen INT
SELECT #endLen = LEN('immediately')
DECLARE #end INT
SELECT #end = CHARINDEX('immediately',#text)
SET #end = #end - #start + #endLen
SELECT #end
SELECT SUBSTRING(#text,#start,#end)
Result: the dog had been very bad and required harsh punishment immediately
Among the many options is to create a simple function.
Can keep your code cleaner.
Gives the ability to handle errors if the start or end marker/string is not present.
This function also allows for trimming leading or trailing whitespace as an option.
SELECT dbo.GetStringBetweenMarkers('123456789', '234', '78', 0, 1)
Yields:
56
--Code to create the function
USE [xxxx_YourDB_xxxx]
GO
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE FUNCTION [dbo].[GetStringBetweenMarkers] (#FullString varchar(max), #StartMarker varchar(500), #EndMarker varchar(500), #TrimLRWhiteSpace bit, #ReportErrorInResult bit)
RETURNS varchar(max)
AS
BEGIN
--Purpose is to simply return the string between 2 string markers. ew 2022-11-06
--Will perform a LTRIM and RTRIM if #TrimLRWhiteSpace = 1
--Will report errors of either marker not being found in the RETURNed string if #ReportErrorInResult = 1.
-- When #ReportErrorInResult = 0, if the start marker isn't found, will return everything from the start of the #FullString to the left of the end marker.
-- When #ReportErrorInResult = 0, if the end marker isn't found, SQL will return an error of "Invalid length parameter passed to the LEFT or SUBSTRING function."
DECLARE #ReturnString VARCHAR(max) = ''
DECLARE #StartOfStartMarker INT = CHARINDEX(#StartMarker, #FullString)
DECLARE #StartOfTarget INT = CHARINDEX(#StartMarker, #FullString) + LEN(#StartMarker)
DECLARE #EndOfTarget INT = CHARINDEX(#EndMarker, #FullString, #StartOfTarget)
--If a marker wasn't found, put that into the
IF #ReportErrorInResult = 1
BEGIN
IF #EndOfTarget = 0 SET #ReturnString = '[ERROR: EndMarker not found.]'
IF #StartOfStartMarker = 0 SET #ReturnString = '[ERROR: StartMarker not found.]'
IF #StartOfStartMarker = 0 AND #EndOfTarget = 0 SET #ReturnString = '[ERROR: Both StartMarker and EndMarker not found.]'
END
--If not reporting errors, and start marker not found (i.e. CHARINDEX = 0) we would start our string at the LEN(#StartMarker).
-- This would give an odd result. Best to just provide from 0, i.e. the start of the #FullString.
IF #ReportErrorInResult = 0 AND #StartOfStartMarker = 0 SET #StartOfTarget = 0
--Main action
IF #ReturnString = '' SET #ReturnString = SUBSTRING(#FullString, #StartOfTarget, #EndOfTarget - #StartOfTarget)
IF #TrimLRWhiteSpace = 1 SET #ReturnString = LTRIM(RTRIM(#ReturnString))
RETURN #ReturnString
--Examples
-- SELECT '>' + dbo.GetStringBetweenMarkers('123456789','234','78',0,1) + '<' AS 'Result-Returns what is in between markers w/ white space'
-- SELECT '>' + dbo.GetStringBetweenMarkers('1234 56 789','234','78',0,1) + '<' AS 'Result-Without trimming white space'
-- SELECT '>' + dbo.GetStringBetweenMarkers('1234 56 789','234','78',1,1) + '<' AS 'Result-Will trim white space with a #TrimLRWhiteSpace = 1'
-- SELECT '>' + dbo.GetStringBetweenMarkers('abcdefgh','ABC','FG',0,1) + '<' AS 'Result-Not Case Sensitive'
-- SELECT '>' + dbo.GetStringBetweenMarkers('abc_de_fgh','_','_',0,1) + '<' AS 'Result-Using the same marker for start and end'
--Errors are returned if start or end marker are not found
-- SELECT '>' + dbo.GetStringBetweenMarkers('1234 56789','zz','78',0,1) + '<' AS 'Result-Start not found'
-- SELECT '>' + dbo.GetStringBetweenMarkers('1234 56789','234','zz',0,1) + '<' AS 'Result-End not found'
-- SELECT '>' + dbo.GetStringBetweenMarkers('1234 56789','zz','zz',0,1) + '<' AS 'Result-Niether found'
--If #ReportErrorInResult = 0
-- SELECT '>' + dbo.GetStringBetweenMarkers('123456789','zz','78',0,0) + '<' AS 'Result-Start not found-Returns from the start of the #FullString'
-- SELECT '>' + dbo.GetStringBetweenMarkers('123456789','34','zz',0,0) + '<' AS 'Result-End found-should get "Invalid length parameter passed to the LEFT or SUBSTRING function."'
END
GO
SELECT SUBSTRING('aaaaa$bbbbb$ccccc',instr('aaaaa$bbbbb$ccccc','$',1,1)+1, instr('aaaaa$bbbbb$ccccc','$',1,2)-1) -instr('aaaaa$bbbbb$ccccc','$',1,1)) as My_String
Hope this helps :
Declared a variable , in case of any changes need to be made thats only once .
declare #line varchar(100)
set #line ='Email_i-Julie#mail.com'
select SUBSTRING(#line ,(charindex('-',#line)+1), CHARINDEX('#',#line)-charindex('-',#line)-1)
I needed to get (099) 0000111-> (099) | 0000111 like two different columns.
SELECT
SUBSTRING(Phone, CHARINDEX('(', Phone) + 0, (2 + ((LEN(Phone)) - CHARINDEX(')', REVERSE(Phone))) - CHARINDEX('(', Phone))) AS CodePhone,
LTRIM(SUBSTRING(Phone, CHARINDEX(')', Phone) + 1, LEN(Phone))) AS NumberPhone
FROM
Suppliers
WHERE
Phone LIKE '%(%)%'
DECLARE #text VARCHAR(MAX)
SET #text = 'All I knew was that the dog had been very bad and required harsh punishment immediately regardless of what anyone else thought.'
DECLARE #pretext AS nvarchar(100) = 'the dog'
DECLARE #posttext AS nvarchar(100) = 'immediately'
SELECT
CASE
WHEN CHARINDEX(#posttext, #Text) - (CHARINDEX(#pretext, #Text) + len(#pretext)) < 0
THEN ''
ELSE SUBSTRING(#Text,
CHARINDEX(#pretext, #Text) + LEN(#pretext),
CHARINDEX(#posttext, #Text) - (CHARINDEX(#pretext, #Text) + LEN(#pretext)))
END AS betweentext
I'm a few years behind, but here's what I did to get a string between characters, that are not the same and also in the even you don't find the ending character, to still give you the substring
BEGIN
DECLARE #TEXT AS VARCHAR(20)
SET #TEXT='E101465445454-1'
SELECT SUBSTRING(#TEXT, CHARINDEX('E', #TEXT)+1, CHARINDEX('-',#TEXT)) as 'STR',
CAST(CHARINDEX('E', #TEXT)+1 AS INT) as 'val1', CAST(CHARINDEX('-', #TEXT) AS INT) as 'val2',
(CAST(CHARINDEX('-',#TEXT) AS INT) - CAST(CHARINDEX('E',#TEXT)+1 AS INT)) as 'SUBTR', LEN(#TEXT) as 'LEN'
SELECT CASE WHEN (CHARINDEX('-', #TEXT) > 0) THEN
SUBSTRING(#TEXT, CHARINDEX('E', #TEXT)+1, (CAST(CHARINDEX('-',#TEXT) AS INT) - CAST(CHARINDEX('E',#TEXT)+1 AS INT)))
ELSE
SUBSTRING(#TEXT, CHARINDEX('E', #TEXT)+1,LEN(#TEXT)- CHARINDEX('E', #TEXT))
END
END
Try it and comment for any improvements or if it does the job
select substring(#string,charindex('#first',#string)+1,charindex('#second',#string)-(charindex('#first',#string)+1))
Let us consider we have a string DUMMY_DATA_CODE_FILE and we want to find out the substring between 2nd and 3rd underscore(_). Then we use query something like this.
select SUBSTRING('DUMMY_DATA_CODE_FILE',charindex('_', 'DUMMY_DATA_CODE_FILE', (charindex('_','DUMMY_DATA_CODE_FILE', 1))+1)+1, (charindex('_', 'DUMMY_DATA_CODE_FILE', (charindex('_','DUMMY_DATA_CODE_FILE', (charindex('_','DUMMY_DATA_CODE_FILE', 1))+1))+1)- charindex('_', 'DUMMY_DATA_CODE_FILE', (charindex('_','DUMMY_DATA_CODE_FILE', 1))+1)-1)) as Code

T-SQL Find char string and take all char to right of expression

How do I
Take:
RJI#\\\\Cjserver\TrialWorks\CaseFiles\10000269\Pleadings\RJI - 10005781.doc
Find Constant expression '\\Cjserver\' and take everything to the right of the expression so the correct pointer would be:
\\\\Cjserver\TrialWorks\CaseFiles\10000269\Pleadings\RJI - 10005781.doc
I know some kind of combinaton of RIGHT and CHARINDEX should do it.
DECLARE #input NVarChar(1000) =
'RJI#\\Cjserver\TrialWorks\CaseFiles\10000269\Pleadings\RJI - 10005781.doc',
#match NVarChar(100) =
'\\Cjserver';
DECLARE #position Int = CHARINDEX(#match, #input);
SELECT SUBSTRING(#input, #position, 1000);
I'm just using 1000 for some arbitrarily large value. You should probably size this more appropriately to your data.
You want to use Substring, starting one after the index of your target, and take the length of the entire string less the charindex of your target
declare #string varchar(1000)
set #string = 'xxxxxxxxyzzzzzzzz'
select substring(#string, charindex('y', #string) +1,
len(#string) - charindex('y', #string))
zzzzzzzz
In this case I want everything after the y
DECLARE #String VARCHAR(100)
SET #String = 'RJI#\\Cjserver\TrialWorks\CaseFiles\10000269\Pleadings\RJI - 10005781.doc'
SELECT RIGHT(#String,LEN(#String)-PATINDEX('%\\Cjserver\%',#String)+1)