How to extract text between square brackets in TSQL - sql-server

I have the following query:
DECLARE #value as nvarchar(max)
SET #value = '(company.[department] LIKE ''Development'')';
I would like to extract the word between brackets keep it in a value and then put as input in a replace function like this.
select replace(#value, #department, 'another_string');
You will say probably why I don't do it immediately with the replace function.
The case is that this department string may change dynamically to another string for example country and I would like every time to keep this choice and change it with a value.

You can do this in a query via the base string functions:
SELECT
SUBSTRING(col,
CHARINDEX('[', col) + 1,
CHARINDEX(']', col) - CHARINDEX('[', col) - 1) AS output
FROM yourTable;
Caveats include that you only have one bracketed term, and also that this query form of an answer would be usable in your particular scenario.
Demo

your particular case will idealy works with parsenamefunction:
DECLARE #value as nvarchar(max), #department varchar(100);
SET #value = '(company.[department] LIKE ''Development'')';
SET #department = parsename(replace(replace(#value,'[','.'),']','.'),2)
SELECT replace(#value, #department, 'another_string');
will return:
(company.[another_string] LIKE 'Development')
explanation:
replace brackets with dot '.' and your #value will looks like this:
(company..department. LIKE 'Development')
such pattern is similar with:
Server name.Database name.Schema name.Object name
and you can extract the part of string using parsename function, where: 1 = Object name, 2 = Schema name, 3 = Database name, 4 = Server name
link to function here:
https://learn.microsoft.com/en-us/sql/t-sql/functions/parsename-transact-sql
DEMO

Try like following.
DECLARE #value as nvarchar(max)
SET #value = '(company.[department] LIKE ''Development'')';
declare #department NVARCHAR(100)
SELECT #department = Substring(#value,
Charindex('[', #value) + 1,
Charindex(']', #value) -
Charindex('[', #value) - 1)
select Replace(#value, #department, 'another_string');
Output
(company.[another_string] LIKE 'Development')

Related

SQL Server : select all after specific character

How I can select
"ALT1" if value is "W61N03D20V0-WHIH-ALT1"
"ALT2" if for "W61N03D20V0-WHIH-ALT2"
"SW" for "W61N03D20V0-WHIH-SW"
"Default" for "W61N26D1YA1-VICU" (without prefix)
"Defailt" for "W61N27D21V2-AZTD"
In other words I'm looking for a way extract last part after second suffix, but if I have't second suffix - then default
Thanks for advice
Try it like this:
First you "split" the string on its minus signs with the XML trick.
Then you read the third node from you XML - voila!
CREATE TABLE #tbl(content VARCHAR(100));
INSERT INTO #tbl VALUES('W61N03D20V0-WHIH-ALT1')
,('W61N03D20V0-WHIH-SW')
,('W61N26D1YA1-VICU');
WITH SplittedAsXml AS
(
SELECT CAST('<x>' + REPLACE(content,'-','</x><x>') + '</x>' AS XML) AS Content
FROM #tbl
)
SELECT ISNULL(Content.value('/x[3]','varchar(max)'),'default') AS TheThirdPart
FROM SplittedAsXml;
DROP TABLE #tbl;
The result
ALT1
SW
default
Going this ways would also give you the chance to get the other parts in one go just querying /x[1] and /x[2] too
I did it using the built-in substring() function:
declare #str VARCHAR(40) = 'W61N03D20V0-WHIH-ALT1' -- also works for the other examples
declare #sep VARCHAR(1) = '-'
declare #middleToEnd VARCHAR(40) = substring(#str, charindex(#sep, #str) + 1, len(#str))
declare #pos INT = charindex(#sep, #middleToEnd)
declare #lastPart VARCHAR(40) =
CASE WHEN #pos = 0
THEN 'Default'
ELSE substring(#middleToEnd, #pos + 1, len(#middleToEnd))
END
select #lastPart
For best performance, you can solve it with this one-liner(calculation is one line)
SELECT
COALESCE(STUFF(col,1,NULLIF(CHARINDEX('-',col, CHARINDEX('-',col)+1), 0),''),'Default')
FROM (values
('W61N03D20V0-WHIH-ALT1'),('W61N03D20V0-WHIH-ALT2'),
('W61N03D20V0-WHIH-SW'),('W61N26D1YA1-VICU'),
('W61N27D21V2-AZTD')) x(col)
Result:
ALT1
ALT2
SW
Default
Default
If I understand what you are asking for, the following does what you need:
-- fake table
WITH SomeTable AS (
SELECT 'W61N03D20V0-WHIH-ALT1' AS Field1
UNION ALL
SELECT 'W61N03D20V0-WHIH-SW'
UNION ALL
SELECT 'W61N26D1YA1-VICU'
)
-- select
SELECT
CASE CHARINDEX('-WHIH-', Field1)
WHEN 0 THEN 'Default'
ELSE SUBSTRING(Field1, CHARINDEX('-WHIH-', Field1) + 6, LEN(Field1) - (CHARINDEX('-WHIH-', Field1) + 5))
END
FROM SomeTable
Use can use a CASE expression to check whether the string starts with W61N03D20V0-WHIH.
If it starts with it use a combination of RIGHT, REVERSE and CHARINDEX functions to get last part from the string, else Default.
Query
select case when [your_column_name] like 'W61N03D20V0-WHIH%'
then right([your_column_name], charindex('-', reverse([your_column_name]), 1) - 1)
else 'Default' end as new_column_name
from your_table_name;
SQl Fiddle demo

Extract a number after a number pattern in SQL

I am working in SQL server. I have some number like 130-0029. I need to get the integer after the - delimiter out of it. So in this example I need to return 29. These are the following scenarios I have with this,
The pattern may differ like 130-00000029 or 130-0029.
If there are all 0's then print 0, else get actual number like 29.
Please advise/suggest me on this.
Here is an example:
declare #s varchar(100) = '130-0029'
select cast(substring(#s, patindex('%[-]%', #s) + 1, len(#s)) as int)
You may need to cast to some numeric if the number overflows ineteger type.
Try this:
DECLARE #num varchar(50) = '130-0029'
SELECT CAST(SUBSTRING(#num, CHARINDEX('-', #num) + 1, LEN(#num)) AS INT)
Here is a fiddle.
This also works if the - is missing. But if what follows is not a number it will give an error.
declare #string as varchar(100)
set #string = '130-0029'
select convert(int,Right(#string, LEN(#string)-CHARINDEX('-', #string)))
Probably not so different than other answers, but this works using STUFF too:
DECLARE #String VARCHAR(10) = '130-0029';
SELECT CONVERT(INT, STUFF(#String, 1, CHARINDEX('-', #String), ''));
See this running in Query Stack Exchange.

sql to check string contains with where clause

in Sql server
I have a following string
DECLARE #str nvarchar(max);
set #str = "Hello how are you doing today,Its Monday and 5 waiting days";
DECLARE #srch nvarchar(max);
set #srch = " how,doing,monday,waiting";
Now i want to check whether str contains any of string (comma separated string) of srch
I want it in only sql server
is there possibilites to write some query with in clause
like
select from #str where _____ in (select * from CommaSplit(#srch)
where CommaSplit function rerturns rows of #srch comma separted value
I dont want to use cursor or any loop concept as the #srch value can be very long
Thanks
you can use same function to get first string in rows
select string from CommaSplit(#srch,'') where string in (select * from CommaSplit(#srch)
You can use the following common table expressions query to split your string into parts. cte will contain one record per phrase in #srch. In my example below, I show where in #str each of the search phrase is located. It returns 0 if it cannot locate a search phrase.
Note 1: it won't show the location twice if your search phrase is duplicated - you would need another CTE for that.
Note 2: I have to add comma at the end of #srch to make my CTE work. You can do that inside the CTE if you prefer not to change the search string.
DECLARE #str nvarchar(max);
set #str = 'Hello how are you doing today,Its Monday and 5 waiting days';
DECLARE #srch nvarchar(max);
set #srch = 'how,doing,monday,waiting';
set #srch = #srch + ','
-- first split the text into 1 character per row
;with cte
as
(
select substring(#srch, 1, CHARINDEX(',', #srch, 1) - 1) as Phrase, CHARINDEX(',', #srch, 1) as Idx
union all
select substring(#srch, cte.Idx + 1, CHARINDEX(',', #srch, cte.Idx + 1) - cte.Idx - 1) as Phrase, CHARINDEX(',', #srch, cte.Idx + 1) as Idx
from cte
where cte.Idx < CHARINDEX(',', #srch, cte.Idx + 1)
)
select charindex(cte.Phrase, #str, 1) from cte
I don't think that the IN clause is what you need. Instead of this you can use the LIKE construction as following:
if (select count(*) from CommaSplit(#srch) where #str like '%' + val + '%') > 0
select 'true'
else
select 'false'
In this case you will receive 'true' when at least 1 result of CommaSplit function exists in the #str text. But in this case you also will receive a 'true' value when the result of CommaSplit function is a part of the word in the #str string.
If you need more accurate solution, this can be achieved by the following way: you need to split the #str into the words (also replacing punctuation by spaces beforehand). And, after this, intersect of CommaSplit (#srch) and SpaceSplit(#str) will be the answer on the question. Among this, you also will be able to check which words are matching between two strings.
The overhead of this method is to create function SpaceSplit which is copy of CommaSplit but with another separator. Or the function CommaSplit can be modified to receive a separator as parameter.

Is there an SQL Server function to remove brackets and their contents?

I need to remove all brackets and their contents from multiple records but I can't figure out the best way to do this.
I would like to be able to write something like
SELECT dbo.RemoveBracketedText(ColumnName) FROM TableName;
And it would convert a record such as 'Hello (World)' to just 'Hello '
Any help is appreciated.
Thanks!
My first approach would probably have been to write a quick c# app to do it or use SSIS and write a package to take care of it, but if your determined to use tsql... it will likely require a combination of a recursive function and some string manipulation.
This is minimally tested but should be close. (i.e. it worked on the sample text you provide in your question).
CREATE FUNCTION RemoveBracketedText (#sourceString varchar(max))
RETURNS varchar(max)
AS
BEGIN
DECLARE #pStart Int
DECLARE #pEnd Int
DECLARE #pTarget varchar(max)
DECLARE #pResult varchar(max)
SET #pStart = CHARINDEX('(', #sourceString)
SET #pEnd = CHARINDEX(')', #sourceString, #pStart) /** start looking from pos of opening bracket */
IF #pEnd > #pStart AND #pEnd > 0 /** basic error avoidance */
BEGIN
SET #pTarget = SUBSTRING(#sourceString, #pStart, #pEnd - #pStart + 1)
SET #pResult = Replace(#sourceString, #pTarget, '')
/** recursion to get rid of more than one set of brackets per string */
IF CHARINDEX('(', #pResult) > 0 AND CHARINDEX(')', #pResult) > CHARINDEX('(', #pResult)
BEGIN
SET #pResult = dbo.RemoveBracketedText(#pResult)
END
END
ELSE
BEGIN
SET #pResult = #sourceString /** no matching set of brackets found */
END
RETURN #pResult
END
select ltrim(rtrim(
replace(
replace(ColumnName,
substring(ColumnName,
charindex('(',ColumnName),
charindex(')',ColumnName) - charindex('(',ColumnName) + 1),
''),
' ',' ')
)) from TableName;

T-Sql function to convert a varchar - in this instance someone's name - from upper to title case?

Does anyone have in their back pocket a function that can achieve this?
Found this here :-
create function ProperCase(#Text as varchar(8000))
returns varchar(8000)
as
begin
declare #Reset bit;
declare #Ret varchar(8000);
declare #i int;
declare #c char(1);
select #Reset = 1, #i=1, #Ret = '';
while (#i <= len(#Text))
select #c= substring(#Text,#i,1),
#Ret = #Ret + case when #Reset=1 then UPPER(#c) else LOWER(#c) end,
#Reset = case when #c like '[a-zA-Z]' then 0 else 1 end,
#i = #i +1
return #Ret
end
Results from this:-
select dbo.propercase('ALL UPPERCASE'); -- All Uppercase
select dbo.propercase('MiXeD CaSe'); -- Mixed Case
select dbo.propercase('lower case'); -- Lower Case
select dbo.propercase('names with apostrophe - mr o''reilly '); -- Names With Apostrophe - Mr O'Reilly
select dbo.propercase('names with hyphen - mary two-barrels '); -- Names With Hyphen - Mary Two-Barrels
I'd do this outside of TSQL, in the calling code tbh.
e.g. if you're using .NET, it's just a case of using TextInfo.ToTitleCase.
That way, you leave your formatting code outside of TSQL (standard "let the caller decide how to use/format the data" approach).
This kind of function is better done on the application side, as it will perform relatively poorly in SQL.
With SQL-Server 2005 and above you could write a CLR function that does that and call it from your SQL. Here is an article on how to do this.
If you really want to do this in T-SQL and without a loop, see Tony Rogerson's article "Turning stuff into "Camel Case" without loops"
I haven't tried it... that's what client code it for :-)
No cursors, no while loops, no (inline) sub-queries
-- ===== IF YOU DON'T HAVE A NUMBERS TABLE =================
--CREATE TABLE Numbers (
-- Num INT NOT NULL PRIMARY KEY CLUSTERED WITH(FILLFACTOR = 100)
--)
--INSERT INTO Numbers
--SELECT TOP(11000)
-- ROW_NUMBER() OVER (ORDER BY (SELECT 1))
--FROM master.sys.all_columns a
-- CROSS JOIN master.sys.all_columns b
DECLARE #text VARCHAR(8000) = 'my text to make title-case';
DECLARE #result VARCHAR(8000);
SET #result = UPPER(LEFT(#text, 1));
SELECT
#result +=
CASE
WHEN SUBSTRING(#text, Num - 1, 1) IN (' ', '-') THEN UPPER(SUBSTRING(#text, Num, 1))
ELSE SUBSTRING(#text, Num, 1)
END
FROM Numbers
WHERE Num > 1 AND Num <= LEN(#text);
PRINT #result;
Will any given row only contain a firstname or a lastname that you wish to convert or will it contain full names separated by spaces? Also, are there any other rules you wish to what characters it should "upper" or lower"?
If you can guarantee that it's only first and last names and you aren't dealing with any specialized capitalization such as after an apostrophe, might this do what you're looking for?
SELECT -- Initial of First Name
UPPER(LEFT(FullName, 1))
-- Rest of First Name
+ SUBSTRING(LOWER(FullName), 2, CHARINDEX(' ', FullName, 0) - 2)
-- Space between names
+ ' '
-- Inital of last name
+ UPPER(SUBSTRING(FullName, CHARINDEX(' ', FullName, 0) + 1, 1))
-- Rest of last name
+ SUBSTRING(LOWER(FullName), CHARINDEX(' ', FullName, 0) + 2, LEN(FullName) - CHARINDEX(' ', FullName, 0) + 2)
FROM Employee

Resources