Replacing set of character in sql query - sql

How do i replace set of character in a table?
ColumnA
%%1234UIT
!!1234TTT
678##PPP
Currently I am using
`replace(replace(replace([BLOCK_NAME],'%%',''),'!!',''),'##',''),1,LEN(BLOCK_NAME)-1`
OR
replace(replace(replace(substring([BLOCK_NAME],1,LEN(BLOCK_NAME)-1),'**',''),'##',''),'$$','')
Expected OUTPUT:
1234UIT
123TTT
678PPP

This should work for your problem, it removes all non numeric characters from the record. You can create a sql function to be called from your query.
WHILE PATINDEX('%[^0-9]%', #strText) > 0
BEGIN
SET #strText = STUFF(#strText, PATINDEX('%[^0-9]%', #strText), 1, '')
END
RETURN #strText

You can create a function as:
CREATE FUNCTION [dbo].[fn_RemoveCharacters]
(
#Str NVARCHAR(MAX),
#MatchExpression VARCHAR(255)
)
RETURNS NVARCHAR(MAX)
AS
BEGIN
SET #MatchExpression = '%['+#MatchExpression+']%'
WHILE PatIndex(#MatchExpression, #Str) > 0
SET #Str = Stuff(#Str, PatIndex(#MatchExpression, #Str), 1, '')
RETURN #Str
END
Go
and then call it as:
SELECT [dbo].[fn_RemoveCharacters](ColumnA, '%%!!##') as ColumnA
from table1
Hope this helps!!!

Please refer how to remove non-numeric/non-alphanumeric characters from string
CREATE FUNCTION [fnRemoveNonNumericCharacters](#strText VARCHAR(1000))
RETURNS VARCHAR(1000)
AS
BEGIN
WHILE PATINDEX('%[^a-z0-9]%', #strText) > 0
BEGIN
SET #strText = STUFF(#strText, PATINDEX('%[^a-z0-9]%', #strText), 1, '')
END
RETURN #strText
END
select data using the created function
SELECT
dbo.fnRemoveNonNumericCharacters(BLOCK_NAME)
FROM
YourTable
OR
;WITH T as(
SELECT STUFF(BLOCK_NAME, PATINDEX('%[^a-z0-9]%', BLOCK_NAME), 1, '') BLOCK_NAME from YourTable
UNION ALL
SELECT STUFF(BLOCK_NAME, PATINDEX('%[^a-z0-9]%', BLOCK_NAME), 1, '') BLOCK_NAME from T where PATINDEX('%[^a-z0-9]%', BLOCK_NAME) > 0
)
select
*
from
T
where PATINDEX('%[^a-z0-9]%', BLOCK_NAME) = 0
I prefer the second method using CTE without a user-defined function.

Related

SQL Query to retrieve 2 digit numbers from the below string

SQL Query to retrieve 2 digit numbers from the below string
String --> 'Partial:[64][95]'
The output should be in the below format.
64,95
You can use the replace() function several times to replace parts of the string.
In the example below I've set a declared variable to your example string:
DECLARE #mystring varchar(100) = 'Partial:[64][95]'
SELECT REPLACE(REPLACE(REPLACE(#mystring, 'Partial:[', '')
, '][', ',')
, ']', '') AS [answer]
Produces output:
answer
------
64,95
Use replace() :
select *, replace(replace(replace(Partial, '][', ','), '[', ''), ']', '')
from table t;
However, this would reduce your nested replace via TRANSLATE() but available from SQL Server 2017.
I was able to get the result with the below query.
DECLARE #string VARCHAR(100);
SET #string = 'Partial:[64][95]';
WHILE PATINDEX('%[^0-9]%', #string) <> 0
SET #string = STUFF(#string, PATINDEX('%[^0-9]%', #string), 1, '');
DECLARE #splitstring NVARCHAR(20) = #string;
DECLARE #i INT = 3;
WHILE #i < LEN(#splitstring)
BEGIN
SELECT #splitstring = STUFF(#splitstring, #i, 0, ',');
SET #i = #i +3;
END;
SELECT #splitstring;
Thanks everyone for the help.

SQL Server capitalize every first letter of every word with loop [duplicate]

What’s the best way to capitalize the first letter of each word in a string in SQL Server.
From http://www.sql-server-helper.com/functions/initcap.aspx
CREATE FUNCTION [dbo].[InitCap] ( #InputString varchar(4000) )
RETURNS VARCHAR(4000)
AS
BEGIN
DECLARE #Index INT
DECLARE #Char CHAR(1)
DECLARE #PrevChar CHAR(1)
DECLARE #OutputString VARCHAR(255)
SET #OutputString = LOWER(#InputString)
SET #Index = 1
WHILE #Index <= LEN(#InputString)
BEGIN
SET #Char = SUBSTRING(#InputString, #Index, 1)
SET #PrevChar = CASE WHEN #Index = 1 THEN ' '
ELSE SUBSTRING(#InputString, #Index - 1, 1)
END
IF #PrevChar IN (' ', ';', ':', '!', '?', ',', '.', '_', '-', '/', '&', '''', '(')
BEGIN
IF #PrevChar != '''' OR UPPER(#Char) != 'S'
SET #OutputString = STUFF(#OutputString, #Index, 1, UPPER(#Char))
END
SET #Index = #Index + 1
END
RETURN #OutputString
END
GO
There is a simpler/smaller one here (but doesn't work if any row doesn't have spaces, "Invalid length parameter passed to the RIGHT function."):
http://www.devx.com/tips/Tip/17608
As a table-valued function:
CREATE FUNCTION dbo.InitCap(#v AS VARCHAR(MAX))
RETURNS TABLE
AS
RETURN
WITH a AS (
SELECT (
SELECT UPPER(LEFT(value, 1)) + LOWER(SUBSTRING(value, 2, LEN(value))) AS 'data()'
FROM string_split(#v, ' ')
ORDER BY CHARINDEX(value,#v)
FOR XML PATH (''), TYPE) ret)
SELECT CAST(a.ret AS varchar(MAX)) ret from a
GO
Note that string_split requires COMPATIBILITY_LEVEL 130.
A variation of the one I've been using for quite some time is:
CREATE FUNCTION [widget].[properCase](#string varchar(8000)) RETURNS varchar(8000) AS
BEGIN
SET #string = LOWER(#string)
DECLARE #i INT
SET #i = ASCII('a')
WHILE #i <= ASCII('z')
BEGIN
SET #string = REPLACE( #string, ' ' + CHAR(#i), ' ' + CHAR(#i-32))
SET #i = #i + 1
END
SET #string = CHAR(ASCII(LEFT(#string, 1))-32) + RIGHT(#string, LEN(#string)-1)
RETURN #string
END
You can easily modify to handle characters after items other than spaces if you wanted to.
Another solution without using the loop - pure set-based approach with recursive CTE
create function [dbo].InitCap (#value varchar(max))
returns varchar(max) as
begin
declare
#separator char(1) = ' ',
#result varchar(max) = '';
with r as (
select value, cast(null as varchar(max)) [x], cast('' as varchar(max)) [char], 0 [no] from (select rtrim(cast(#value as varchar(max))) [value]) as j
union all
select right(value, len(value)-case charindex(#separator, value) when 0 then len(value) else charindex(#separator, value) end) [value]
, left(r.[value], case charindex(#separator, r.value) when 0 then len(r.value) else abs(charindex(#separator, r.[value])-1) end ) [x]
, left(r.[value], 1)
, [no] + 1 [no]
from r where value > '')
select #result = #result +
case
when ascii([char]) between 97 and 122
then stuff(x, 1, 1, char(ascii([char])-32))
else x
end + #separator
from r where x is not null;
set #result = rtrim(#result);
return #result;
end
If you are looking for the answer to the same question in Oracle/PLSQL then you may use the function INITCAP. Below is an example for the attribute dname from a table department which has the values ('sales', 'management', 'production', 'development').
SQL> select INITCAP(dname) from department;
INITCAP(DNAME)
--------------------------------------------------
Sales
Management
Production
Development
;WITH StudentList(Name) AS (
SELECT CONVERT(varchar(50), 'Carl-VAN')
UNION SELECT 'Dean o''brian'
UNION SELECT 'Andrew-le-Smith'
UNION SELECT 'Eddy thompson'
UNION SELECT 'BOBs-your-Uncle'
), Student AS (
SELECT CONVERT(varchar(50), UPPER(LEFT(Name, 1)) + LOWER(SUBSTRING(Name, 2, LEN(Name)))) Name,
pos = PATINDEX('%[-'' ]%', Name)
FROM StudentList
UNION ALL
SELECT CONVERT(varchar(50), LEFT(Name, pos) + UPPER(SUBSTRING(Name, pos + 1, 1)) + SUBSTRING(Name, pos + 2, LEN(Name))) Name,
pos = CASE WHEN PATINDEX('%[-'' ]%', RIGHT(Name, LEN(Name) - pos)) = 0 THEN 0 ELSE pos + PATINDEX('%[-'' ]%', RIGHT(Name, LEN(Name) - pos)) END
FROM Student
WHERE pos > 0
)
SELECT Name
FROM Student
WHERE pos = 0
ORDER BY Name
This will result in:
Andrew-Le-Smith
Bobs-Your-Uncle
Carl-Van
Dean O'Brian
Eddy Thompson
Using a recursive CTE set based query should out perform a procedural while loop query.
Here I also have made my separate to be 3 different characters [-' ] instead of 1 for a more advanced example. Using PATINDEX as I have done allows me to look for many characters. You could also use CHARINDEX on a single character and this function excepts a third parameter StartFromPosition so I could further simply my 2nd part of the recursion of the pos formula to (assuming a space): pos = CHARINDEX(' ', Name, pos + 1).
The suggested function works fine, however, if you do not want to create any function this is how I do it:
select ID,Name
,string_agg(concat(upper(substring(value,1,1)),lower(substring(value,2,len(value)-1))),' ') as ModifiedName
from Table_Customer
cross apply String_Split(replace(trim(Name),' ',' '),' ')
where Name is not null
group by ID,Name;
The above query split the words by space (' ') and create different rows of each having one substring, then convert the first letter of each substring to upper and keep remaining as lower. The final step is to string aggregate based on the key.
BEGIN
DECLARE #string varchar(100) = 'asdsadsd asdad asd'
DECLARE #ResultString varchar(200) = ''
DECLARE #index int = 1
DECLARE #flag bit = 0
DECLARE #temp varchar(2) = ''
WHILE (#Index <LEN(#string)+1)
BEGIN
SET #temp = SUBSTRING(#string, #Index-1, 1)
--select #temp
IF #temp = ' ' OR #index = 1
BEGIN
SET #ResultString = #ResultString + UPPER(SUBSTRING(#string, #Index, 1))
END
ELSE
BEGIN
SET #ResultString = #ResultString + LOWER(SUBSTRING(#string, #Index, 1))
END
SET #Index = #Index+ 1--increase the index
END
SELECT #ResultString
END
It can be as simple as this:
DECLARE #Name VARCHAR(500) = 'Roger';
SELECT #Name AS Name, UPPER(LEFT(#Name, 1)) + SUBSTRING(#Name, 2, LEN(#Name)) AS CapitalizedName;
fname is column name if fname value is akhil then UPPER(left(fname,1)) provide capital First letter(A) and substring function SUBSTRING(fname,2,LEN(fname)) provide(khil) concate both using + then result is (Akhil)
select UPPER(left(fname,1))+SUBSTRING(fname,2,LEN(fname)) as fname
FROM [dbo].[akhil]
On SQL Server 2016+ using JSON which gives guaranteed order of the words:
CREATE FUNCTION [dbo].[InitCap](#Text NVARCHAR(MAX))
RETURNS NVARCHAR(MAX)
AS
BEGIN
RETURN STUFF((
SELECT ' ' + UPPER(LEFT(s.value,1)) + LOWER(SUBSTRING(s.value,2,LEN(s.value)))
FROM OPENJSON('["' + REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(#Text,'\','\\'),'"','\"'),CHAR(9),'\t'),CHAR(10),'\n'),' ','","') + '"]') s
ORDER BY s.[key]
FOR XML PATH(''),TYPE).value('(./text())[1]','NVARCHAR(MAX)'),1,1,'');
END
GO
CREATE FUNCTION [dbo].[Capitalize](#text NVARCHAR(MAX)) RETURNS NVARCHAR(MAX) AS
BEGIN
DECLARE #result NVARCHAR(MAX) = '';
DECLARE #c NVARCHAR(1);
DECLARE #i INT = 1;
DECLARE #isPrevSpace BIT = 1;
WHILE #i <= LEN(#text)
BEGIN
SET #c = SUBSTRING(#text, #i, 1);
SET #result += IIF(#isPrevSpace = 1, UPPER(#c), LOWER(#c));
SET #isPrevSpace = IIF(#c LIKE '[ -]', 1, 0);
SET #i += 1;
END
RETURN #result;
END
GO
DECLARE #sentence NVARCHAR(100) = N'i-thINK-this soLUTION-works-LiKe-a charm';
PRINT dbo.Capitalize(#sentence);
-- I-Think-This Solution-Works-Like-A Charm
Here is the simplest one-liner to do this:
SELECT LEFT(column, 1)+ lower(RIGHT(column, len(column)-1) ) FROM [tablename]
I was looking for the best way to capitalize and i recreate simple sql script
how to use SELECT dbo.Capitalyze('this is a test with multiple spaces')
result "This Is A Test With Multiple Spaces"
CREATE FUNCTION Capitalyze(#input varchar(100) )
returns varchar(100)
as
begin
declare #index int=0
declare #char as varchar(1)=' '
declare #prevCharIsSpace as bit=1
declare #Result as varchar(100)=''
set #input=UPPER(LEFT(#input,1))+LOWER(SUBSTRING(#input, 2, LEN(#input)))
set #index=PATINDEX('% _%',#input)
if #index=0
set #index=len(#input)
set #Result=substring(#input,0,#index+1)
WHILE (#index < len(#input))
BEGIN
SET #index = #index + 1
SET #char=substring(#input,#index,1)
if (#prevCharIsSpace=1)
begin
set #char=UPPER(#char)
if (#char=' ')
set #char=''
end
if (#char=' ')
set #prevCharIsSpace=1
else
set #prevCharIsSpace=0
set #Result=#Result+#char
--print #Result
END
--print #Result
return #Result
end
IF OBJECT_ID ('dbo.fnCapitalizeFirstLetterAndChangeDelimiter') IS NOT NULL
DROP FUNCTION dbo.fnCapitalizeFirstLetterAndChangeDelimiter
GO
CREATE FUNCTION [dbo].[fnCapitalizeFirstLetterAndChangeDelimiter] (#string NVARCHAR(MAX), #delimiter NCHAR(1), #new_delimeter NCHAR(1))
RETURNS NVARCHAR(MAX)
AS
BEGIN
DECLARE #result NVARCHAR(MAX)
SELECT #result = '';
IF (LEN(#string) > 0)
DECLARE #curr INT
DECLARE #next INT
BEGIN
SELECT #curr = 1
SELECT #next = CHARINDEX(#delimiter, #string)
WHILE (LEN(#string) > 0)
BEGIN
SELECT #result =
#result +
CASE WHEN LEN(#result) > 0 THEN #new_delimeter ELSE '' END +
UPPER(SUBSTRING(#string, #curr, 1)) +
CASE
WHEN #next <> 0
THEN LOWER(SUBSTRING(#string, #curr+1, #next-2))
ELSE LOWER(SUBSTRING(#string, #curr+1, LEN(#string)-#curr))
END
IF (#next > 0)
BEGIN
SELECT #string = SUBSTRING(#string, #next+1, LEN(#string)-#next)
SELECT #next = CHARINDEX(#delimiter, #string)
END
ELSE
SELECT #string = ''
END
END
RETURN #result
END
GO

by using split function of sql get correct result

I am using Oracle DB.
select split('123,45,6,7',1,',') from dual ;
---------------------------------------------------------------------
result
123
---------------------------------------------------------------------
In above query only 1st value(123) will be in result.
Is there any way to fetch all values from above query.
I want result like below in one query:
result
123
45
6
7
Try this way
DECLARE #Str VARCHAR(100)= '123,45,6,7' ;WITH _CTE (_Str , _RemStr) AS
(
SELECT SUBSTRING(#Str,0,CHARINDEX(',',#Str)) ,
SUBSTRING(#Str,CHARINDEX(',',#Str)+1,LEN(#Str))
UNION ALL
SELECT CASE WHEN CHARINDEX(',',_RemStr) = 0 THEN _RemStr ELSE SUBSTRING(_RemStr,0,CHARINDEX(',',_RemStr)) END,
CASE WHEN CHARINDEX(',',_RemStr) = 0 THEN '' ELSE SUBSTRING(_RemStr,CHARINDEX(',',_RemStr)+1,LEN(_RemStr)) END
FROM _CTE
WHERE _RemStr <> ''
)
SELECT _Str
FROM _CTE
Use below function for Split string
Create FUNCTION [dbo].[SplitString]
(
#INPUT nvarchar(max)
)
RETURNS
#ParsedList table
(
OrderID int
)
AS
BEGIN
DECLARE #OrderID varchar(10), #Pos int
SET #INPUT = LTRIM(RTRIM(#INPUT))+ ','
SET #Pos = CHARINDEX(',', #INPUT, 1)
IF REPLACE(#INPUT, ',', '') <> ''
BEGIN
WHILE #Pos > 0
BEGIN
SET #OrderID = LTRIM(RTRIM(LEFT(#INPUT, #Pos - 1)))
IF #OrderID <> ''
BEGIN
INSERT INTO #ParsedList (OrderID)
VALUES (CAST(#OrderID AS int)) --Use Appropriate conversion
END
SET #INPUT = RIGHT(#INPUT, LEN(#INPUT) - #Pos)
SET #Pos = CHARINDEX(',', #INPUT, 1)
END
END
RETURN
END
And Execute below
Select * from [SplitString]('123,45,6,7')

Append a specific character after each character of a string in sql server

Thanks to advise me for the below issue:
I am using below query to fetch the value of a column:
Select OptionList = case when isnull(AS_CIS_Code,'') <> '' then AS_CIS_Code
else ''
end
from added_services
AS_CIS_Code column is of varchar(10) in added_services table. It contains values like 'AB', 'ABC', 'GHKIK', 'UYTIOPJ' and so on which represents different codes.
Now I have to select these codes after modifying the above query so that '_' is appended after each character.
Like it should be fetched as 'A_B_', 'A_B_C_', 'G_H_K_I_K_', 'U_Y_T_I_O_P_J_'.
How should I implement it? Using a temp table will down the performance for one column only, so should I use while loop or please suggest me better alternatives.
Try this:
DECLARE #Input VARCHAR(100) = 'TESTING'
DECLARE #Pos INT = LEN(#Input)
WHILE #Pos > 1
BEGIN
SET #Input = STUFF(#Input,#Pos,0,'_')
SET #Pos = #Pos - 1
END
SELECT #Input
Output
T_E_S_T_I_N_G
UDF
CREATE FUNCTION PadStr(#Data VARCHAR(100)) RETURNS VARCHAR(200)
AS
BEGIN
DECLARE #Input VARCHAR(200) = #Data
DECLARE #Pos INT = LEN(#Input)
WHILE #Pos > 1
BEGIN
SET #Input = STUFF(#Input,#Pos,0,'_')
SET #Pos = #Pos - 1
END
RETURN #Input + '_'
END
Output
SELECT dbo.PadStr('TESTING') -- T_E_S_T_I_N_G_
You can split the string using a numbers table and the rebuild it using for xml path().
select isnull(C.Value, '') as AS_CIS_Code
from added_services as A
cross apply (
select substring(A.AS_CIS_Code, T.N, 1)+'_'
from (values(1),(2),(3),(4),(5),(6),(7),(8),(9),(10)) as T(N)
where T.N <= len(A.AS_CIS_Code)
order by T.N
for xml path('')
) as C(Value)
SQL Fiddle
Try this
Create Function Code_Pad
(
#code varchar(max)
)
returns varchar(max)
as
begin
Declare #coding varchar(max) =''
Declare #i int = 1
WHILE(LEN(#Coding)<=2*len(#code)-1)
begin
Select #coding = #coding+SUBSTRING(#code,#i,1)+'_'
set #i=#i+1
end
return #coding
end
End of Function
Select OptionList = case when isnull(AS_CIS_Code,'') <> '' then dbo.Code_Pad(AS_CIS_Code) else ''
end
from added_services
May not be best solution, but works in one query using recursion
;WITH valCTE(Replaced,ToBeReplaced,Position)
AS
(
SELECT CAST(LEFT(AS_CIS_Code,1) + '_' AS VARCHAR(20))
,SUBSTRING(AS_CIS_Code,2,LEN(AS_CIS_Code)-1)
,1
FROM added_services
UNION ALL
SELECT CAST(Replaced + LEFT(ToBeReplaced,1) + '_' AS VARCHAR(20))
,SUBSTRING(ToBeReplaced,2,LEN(ToBeReplaced)-1)
,Position+1
FROM valCTE
WHERE LEN(ToBeReplaced)>0
)
SELECT TOP 1 LEFT(Replaced,LEN(Replaced)-1) -- remove last _
FROM valCTE
ORDER BY Position DESC

How to capitalize the first letter of each word in a string in SQL Server

What’s the best way to capitalize the first letter of each word in a string in SQL Server.
From http://www.sql-server-helper.com/functions/initcap.aspx
CREATE FUNCTION [dbo].[InitCap] ( #InputString varchar(4000) )
RETURNS VARCHAR(4000)
AS
BEGIN
DECLARE #Index INT
DECLARE #Char CHAR(1)
DECLARE #PrevChar CHAR(1)
DECLARE #OutputString VARCHAR(255)
SET #OutputString = LOWER(#InputString)
SET #Index = 1
WHILE #Index <= LEN(#InputString)
BEGIN
SET #Char = SUBSTRING(#InputString, #Index, 1)
SET #PrevChar = CASE WHEN #Index = 1 THEN ' '
ELSE SUBSTRING(#InputString, #Index - 1, 1)
END
IF #PrevChar IN (' ', ';', ':', '!', '?', ',', '.', '_', '-', '/', '&', '''', '(')
BEGIN
IF #PrevChar != '''' OR UPPER(#Char) != 'S'
SET #OutputString = STUFF(#OutputString, #Index, 1, UPPER(#Char))
END
SET #Index = #Index + 1
END
RETURN #OutputString
END
GO
There is a simpler/smaller one here (but doesn't work if any row doesn't have spaces, "Invalid length parameter passed to the RIGHT function."):
http://www.devx.com/tips/Tip/17608
As a table-valued function:
CREATE FUNCTION dbo.InitCap(#v AS VARCHAR(MAX))
RETURNS TABLE
AS
RETURN
WITH a AS (
SELECT (
SELECT UPPER(LEFT(value, 1)) + LOWER(SUBSTRING(value, 2, LEN(value))) AS 'data()'
FROM string_split(#v, ' ')
ORDER BY CHARINDEX(value,#v)
FOR XML PATH (''), TYPE) ret)
SELECT CAST(a.ret AS varchar(MAX)) ret from a
GO
Note that string_split requires COMPATIBILITY_LEVEL 130.
A variation of the one I've been using for quite some time is:
CREATE FUNCTION [widget].[properCase](#string varchar(8000)) RETURNS varchar(8000) AS
BEGIN
SET #string = LOWER(#string)
DECLARE #i INT
SET #i = ASCII('a')
WHILE #i <= ASCII('z')
BEGIN
SET #string = REPLACE( #string, ' ' + CHAR(#i), ' ' + CHAR(#i-32))
SET #i = #i + 1
END
SET #string = CHAR(ASCII(LEFT(#string, 1))-32) + RIGHT(#string, LEN(#string)-1)
RETURN #string
END
You can easily modify to handle characters after items other than spaces if you wanted to.
Another solution without using the loop - pure set-based approach with recursive CTE
create function [dbo].InitCap (#value varchar(max))
returns varchar(max) as
begin
declare
#separator char(1) = ' ',
#result varchar(max) = '';
with r as (
select value, cast(null as varchar(max)) [x], cast('' as varchar(max)) [char], 0 [no] from (select rtrim(cast(#value as varchar(max))) [value]) as j
union all
select right(value, len(value)-case charindex(#separator, value) when 0 then len(value) else charindex(#separator, value) end) [value]
, left(r.[value], case charindex(#separator, r.value) when 0 then len(r.value) else abs(charindex(#separator, r.[value])-1) end ) [x]
, left(r.[value], 1)
, [no] + 1 [no]
from r where value > '')
select #result = #result +
case
when ascii([char]) between 97 and 122
then stuff(x, 1, 1, char(ascii([char])-32))
else x
end + #separator
from r where x is not null;
set #result = rtrim(#result);
return #result;
end
If you are looking for the answer to the same question in Oracle/PLSQL then you may use the function INITCAP. Below is an example for the attribute dname from a table department which has the values ('sales', 'management', 'production', 'development').
SQL> select INITCAP(dname) from department;
INITCAP(DNAME)
--------------------------------------------------
Sales
Management
Production
Development
;WITH StudentList(Name) AS (
SELECT CONVERT(varchar(50), 'Carl-VAN')
UNION SELECT 'Dean o''brian'
UNION SELECT 'Andrew-le-Smith'
UNION SELECT 'Eddy thompson'
UNION SELECT 'BOBs-your-Uncle'
), Student AS (
SELECT CONVERT(varchar(50), UPPER(LEFT(Name, 1)) + LOWER(SUBSTRING(Name, 2, LEN(Name)))) Name,
pos = PATINDEX('%[-'' ]%', Name)
FROM StudentList
UNION ALL
SELECT CONVERT(varchar(50), LEFT(Name, pos) + UPPER(SUBSTRING(Name, pos + 1, 1)) + SUBSTRING(Name, pos + 2, LEN(Name))) Name,
pos = CASE WHEN PATINDEX('%[-'' ]%', RIGHT(Name, LEN(Name) - pos)) = 0 THEN 0 ELSE pos + PATINDEX('%[-'' ]%', RIGHT(Name, LEN(Name) - pos)) END
FROM Student
WHERE pos > 0
)
SELECT Name
FROM Student
WHERE pos = 0
ORDER BY Name
This will result in:
Andrew-Le-Smith
Bobs-Your-Uncle
Carl-Van
Dean O'Brian
Eddy Thompson
Using a recursive CTE set based query should out perform a procedural while loop query.
Here I also have made my separate to be 3 different characters [-' ] instead of 1 for a more advanced example. Using PATINDEX as I have done allows me to look for many characters. You could also use CHARINDEX on a single character and this function excepts a third parameter StartFromPosition so I could further simply my 2nd part of the recursion of the pos formula to (assuming a space): pos = CHARINDEX(' ', Name, pos + 1).
The suggested function works fine, however, if you do not want to create any function this is how I do it:
select ID,Name
,string_agg(concat(upper(substring(value,1,1)),lower(substring(value,2,len(value)-1))),' ') as ModifiedName
from Table_Customer
cross apply String_Split(replace(trim(Name),' ',' '),' ')
where Name is not null
group by ID,Name;
The above query split the words by space (' ') and create different rows of each having one substring, then convert the first letter of each substring to upper and keep remaining as lower. The final step is to string aggregate based on the key.
BEGIN
DECLARE #string varchar(100) = 'asdsadsd asdad asd'
DECLARE #ResultString varchar(200) = ''
DECLARE #index int = 1
DECLARE #flag bit = 0
DECLARE #temp varchar(2) = ''
WHILE (#Index <LEN(#string)+1)
BEGIN
SET #temp = SUBSTRING(#string, #Index-1, 1)
--select #temp
IF #temp = ' ' OR #index = 1
BEGIN
SET #ResultString = #ResultString + UPPER(SUBSTRING(#string, #Index, 1))
END
ELSE
BEGIN
SET #ResultString = #ResultString + LOWER(SUBSTRING(#string, #Index, 1))
END
SET #Index = #Index+ 1--increase the index
END
SELECT #ResultString
END
It can be as simple as this:
DECLARE #Name VARCHAR(500) = 'Roger';
SELECT #Name AS Name, UPPER(LEFT(#Name, 1)) + SUBSTRING(#Name, 2, LEN(#Name)) AS CapitalizedName;
fname is column name if fname value is akhil then UPPER(left(fname,1)) provide capital First letter(A) and substring function SUBSTRING(fname,2,LEN(fname)) provide(khil) concate both using + then result is (Akhil)
select UPPER(left(fname,1))+SUBSTRING(fname,2,LEN(fname)) as fname
FROM [dbo].[akhil]
On SQL Server 2016+ using JSON which gives guaranteed order of the words:
CREATE FUNCTION [dbo].[InitCap](#Text NVARCHAR(MAX))
RETURNS NVARCHAR(MAX)
AS
BEGIN
RETURN STUFF((
SELECT ' ' + UPPER(LEFT(s.value,1)) + LOWER(SUBSTRING(s.value,2,LEN(s.value)))
FROM OPENJSON('["' + REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(#Text,'\','\\'),'"','\"'),CHAR(9),'\t'),CHAR(10),'\n'),' ','","') + '"]') s
ORDER BY s.[key]
FOR XML PATH(''),TYPE).value('(./text())[1]','NVARCHAR(MAX)'),1,1,'');
END
GO
CREATE FUNCTION [dbo].[Capitalize](#text NVARCHAR(MAX)) RETURNS NVARCHAR(MAX) AS
BEGIN
DECLARE #result NVARCHAR(MAX) = '';
DECLARE #c NVARCHAR(1);
DECLARE #i INT = 1;
DECLARE #isPrevSpace BIT = 1;
WHILE #i <= LEN(#text)
BEGIN
SET #c = SUBSTRING(#text, #i, 1);
SET #result += IIF(#isPrevSpace = 1, UPPER(#c), LOWER(#c));
SET #isPrevSpace = IIF(#c LIKE '[ -]', 1, 0);
SET #i += 1;
END
RETURN #result;
END
GO
DECLARE #sentence NVARCHAR(100) = N'i-thINK-this soLUTION-works-LiKe-a charm';
PRINT dbo.Capitalize(#sentence);
-- I-Think-This Solution-Works-Like-A Charm
Here is the simplest one-liner to do this:
SELECT LEFT(column, 1)+ lower(RIGHT(column, len(column)-1) ) FROM [tablename]
I was looking for the best way to capitalize and i recreate simple sql script
how to use SELECT dbo.Capitalyze('this is a test with multiple spaces')
result "This Is A Test With Multiple Spaces"
CREATE FUNCTION Capitalyze(#input varchar(100) )
returns varchar(100)
as
begin
declare #index int=0
declare #char as varchar(1)=' '
declare #prevCharIsSpace as bit=1
declare #Result as varchar(100)=''
set #input=UPPER(LEFT(#input,1))+LOWER(SUBSTRING(#input, 2, LEN(#input)))
set #index=PATINDEX('% _%',#input)
if #index=0
set #index=len(#input)
set #Result=substring(#input,0,#index+1)
WHILE (#index < len(#input))
BEGIN
SET #index = #index + 1
SET #char=substring(#input,#index,1)
if (#prevCharIsSpace=1)
begin
set #char=UPPER(#char)
if (#char=' ')
set #char=''
end
if (#char=' ')
set #prevCharIsSpace=1
else
set #prevCharIsSpace=0
set #Result=#Result+#char
--print #Result
END
--print #Result
return #Result
end
IF OBJECT_ID ('dbo.fnCapitalizeFirstLetterAndChangeDelimiter') IS NOT NULL
DROP FUNCTION dbo.fnCapitalizeFirstLetterAndChangeDelimiter
GO
CREATE FUNCTION [dbo].[fnCapitalizeFirstLetterAndChangeDelimiter] (#string NVARCHAR(MAX), #delimiter NCHAR(1), #new_delimeter NCHAR(1))
RETURNS NVARCHAR(MAX)
AS
BEGIN
DECLARE #result NVARCHAR(MAX)
SELECT #result = '';
IF (LEN(#string) > 0)
DECLARE #curr INT
DECLARE #next INT
BEGIN
SELECT #curr = 1
SELECT #next = CHARINDEX(#delimiter, #string)
WHILE (LEN(#string) > 0)
BEGIN
SELECT #result =
#result +
CASE WHEN LEN(#result) > 0 THEN #new_delimeter ELSE '' END +
UPPER(SUBSTRING(#string, #curr, 1)) +
CASE
WHEN #next <> 0
THEN LOWER(SUBSTRING(#string, #curr+1, #next-2))
ELSE LOWER(SUBSTRING(#string, #curr+1, LEN(#string)-#curr))
END
IF (#next > 0)
BEGIN
SELECT #string = SUBSTRING(#string, #next+1, LEN(#string)-#next)
SELECT #next = CHARINDEX(#delimiter, #string)
END
ELSE
SELECT #string = ''
END
END
RETURN #result
END
GO