Find length of the string between two given special character - sql

Is there any simplest way to find length of the string between two given special charcter.
Something like this :
select string from table1 where len(string) between '-' and ','
for example : 341267-8763,68978
The query should return 4 (that is the length of 8763)

SELECT CHARINDEX(',', '341267-8763,68978') - CHARINDEX('-', '341267-8763,68978') - 1
4

Use CHARINDEX() function
select string, CHARINDEX(',', string) - CHARINDEX('-', string) Lengths
from table t

Please use CHARINDEX(MatchCharacter,SourceString)
DECLARE #string VARCHAR(2000),
#startChar VARCHAR,
#EndChar VARCHAR
SET #string = 'It is a established #fact that #a reader'
SET #startChar = '#'
SET #EndChar = '#'
SELECT #string Source, CHARINDEX(#EndChar, #string) - CHARINDEX(#startChar, #string) - 1 LENGTH
Result
Source LENGTH
------------------------------------------- -----------
It is a established #fact that# a reader 10

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.)

Regex for a single space then numbers

I am using this an an sql query to return just the first numbers out of a string and nothing else. I need it to do that for the first match that starts with a space.
so
hello world56 12345
would return only 12345
right now I get the 56
SUBSTRING(s.Description, PATINDEX('%[0-9]%',s.Description), PATINDEX('%[^0-9]%',SUBSTRING(s.Description, PATINDEX('%[0-9]%',s.Description), LEN(s.Description)))-1);
--test
DECLARE #Str nvarchar(1000)
SET #Str = 'ANDERSON, LEILANI M - MEDICAL ONCOLOGY 40225 (DFCI)'
SELECT SUBSTRING(#str,
PATINDEX(' %[0-9]%',#str)+1,
PATINDEX('%[^0-9]%',
SUBSTRING(#str,
PATINDEX(' %[0-9]%',#str)+1,
LEN(#str)))-1);
Put a space at the beginning of the pattern, and then add 1 to the index that it returns to get the position of the digit after the space.
SUBSTRING(s.Description,
PATINDEX('% [0-9]%',s.Description)+1,
PATINDEX('%[^0-9]%',
SUBSTRING(s.Description,
PATINDEX('% [0-9]%',s.Description)+1,
LEN(s.Description))
+ ' ')-1);
I append a space in the second PATINDEX() call so that it will work correctly if the number is at the end of the string.
DEMO
You may use the following select statement with substring, charindex, and patindex :
select substring(q.str, charindex(' ',q.str)+1,len(q.str)) as "Result"
from
(
select substring(Description,patindex('%[0-9]%',Description),len(Description)) str
from tab
) q;
Result
------
12345
Rextester Demo

TrimEnd Equivalent in SQL Server

I have column (Numbers) which has values as follows:
1,2,3
1,2,3,
1,2,3,,,
1,2,3,,,,,,
I want to Trim all the Commas at the end of string, So that result would be
1,2,3
1,2,3
1,2,3
1,2,3
I have tried below Query but by this we can remove only one last comma
DECLARE #String as VARCHAR(50)
SET #String='1,2,3,4,,,,,,,,,,,,,,,,'
SELECT CASE WHEN right(rtrim(#String),1) = ',' then substring(rtrim(#String),1,len(rtrim(#String))-1)
ELSE #String
END AS TruncString
How can I remove all the commas at the end of string?
You can do this using:
LEFT(Numbers, LEN(Numbers) - (PATINDEX('%[^,]%', REVERSE(Numbers)) - 1))
The premise of this is you first reverse the string using REVERSE:
REVERSE(Numbers) --> ,,,,,,3,2,1
You then find the position of the first character that is not a comma using PATINDEX and the pattern match [^,]:
PATINDEX('%[^,]%', REVERSE(Numbers)) --> ,,,,,,3,2,1 = 7
Then you can use the length of the string using LEN, to get the inverse position, i.e. if the position of the first character that is not a comma is 7 in the reversed string, and the length of the string is 10, then you need the first 4 characters of the string. You then use SUBSTRING to extract the relevant part
A full example would be
SELECT Numbers,
Reversed = REVERSE(Numbers),
Position = PATINDEX('%[^,]%', REVERSE(Numbers)),
TrimEnd = LEFT(Numbers, LEN(Numbers) - (PATINDEX('%[^,]%', REVERSE(Numbers)) - 1))
FROM (VALUES
('1,2,3'),
('1,2,3,'),
('1,2,3,,,'),
('1,2,3,,,,,,'),
('1,2,3,,,5,,,'),
(',,1,2,3,,,5,,')
) t (Numbers);
EDIT
In response to an edit, that had some errors in the syntax, the below has functions to trim the start, and trim both sides of commas:
SELECT Numbers,
Reversed = REVERSE(Numbers),
Position = PATINDEX('%[^,]%', REVERSE(Numbers)),
TrimEnd = LEFT(Numbers, LEN(Numbers) - (PATINDEX('%[^,]%', REVERSE(Numbers)) - 1)),
TrimStart = SUBSTRING(Numbers, PATINDEX('%[^,]%', Numbers), LEN(Numbers)),
TrimBothSide = SUBSTRING(Numbers,
PATINDEX('%[^,]%', Numbers),
LEN(Numbers) -
(PATINDEX('%[^,]%', REVERSE(Numbers)) - 1) -
(PATINDEX('%[^,]%', Numbers) - 1)
)
FROM (VALUES
('1,2,3'),
('1,2,3,'),
('1,2,3,,,'),
('1,2,3,,,,,,'),
('1,2,3,,,5,,,'),
(',,1,2,3,,,5,,')
) t (Numbers);
Because there are multiple occurrences you can't do it with a simple builtin function expression, but a simple user defined function can do the job.
create function dbo.MyTrim(#text varchar(max)) returns varchar(max)
as
-- function to remove all commas from the right end of the input.
begin
while (right(#text, 1) = ','
begin
set #text = left(#text, len(#text) - 1)
end
return #text
end
go
You can search for the first occurrence of ',,' and take everything before that:
select (case when numbers like '%,,'
then left(numbers, charindex(',,', numbers) - 1)
when numbers like '%,'
then left(numbers, len(numbers) - 1)
else numbers
end)
Note: it would seem that you are storing lists of things in a comma-delimited string. It is usually better to store these using a junction table.
EDIT:
Or, an alternative way of formulating this without the case:
select left(numbers + ',,', charindex(',,', numbers + ',,') - 1)
SQL Server 2017 has implemented an enhanced version of TRIM function.
You can use TRIM(',' FROM '1,2,3,,,') to get the string, '1,2,3'
Run below query and get expected results
declare #sql varchar(500)
set #sql ='1,2,3,,,,,,'
select left(#sql,case charindex(',,',#sql,0)
when 0 then len(#sql)-1
else charindex(',,',#sql,0)-1
end)
Create FUNCTION TrimStartEndAll
(
#string varchar(max),
#trimValue varchar(5),
#removeall int=0
)
RETURNS varchar(max)
AS
BEGIN
if #removeall=1
while CHARINDEX(#trimValue,#string) >0 and #removeall=1
begin
set #string = REPLACE(#string,#trimValue,'')
end
if #removeall = 0
begin
while CHARINDEX(#trimValue,#string) =1
begin
set #string = SUBSTRING(#string,len(#trimValue)+1, len(#string))
end
while substring(#string,len(#string)-len(#trimValue)+1, len(#trimValue)) = #trimValue
begin
set #string =substring(#string,0, (len(#string)-len(#trimValue)+1))
end
end
return #string
END
GO
output
select dbo.TrimStartEndAll( ',,1,2,3,,,5,,,,,,,,,',',,',1) => 1,2,3,5,
select dbo.TrimStartEndAll( ',,1,2,3,,,5,,,,,,,,,',',,',0) => 1,2,3,,,5,

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

Replace null character in a string in sql

I need to replace a null character in a sql string, i cant seem to find the right command to achieve this. I have used replace (myString ,'\0', '') but this seems not to work, any help would be great
The trick that works is to COLLATE your value to Latin1_General_BIN before using REPLACE and also use nchar(0x00) COLLATE Latin1_General_BIN for string_pattern.
REPLACE ( string_expression , string_pattern , string_replacement )
select
[Terminated] = N'123' + nchar(0) + N'567'
,[Replaced with -] = REPLACE((N'123' + nchar(0) + N'567') COLLATE Latin1_General_BIN
, nchar(0x00) COLLATE Latin1_General_BIN
,'-')
,[Removed] = REPLACE((N'123' + nchar(0) + N'567') COLLATE Latin1_General_BIN
, nchar(0x00) COLLATE Latin1_General_BIN
,'')
Here is the result (use Output To Text):
Contains Replaced with - Removed
---------- ----------------- --------
123 567 123-567 123567
Use this:
REPLACE(myString, char(0), '')
These functions remove null characters from Unicode strings, at least in SQL Server 2008.
-- Remove all null characters
CREATE FUNCTION RemoveNulls(#s nvarchar(max))
RETURNS nvarchar(max)
AS
BEGIN
DECLARE #r nvarchar(max);
SET #r = REPLACE(#s COLLATE Latin1_General_BIN, NCHAR(0), N'');
RETURN #r;
END
-- Remove all characters from the first null character
CREATE FUNCTION TrimNull(#s nvarchar(max))
RETURNS nvarchar(max)
AS
BEGIN
DECLARE #r nvarchar(max);
DECLARE #i int = CHARINDEX(NCHAR(0), #s COLLATE Latin1_General_BIN);
IF #i = 0
SET #r = #s;
ELSE
SET #r = SUBSTRING(#s, 1, #i - 1);
RETURN #r;
END
-- Example usage
DECLARE #s nvarchar(10) = N'Test' + NCHAR(0) + N'!';
SELECT dbo.RemoveNulls(#s), dbo.TrimNull(#s);
--> Test!, Test
In my case, fields from ODBC were padded to 8000 characters with null and TrimNull was much faster than RemoveNulls.
For latin characters:
select REPLACE('Ho'+CHAR(0)+'mer' COLLATE SQL_Latin1_General_CP1_CS_AS, CHAR(0), '')
For russian characters:
select REPLACE(('Го'+CHAR(0)+'мер') COLLATE Cyrillic_General_BIN , CHAR(0), '')
If you Only have ASCII (Char/VarChar) strings then this will work as #DyingCactus suggests:
REPLACE(myString, Char(0x00), '')
However, if you are dealing with Null-Terminated Strings and are trying to fix or convert to something like XML, and your data is Unicode (nChar/nVarChar), then use this:
(CASE WHEN UNICODE(SUBSTRING(myString, LEN(myString), 1)) = 0x0000
THEN SUBSTRING(myString, 1, LEN(myString) - 1)
ELSE myString END)
This works for both ASCII (Char/VarChar) and Unicode (nChar/nVarChar).
Note
Using the Replace() function with Char(0) or nChar(0) will NOT work for Unicode (nChar/nVarChar).
It's a bug in the SQL Server Replace() function.
You could cast as VarChar, then use Replace(), but then you would lose any special Unicode/Non-ASCII characters you might have intended to keep.
Otherwise you wouldn't have used the Unicode datatype (that takes up twice as much space to store your data) in the first place.
If you have Null-Characters mixed in with your Unicode strings (and not only at the end), and, for the purposes of your query, maintaining Unicode-specific characters are unimportant, then as a last resort you could use this :
(CASE WHEN myString LIKE (N'%' + nCHAR(0x0000) + N'%')--Has Null-Character(s).
THEN REPLACE(CAST(myString as VarChar(MAX)), Char(0x00), '')--Cast as ASCII
ELSE myString END)--Else, leave as Unicode to preserve Unicode-Only chars.
I'm not completely sure what is wrong with your strings, but here are some things to try, are you using varchar?, edit question with more details:
if you have NULL characters within a string:
declare #x varchar(10)
set #x='123'+char(0)+'456'
SELECT #x AS Has_NULL_in_it, REPLACE(#x, char(0), '') AS Has_NULL_removed
OUTPUT:
Has_NULL_in_it Has_NULL_removed
-------------- ----------------
123 456 123456
(1 row(s) affected)
If you can't tell the character within the string, try this ASCII:
DECLARE #y varchar(10),#c int
set #y='123'+char(0)+'456'
set #c=0
WHILE #c<LEN(#y)
BEGIN
SET #c=#c+1
PRINT CONVERT(varchar(5),#c)+' - '+SUBSTRING(#y,#c,1)+' - CHAR('+CONVERT(varchar(5),ASCII(SUBSTRING(#y,#c,1)))+')'
END
OUTPUT:
1 - 1 - CHAR(49)
2 - 2 - CHAR(50)
3 - 3 - CHAR(51)
4 - - CHAR(0)
5 - 4 - CHAR(52)
6 - 5 - CHAR(53)
7 - 6 - CHAR(54)
try this unicode:
DECLARE #y nvarchar(10),#c int
set #y='123'+char(0)+'456'
set #c=0
WHILE #c<LEN(#y)
BEGIN
SET #c=#c+1
PRINT CONVERT(nvarchar(5),#c)+' - '+SUBSTRING(#y,#c,1)+' - UNICODE('+CONVERT(nvarchar(5),UNICODE(SUBSTRING(#y,#c,1)))+')'
END
if your have strings that are completely NULL:
declare #z varchar(10)
set #z=NULL
select #z AS IS_NULL, ISNULL(#Z,'') AS NULL_Removed
OUTPUT:
IS_NULL NULL_Removed
---------- ------------
NULL
(1 row(s) affected)
If you are concatenating values to get your string use IsNull(value, replacement) to avoid having null values or set CONCAT_NULL_YIELDS_NULL ON to avoid null strings as a result.
We had the same problem: Ending \0 character in nvarchar fields and unable to replace it with any of the REPLACE variants proposed (SQL Server 2008). When using
LEFT(Bar, LEN(Bar)-1)
it cut off the last regular character together with the \0 !
Our solution now to correct the fields is (as weird as it may seem on a first glimpse):
UPDATE Foo
SET Bar = LEFT(Bar, LEN(Bar))
WHERE RIGHT(Bar, 1) = CHAR(0)
Examples resolved
CREATE FUNCTION dbo.F_ReplaceNullChar( #STR NVARCHAR(MAX) )
RETURNS NVARCHAR(MAX)
AS
BEGIN
DECLARE #i INT=0
DECLARE #RET NVARCHAR(MAX)=''
WHILE #I<LEN(#STR)
BEGIN
SET #i=#i+1
IF UNICODE(SUBSTRING(#STR,#i,1)) <> 0x0000
SET #RET=#RET+SUBSTRING(#STR,#i,1)
END
RETURN #RET
END
GO
SELECT LEN(mycol) lenbefore,mycol,
LEN( dbo.F_ReplaceNullChar(mycol)) lenafter, dbo.F_ReplaceNullChar(mycol) mycolafter
FROM mytab
select zz.xx
, replace(zz.xx, '', '')
from (
select
t.string_with_null,
(
select s.string_with_null+''
from TABLE_1 s
where s.token_hash = t.token_hash
for xml path('')
) xx
from TABLE_1 t(nolock)
)zz