Capitalize only the first letter of each word of each sentence in SQL ServerIn SQL Server, should I force a...
Exploding Numbers
Does changing "sa" password require a SQL restart (in mixed mode)?
Ramanujan's radical and how we define an infinite nested radical
Stream.findFirst different than Optional.of?
Is Screenshot Time-tracking Common?
How to write painful torture scenes without being over-the-top
Why is the meaning of kanji 閑 "leisure"?
Could Comets or Meteors be used to Combat Global Warming?
Boss asked me to sign a resignation paper without a date on it along with my new contract
Rudeness by being polite
Was Opportunity's last message to Earth "My battery is low and it's getting dark"?
multiple null checks in Java8
Can I legally make a website about boycotting a certain company?
80-bit collision resistence because of 80-bit x87 registers?
Why Third 'Reich'? Why is 'reich' not translated when 'third' is? What is the English synonym of reich?
How do I write a maintainable, fast, compile-time bit-mask in C++?
Why are `&array` and `array` pointing to the same address?
Why do we divide Permutations to get to Combinations?
Why is Shelob considered evil?
Why would you use 2 alternate layout buttons instead of 1, when only one can be selected at once
Is it possible to detect 100% of SQLi with a simple regex?
Arizona laws regarding ownership of ground glassware for chemistry usage
The Late Queen Gives in to Remorse - Reverse Hangman
How should I ship cards?
Capitalize only the first letter of each word of each sentence in SQL Server
In SQL Server, should I force a LOOP JOIN in the following case?T-SQL bulk insert fails on specific word “DENY” in string-dataPerform regex search queries of a text column in table of 100+ million using regexCapitalize only the first letter of a nameT-SQL Fulltext search by first wordHow can I make this aggregation query more efficient?RTF varchar to Plain Text varcharTSQL Extract first word as First name. If only one word or null, set to ‘’Correct case for each reserved word in SQL Server?Capitalize first letter with exceptions
I want to capitalize only the first letter of each word of each sentence in a SQL column.
For example, if the sentence is:
'I like movies'
then I need the output:
'I Like Movies'
Query:
declare @a varchar(15)
set @a = 'qWeRtY kEyBoArD'
select @a as [Normal text],
upper(@a) as [Uppercase text],
lower(@a) as [Lowercase text],
upper(left(@a,1)) + lower(substring(@a,2,len(@a))) as [Capitalize first letter only]
Here I did upper, lower, and capitalize first letter only in my column (here I put just a random word).
Here are my results:
Is there any possibilities to do that?
Any possibilities to get results without using user defined function?
I need the output Qwerty Keyboard
sql-server sql-server-2014
add a comment |
I want to capitalize only the first letter of each word of each sentence in a SQL column.
For example, if the sentence is:
'I like movies'
then I need the output:
'I Like Movies'
Query:
declare @a varchar(15)
set @a = 'qWeRtY kEyBoArD'
select @a as [Normal text],
upper(@a) as [Uppercase text],
lower(@a) as [Lowercase text],
upper(left(@a,1)) + lower(substring(@a,2,len(@a))) as [Capitalize first letter only]
Here I did upper, lower, and capitalize first letter only in my column (here I put just a random word).
Here are my results:
Is there any possibilities to do that?
Any possibilities to get results without using user defined function?
I need the output Qwerty Keyboard
sql-server sql-server-2014
11
Why you do want to do this within sql server ? Your presentation layer should handle that efficiently !
– Kin
May 24 '16 at 15:53
add a comment |
I want to capitalize only the first letter of each word of each sentence in a SQL column.
For example, if the sentence is:
'I like movies'
then I need the output:
'I Like Movies'
Query:
declare @a varchar(15)
set @a = 'qWeRtY kEyBoArD'
select @a as [Normal text],
upper(@a) as [Uppercase text],
lower(@a) as [Lowercase text],
upper(left(@a,1)) + lower(substring(@a,2,len(@a))) as [Capitalize first letter only]
Here I did upper, lower, and capitalize first letter only in my column (here I put just a random word).
Here are my results:
Is there any possibilities to do that?
Any possibilities to get results without using user defined function?
I need the output Qwerty Keyboard
sql-server sql-server-2014
I want to capitalize only the first letter of each word of each sentence in a SQL column.
For example, if the sentence is:
'I like movies'
then I need the output:
'I Like Movies'
Query:
declare @a varchar(15)
set @a = 'qWeRtY kEyBoArD'
select @a as [Normal text],
upper(@a) as [Uppercase text],
lower(@a) as [Lowercase text],
upper(left(@a,1)) + lower(substring(@a,2,len(@a))) as [Capitalize first letter only]
Here I did upper, lower, and capitalize first letter only in my column (here I put just a random word).
Here are my results:
Is there any possibilities to do that?
Any possibilities to get results without using user defined function?
I need the output Qwerty Keyboard
sql-server sql-server-2014
sql-server sql-server-2014
edited May 29 '16 at 20:04
Paul White♦
52.2k14278450
52.2k14278450
asked May 24 '16 at 15:27
Marin MohanadasMarin Mohanadas
1862517
1862517
11
Why you do want to do this within sql server ? Your presentation layer should handle that efficiently !
– Kin
May 24 '16 at 15:53
add a comment |
11
Why you do want to do this within sql server ? Your presentation layer should handle that efficiently !
– Kin
May 24 '16 at 15:53
11
11
Why you do want to do this within sql server ? Your presentation layer should handle that efficiently !
– Kin
May 24 '16 at 15:53
Why you do want to do this within sql server ? Your presentation layer should handle that efficiently !
– Kin
May 24 '16 at 15:53
add a comment |
11 Answers
11
active
oldest
votes
declare @a varchar(30);
set @a = 'qWeRtY kEyBoArD TEST<>&''"X';
select stuff((
select ' '+upper(left(T3.V, 1))+lower(stuff(T3.V, 1, 1, ''))
from (select cast(replace((select @a as '*' for xml path('')), ' ', '<X/>') as xml).query('.')) as T1(X)
cross apply T1.X.nodes('text()') as T2(X)
cross apply (select T2.X.value('.', 'varchar(30)')) as T3(V)
for xml path(''), type
).value('text()[1]', 'varchar(30)'), 1, 1, '') as [Capitalize first letter only];
This first converts the string to XML by replacing all spaces with the empty tag <X/>
. Then it shreds the XML to get one word per row using nodes()
. To get the rows back to one value it uses the for xml path
trick.
8
And that code is exactly why I would never do that in SQL. Not saying the answer is wrong - this was asked for. But standard SQL is ridiculously ill suited for this type of string manipulation. A CLR based function would work, or just doing it on the presentation layer.
– TomTom
May 24 '16 at 16:20
8
@TomTom It looks complicated but that is nothing compared to the query plan it produces and it will not be fast by any standard. It is however educational and fun to dig in to what is actually going on in the query and why it is written the way it is. The problem could be solved with a string split function (number table). Hard to avoid thefor xml path
trick for concatenation. Unless you go for CLR which would be the best option if speed and efficiency is important.
– Mikael Eriksson
May 24 '16 at 17:14
1
@MikaelEriksson Well done! I modified this code slightly and used it in my answer to compare against a SQLCLR implementation (only compared functionality, not performance): dba.stackexchange.com/a/142435/30859
– Solomon Rutzky
Jun 28 '16 at 7:16
add a comment |
In SQL Server 2016 you can do this with R, eg
-- R capitalisation code stolen from here:
-- http://stackoverflow.com/questions/6364783/capitalize-the-first-letter-of-both-words-in-a-two-word-string
EXEC sp_execute_external_script
@language = N'R',
@script = N'
simpleCap <- function(x) {
s <- strsplit(x, " ")[[1]]
paste(toupper(substring(s, 1,1)), substring(s, 2),
sep="", collapse=" ")
}
OutputDataSet <- as.data.frame((sapply(as.vector(InputDataSet$xtext), simpleCap)))',
@input_data_1 = N'SELECT LOWER(testString) xtext FROM dbo.testStrings'
WITH RESULT SETS ( ( properCase VARCHAR(50) NOT NULL ) );
Whether you should or not is a different question : )
add a comment |
Maybe I'm being silly but checking the below query I've written against some of the provided, this seems to be a bit more efficient (depending on indexing).
The code is a bit stupid, but isn't there a saying that if it looks stupid but it works then it's not stupid.
Begin
Declare @text Varchar(30);
Set @text = 'qWeRtY kEyBoArD TEST<>&''"X';
Declare @1 Varchar(2)= ' a'
, @2 Varchar(2)= ' b'
, @3 Varchar(2)= ' c'
, @4 Varchar(2)= ' d'
, @5 Varchar(2)= ' e'
, @6 Varchar(2)= ' f'
, @7 Varchar(2)= ' g'
, @8 Varchar(2)= ' h'
, @9 Varchar(2)= ' i'
, @10 Varchar(2)= ' j'
, @11 Varchar(2)= ' k'
, @12 Varchar(2)= ' l'
, @13 Varchar(2)= ' m'
, @14 Varchar(2)= ' n'
, @15 Varchar(2)= ' o'
, @16 Varchar(2)= ' p'
, @17 Varchar(2)= ' q'
, @18 Varchar(2)= ' r'
, @19 Varchar(2)= ' s'
, @20 Varchar(2)= ' t'
, @21 Varchar(2)= ' u'
, @22 Varchar(2)= ' v'
, @23 Varchar(2)= ' w'
, @24 Varchar(2)= ' x'
, @25 Varchar(2)= ' y'
, @26 Varchar(2)= ' z';
Set @text=' '+@text
Select LTrim(Replace(Replace(Replace(Replace(Replace(Replace(Replace(Replace(Replace(Replace(Replace(Replace(Replace(Replace(Replace(Replace(Replace(Replace(Replace(Replace(Replace(Replace(Replace(Replace(Replace(Replace(Lower(@text) ,
@1 , Upper(@1)) ,
@2 , Upper(@2)) ,
@3 , Upper(@3)) ,
@4 , Upper(@4)) ,
@5 , Upper(@5)) ,
@6 , Upper(@6)) ,
@7 , Upper(@7)) ,
@8 , Upper(@8)) ,
@9 , Upper(@9)) ,
@10 , Upper(@10)) ,
@11 , Upper(@11)) ,
@12 , Upper(@12)) ,
@13 , Upper(@13)) ,
@14 , Upper(@14)) ,
@15 , Upper(@15)) ,
@16 , Upper(@16)) ,
@17 , Upper(@17)) ,
@18 , Upper(@18)) ,
@19 , Upper(@19)) ,
@20 , Upper(@20)) ,
@21 , Upper(@21)) ,
@22 , Upper(@22)) , @23 ,
Upper(@23)) , @24 , Upper(@24)) ,
@25 , Upper(@25)) , @26 , Upper(@26)));
end
2
This is a great, and horrible, answer. I particularly like the space you've tacked on at the beginning and then strip off at the end.
– BradC
Jun 14 '16 at 17:03
2
@BradC it is hideous, but when I've tried it compared to XML method against a data set it seems to run at a fraction of the cost!
– Chris J
Jun 14 '16 at 18:31
Haha! Beautiful! +1
– Nelz
Jul 27 '17 at 9:50
add a comment |
Another option is to handle this via SQLCLR. There is even a method already available in .NET that does this: TextInfo.ToTitleCase (in System.Globalization
). This method will Upper-Case the first letter of each word, and Lower-Case the remaining letters. Unlike the other proposals here, it also skips words that are in all upper-case, assuming them to be acronyms. Of course, if this behavior is desired, it would be easy enough to update any of the T-SQL suggestions to do this as well.
One benefit of the .NET method is that it can Upper-Case letters that are Supplementary Characters. For example: DESERET SMALL LETTER OW has an upper-case mapping of DESERET CAPITAL LETTER OW (both show up as boxes when I paste them into here), but the UPPER()
function does not change the lower-case version to upper-case, even when the default Collation for the current Database is set to Latin1_General_100_CI_AS_SC
. This seems consistent with the MSDN documentation which does not list UPPER
and LOWER
in the chart of functions that behave differently when using an _SC
Collation: Collation and Unicode Support: Supplementary Characters.
SELECT N'DESERET SMALL LETTER OW' AS [Label], NCHAR(0xD801)+NCHAR(0xDC35) AS [Thing]
UNION ALL
SELECT N'DESERET CAPITAL LETTER OW' AS [Label], NCHAR(0xD801)+NCHAR(0xDC0D) AS [Thing]
UNION ALL
SELECT N'SmallButShouldBeCapital' AS [Label], UPPER(NCHAR(0xD801)+NCHAR(0xDC35)) AS [Thing]
Returns (enlarged so you can actually see the Supplementary Character):
You can see the full (and current) list of characters that are lower-case and change to upper-case using the following search feature at Unicode.org (you can see the Supplementary Characters by scrolling down until you get to the "DESERET" section, or just hit Control-F and search for that word):
http://unicode.org/cldr/utility/list-unicodeset.jsp?a=%5B%3AChanges_When_Titlecased%3DYes%3A%5D
Though to be honest, this isn't a huge benefit since it is doubtful that anyone is actually using any of the Supplementary Characters that can be title-cased. Either way, here is the SQLCLR code:
using System.Data.SqlTypes;
using System.Globalization;
using Microsoft.SqlServer.Server;
public class TitleCasing
{
[return: SqlFacet(MaxSize = 4000)]
[Microsoft.SqlServer.Server.SqlFunction(IsDeterministic = true, IsPrecise = true)]
public static SqlString TitleCase([SqlFacet(MaxSize = 4000)] SqlString InputString)
{
TextInfo _TxtInf = new CultureInfo(InputString.LCID).TextInfo;
return new SqlString (_TxtInf.ToTitleCase(InputString.Value));
}
}
Here is @MikaelEriksson's suggestion -- modified slightly to handle NVARCHAR
data as well as skip words that are all upper-case (to more closely match the behavior of the .NET method) -- along with a test of that T-SQL implementation and of the SQLCLR implementation:
SET NOCOUNT ON;
DECLARE @a NVARCHAR(50);
SET @a = N'qWeRtY kEyBoArD TEST<>&''"X one&TWO '
+ NCHAR(0xD801)+NCHAR(0xDC28)
+ N'pPLe '
+ NCHAR(0x24D0) -- ⓐ Circled "a"
+ NCHAR(0xFF24) -- D Full-width "D"
+ N'D u'
+ NCHAR(0x0308) -- ̈ (combining diaeresis / umlaut)
+ N'vU'
+ NCHAR(0x0308) -- ̈ (combining diaeresis / umlaut)
+ N'lA';
SELECT @a AS [Original];
SELECT STUFF((
SELECT N' '
+ IIF(UPPER(T3.V) <> T3.V COLLATE Latin1_General_100_BIN2,
UPPER(LEFT(T3.V COLLATE Latin1_General_100_CI_AS_SC, 1))
+ LOWER(STUFF(T3.V COLLATE Latin1_General_100_CI_AS_SC, 1, 1, N'')),
T3.V)
FROM (SELECT CAST(REPLACE((SELECT @a AS N'*' FOR XML PATH('')), N' ', N'<X/>')
AS XML).query('.')) AS T1(X)
CROSS APPLY T1.X.nodes('text()') AS T2(X)
CROSS APPLY (SELECT T2.X.value('.', 'NVARCHAR(70)')) AS T3(V)
FOR XML PATH(''), TYPE
).value('text()[1]', 'NVARCHAR(70)') COLLATE Latin1_General_100_CI_AS_SC, 1, 1, N'')
AS [Capitalize first letter only];
SELECT dbo.TitleCase(@a) AS [ToTitleCase];
Another difference in behavior is that this particular T-SQL implementation splits on only spaces, whereas the ToTitleCase()
method considers most non-letters to be word separators (hence the difference in handling of the "one&TWO" part).
Both implementations handle combining sequences correctly. Each of the accented letters in "üvÜlA" are comprised of a base letter and a combining diaeresis / umlaut (the two dots above each letter), and they are correctly converted to the other case in both tests.
Finally, one unexpected disadvantage to the SQLCLR version is that in coming up with various tests, I found a bug in the .NET code related to its handling of the Circled Letters (which has now been reported on Microsoft Connect — UPDATE: Connect has been moved to /dev/null
-- literally -- so I might need to resubmit this if the problem still exists). The .NET library treats the Circled Letters as word separators, which is why it does not turn the "ⓐDD" into "Ⓐdd" as it should.
FYI
A pre-done SQLCLR function encapsulating the TextInfo.ToTitleCase
method mentioned above is now available in the Free version of SQL# (which I wrote) as String_ToTitleCase and String_ToTitleCase4k.
😺
Should be way up there.
– Nelz
Jul 27 '17 at 9:51
add a comment |
As an alternative to Mikael Eriksson's answer, you could consider using the proprietary T-SQL handling of variable setting in multi-row select statements.
In SQL Server, when a variable is being set as part of a SELECT statement, each row will execute an iteration of the set logic.
Folks often use this method for concatenating strings, though it's unsupported and there are some officially documented issues with it. The official problem relates to particular ORDER BY characteristics, and we don't need that here, so perhaps it's a safe option.
Here, we iterate over the 26 letters of the alphabet and replace them with an upper case version if they are preceded by a space. (We prep the string initially by capitalizing the first letter and making the rest lower case, as you did in your question.)
The SQL is a little complex because it requires the use of a Tally Table-- a table of numbers-- to generate the 26 iterations of replacing that it's doing. You can make a handy inline table-valued user defined function (TVF) to produce that table of numbers or you could even use a physical table.
A drawback of this option is that it can't be part of an inline TVF as it needs to involve setting a variable. So if you wanted to apply this method to a column of your output, you would need to wrap it into a multi-statement TVF or a scalar user defined function.
However, its query plan is much simpler and it is probably significantly faster than the XML method. You could argue it's easier to understand, too (especially if you have your own tally table).
DECLARE
@a VARCHAR(15) = 'qWeRtY kEyBoArD';
SELECT
@a = UPPER(LEFT(@a,1)) + LOWER(SUBSTRING(@a,2,LEN(@a)));
WITH TallyTableBase AS
(
SELECT
0 AS n
FROM (VALUES(0),(0),(0),(0),(0),(0),(0),(0),(0),(0)) AS t(n)
)
SELECT
@a = REPLACE(@a, ' ' + CHAR(n.n), ' ' + CHAR(n.n))
FROM (
SELECT TOP 26 ROW_NUMBER() OVER (ORDER BY (SELECT 1)) + 64 AS n
FROM TallyTableBase a
CROSS JOIN TallyTableBase b
) AS n;
SELECT
@a AS [NewValue];
(I tested this using a much larger string and it was about 6ms vs 14ms for the XML solution.)
There are a number of additional limitations with this solution. As written, it assumes a case insensitive collation, though you could eliminate that issue by specifying a collation or running LCASE on the search term, at the cost of some performance. It also only addresses standard ASCII letters and relies on their placement in the character set, so it would do nothing with ñ.
add a comment |
Assuming you are only looking to capitalize words following a space, here is an another way you could do it.
DECLARE @String VARCHAR(1000)
SET @String = 'qWeRtY kEyBoArD tEst'
/*
Set the string to all lower case and
add a space at the beginning to ensure
the first letter gets capitalized
in the CTE
*/
SET @String = LOWER(' ' + @String)
/*
Use a Tally "Table" as a means of
replacing the letter after the space
with the capitalize version of the
letter
*/
;WITH TallyTable
AS
(
SELECT TOP 1000 ROW_NUMBER() OVER (ORDER BY (SELECT NULL)) as N
FROM master.sys.all_columns a CROSS JOIN master.sys.all_columns b
)
SELECT @String = REPLACE(@String,SUBSTRING(@String,CHARINDEX(' ',@String,N), 2),UPPER(SUBSTRING(@String,CHARINDEX(' ',@String,N), 2)))
FROM TallyTable
WHERE CHARINDEX(' ',@String,N) <> 0
--Remove the space added to the beginning of the string earlier
SET @String = RIGHT(@String,LEN(@String) - 1)
add a comment |
Might not be bullet-proof but I hope it's a helpful contribution to this thread.
DECLARE @t VARCHAR(50) = 'the quick brown fox jumps over the lazy dog', @i INT = 0
DECLARE @chk VARCHAR(1)
WHILE @i <= LEN(@t)
BEGIN
SELECT @chk=SUBSTRING(@t,@i,1)
IF @chk = CHAR(32)
BEGIN
SET @t = STUFF(@t,@i+1,1,UPPER(SUBSTRING(@t,@i+1,1)))
END
SET @i=@i+1
END
PRINT @t
add a comment |
Below is the procedure I used in a Firebird database to do this.
Probably can be cleaned up a lot but it got the job done for me.
set term ~;
Create Procedure EachWordCap
As
Declare Variable lcaption varchar(33);
Declare Variable lcurrentpos integer;
Declare Variable lstringlen integer;
begin
for select ' ' || trim(lower(imagedata.imagename)) from imagedata
where imagedata.imagename is not null and imagedata.imagename != ''
into :lcaption
do
begin
lcurrentpos = 0;
lstringlen = char_length(lcaption);
while (lcurrentpos != 1) do
begin
lcurrentpos = position(' ', lcaption, iif(lcurrentpos = 0, 1,lcurrentpos)) + 1 ;
lcaption = left(lcaption,lcurrentpos - 1) || upper(substring(lcaption from lcurrentpos for 1)) || right(lcaption,lstringlen - lcurrentpos);
end
--Put what you want to do with the text in here
end
end~
set term ;~
add a comment |
Recursive CTEs are quite good for this sort of thing.
Probably not particularly efficient for large operations, but does allow for this kind of operation in a pure SQL select statement:
declare @a varchar(100)
set @a = 'tHe qUiCk bRoWn FOX jumps OvEr The lAZy dOG';
WITH [CTE] AS (
SELECT CAST(upper(Left(@a,1)) + lower(substring(@a,2,len(@a))) AS VARCHAR(100)) AS TEXT,
CHARINDEX(' ',@a) AS NEXT_SPACE
UNION ALL
SELECT CAST(Left(TEXT,NEXT_SPACE) + upper(SubString(TEXT,NEXT_SPACE+1,1)) + SubString(TEXT,NEXT_SPACE+2,1000) AS VARCHAR(100)),
CHARINDEX(' ',TEXT, NEXT_SPACE+1)
FROM [CTE]
WHERE NEXT_SPACE <> 0
)
SELECT TEXT
FROM [CTE]
WHERE NEXT_SPACE = 0
Output:
The Quick Brown Fox Jumps Over The Lazy Dog
add a comment |
I like this version. It is simple, and can be used to create a function, you just have to have the right version of SQL Server:
WITH words
AS (
SELECT upper(left(Value, 1)) + lower(substring(Value, 2, len(Value))) AS word
FROM STRING_SPLIT('Lorem ipsum dolor sit amet.', ' ')
)
SELECT STRING_AGG(words.word, ' ')
FROM words
New contributor
Which one is the right version?
– dezso
3 hours ago
add a comment |
Test Data
declare @word varchar(100)
with good as (select 'good' as a union select 'nice' union select 'fine')
select @word = (SELECT TOP 1 a FROM good ORDER BY NEWID())
Implementation
select substring(Upper(@word),1,1) + substring(@word, 2, LEN(@word))
Capitalizing words which are already separate is easy. I believe the OP is interested in how to identify words within a string, and capitalize each of them.
– Jon of All Trades
Feb 26 '18 at 14:36
add a comment |
Your Answer
StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "182"
};
initTagRenderer("".split(" "), "".split(" "), channelOptions);
StackExchange.using("externalEditor", function() {
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled) {
StackExchange.using("snippets", function() {
createEditor();
});
}
else {
createEditor();
}
});
function createEditor() {
StackExchange.prepareEditor({
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: false,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: null,
bindNavPrevention: true,
postfix: "",
imageUploader: {
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
},
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
});
}
});
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fdba.stackexchange.com%2fquestions%2f139382%2fcapitalize-only-the-first-letter-of-each-word-of-each-sentence-in-sql-server%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
11 Answers
11
active
oldest
votes
11 Answers
11
active
oldest
votes
active
oldest
votes
active
oldest
votes
declare @a varchar(30);
set @a = 'qWeRtY kEyBoArD TEST<>&''"X';
select stuff((
select ' '+upper(left(T3.V, 1))+lower(stuff(T3.V, 1, 1, ''))
from (select cast(replace((select @a as '*' for xml path('')), ' ', '<X/>') as xml).query('.')) as T1(X)
cross apply T1.X.nodes('text()') as T2(X)
cross apply (select T2.X.value('.', 'varchar(30)')) as T3(V)
for xml path(''), type
).value('text()[1]', 'varchar(30)'), 1, 1, '') as [Capitalize first letter only];
This first converts the string to XML by replacing all spaces with the empty tag <X/>
. Then it shreds the XML to get one word per row using nodes()
. To get the rows back to one value it uses the for xml path
trick.
8
And that code is exactly why I would never do that in SQL. Not saying the answer is wrong - this was asked for. But standard SQL is ridiculously ill suited for this type of string manipulation. A CLR based function would work, or just doing it on the presentation layer.
– TomTom
May 24 '16 at 16:20
8
@TomTom It looks complicated but that is nothing compared to the query plan it produces and it will not be fast by any standard. It is however educational and fun to dig in to what is actually going on in the query and why it is written the way it is. The problem could be solved with a string split function (number table). Hard to avoid thefor xml path
trick for concatenation. Unless you go for CLR which would be the best option if speed and efficiency is important.
– Mikael Eriksson
May 24 '16 at 17:14
1
@MikaelEriksson Well done! I modified this code slightly and used it in my answer to compare against a SQLCLR implementation (only compared functionality, not performance): dba.stackexchange.com/a/142435/30859
– Solomon Rutzky
Jun 28 '16 at 7:16
add a comment |
declare @a varchar(30);
set @a = 'qWeRtY kEyBoArD TEST<>&''"X';
select stuff((
select ' '+upper(left(T3.V, 1))+lower(stuff(T3.V, 1, 1, ''))
from (select cast(replace((select @a as '*' for xml path('')), ' ', '<X/>') as xml).query('.')) as T1(X)
cross apply T1.X.nodes('text()') as T2(X)
cross apply (select T2.X.value('.', 'varchar(30)')) as T3(V)
for xml path(''), type
).value('text()[1]', 'varchar(30)'), 1, 1, '') as [Capitalize first letter only];
This first converts the string to XML by replacing all spaces with the empty tag <X/>
. Then it shreds the XML to get one word per row using nodes()
. To get the rows back to one value it uses the for xml path
trick.
8
And that code is exactly why I would never do that in SQL. Not saying the answer is wrong - this was asked for. But standard SQL is ridiculously ill suited for this type of string manipulation. A CLR based function would work, or just doing it on the presentation layer.
– TomTom
May 24 '16 at 16:20
8
@TomTom It looks complicated but that is nothing compared to the query plan it produces and it will not be fast by any standard. It is however educational and fun to dig in to what is actually going on in the query and why it is written the way it is. The problem could be solved with a string split function (number table). Hard to avoid thefor xml path
trick for concatenation. Unless you go for CLR which would be the best option if speed and efficiency is important.
– Mikael Eriksson
May 24 '16 at 17:14
1
@MikaelEriksson Well done! I modified this code slightly and used it in my answer to compare against a SQLCLR implementation (only compared functionality, not performance): dba.stackexchange.com/a/142435/30859
– Solomon Rutzky
Jun 28 '16 at 7:16
add a comment |
declare @a varchar(30);
set @a = 'qWeRtY kEyBoArD TEST<>&''"X';
select stuff((
select ' '+upper(left(T3.V, 1))+lower(stuff(T3.V, 1, 1, ''))
from (select cast(replace((select @a as '*' for xml path('')), ' ', '<X/>') as xml).query('.')) as T1(X)
cross apply T1.X.nodes('text()') as T2(X)
cross apply (select T2.X.value('.', 'varchar(30)')) as T3(V)
for xml path(''), type
).value('text()[1]', 'varchar(30)'), 1, 1, '') as [Capitalize first letter only];
This first converts the string to XML by replacing all spaces with the empty tag <X/>
. Then it shreds the XML to get one word per row using nodes()
. To get the rows back to one value it uses the for xml path
trick.
declare @a varchar(30);
set @a = 'qWeRtY kEyBoArD TEST<>&''"X';
select stuff((
select ' '+upper(left(T3.V, 1))+lower(stuff(T3.V, 1, 1, ''))
from (select cast(replace((select @a as '*' for xml path('')), ' ', '<X/>') as xml).query('.')) as T1(X)
cross apply T1.X.nodes('text()') as T2(X)
cross apply (select T2.X.value('.', 'varchar(30)')) as T3(V)
for xml path(''), type
).value('text()[1]', 'varchar(30)'), 1, 1, '') as [Capitalize first letter only];
This first converts the string to XML by replacing all spaces with the empty tag <X/>
. Then it shreds the XML to get one word per row using nodes()
. To get the rows back to one value it uses the for xml path
trick.
edited May 25 '16 at 5:33
answered May 24 '16 at 15:50
Mikael ErikssonMikael Eriksson
17.8k34685
17.8k34685
8
And that code is exactly why I would never do that in SQL. Not saying the answer is wrong - this was asked for. But standard SQL is ridiculously ill suited for this type of string manipulation. A CLR based function would work, or just doing it on the presentation layer.
– TomTom
May 24 '16 at 16:20
8
@TomTom It looks complicated but that is nothing compared to the query plan it produces and it will not be fast by any standard. It is however educational and fun to dig in to what is actually going on in the query and why it is written the way it is. The problem could be solved with a string split function (number table). Hard to avoid thefor xml path
trick for concatenation. Unless you go for CLR which would be the best option if speed and efficiency is important.
– Mikael Eriksson
May 24 '16 at 17:14
1
@MikaelEriksson Well done! I modified this code slightly and used it in my answer to compare against a SQLCLR implementation (only compared functionality, not performance): dba.stackexchange.com/a/142435/30859
– Solomon Rutzky
Jun 28 '16 at 7:16
add a comment |
8
And that code is exactly why I would never do that in SQL. Not saying the answer is wrong - this was asked for. But standard SQL is ridiculously ill suited for this type of string manipulation. A CLR based function would work, or just doing it on the presentation layer.
– TomTom
May 24 '16 at 16:20
8
@TomTom It looks complicated but that is nothing compared to the query plan it produces and it will not be fast by any standard. It is however educational and fun to dig in to what is actually going on in the query and why it is written the way it is. The problem could be solved with a string split function (number table). Hard to avoid thefor xml path
trick for concatenation. Unless you go for CLR which would be the best option if speed and efficiency is important.
– Mikael Eriksson
May 24 '16 at 17:14
1
@MikaelEriksson Well done! I modified this code slightly and used it in my answer to compare against a SQLCLR implementation (only compared functionality, not performance): dba.stackexchange.com/a/142435/30859
– Solomon Rutzky
Jun 28 '16 at 7:16
8
8
And that code is exactly why I would never do that in SQL. Not saying the answer is wrong - this was asked for. But standard SQL is ridiculously ill suited for this type of string manipulation. A CLR based function would work, or just doing it on the presentation layer.
– TomTom
May 24 '16 at 16:20
And that code is exactly why I would never do that in SQL. Not saying the answer is wrong - this was asked for. But standard SQL is ridiculously ill suited for this type of string manipulation. A CLR based function would work, or just doing it on the presentation layer.
– TomTom
May 24 '16 at 16:20
8
8
@TomTom It looks complicated but that is nothing compared to the query plan it produces and it will not be fast by any standard. It is however educational and fun to dig in to what is actually going on in the query and why it is written the way it is. The problem could be solved with a string split function (number table). Hard to avoid the
for xml path
trick for concatenation. Unless you go for CLR which would be the best option if speed and efficiency is important.– Mikael Eriksson
May 24 '16 at 17:14
@TomTom It looks complicated but that is nothing compared to the query plan it produces and it will not be fast by any standard. It is however educational and fun to dig in to what is actually going on in the query and why it is written the way it is. The problem could be solved with a string split function (number table). Hard to avoid the
for xml path
trick for concatenation. Unless you go for CLR which would be the best option if speed and efficiency is important.– Mikael Eriksson
May 24 '16 at 17:14
1
1
@MikaelEriksson Well done! I modified this code slightly and used it in my answer to compare against a SQLCLR implementation (only compared functionality, not performance): dba.stackexchange.com/a/142435/30859
– Solomon Rutzky
Jun 28 '16 at 7:16
@MikaelEriksson Well done! I modified this code slightly and used it in my answer to compare against a SQLCLR implementation (only compared functionality, not performance): dba.stackexchange.com/a/142435/30859
– Solomon Rutzky
Jun 28 '16 at 7:16
add a comment |
In SQL Server 2016 you can do this with R, eg
-- R capitalisation code stolen from here:
-- http://stackoverflow.com/questions/6364783/capitalize-the-first-letter-of-both-words-in-a-two-word-string
EXEC sp_execute_external_script
@language = N'R',
@script = N'
simpleCap <- function(x) {
s <- strsplit(x, " ")[[1]]
paste(toupper(substring(s, 1,1)), substring(s, 2),
sep="", collapse=" ")
}
OutputDataSet <- as.data.frame((sapply(as.vector(InputDataSet$xtext), simpleCap)))',
@input_data_1 = N'SELECT LOWER(testString) xtext FROM dbo.testStrings'
WITH RESULT SETS ( ( properCase VARCHAR(50) NOT NULL ) );
Whether you should or not is a different question : )
add a comment |
In SQL Server 2016 you can do this with R, eg
-- R capitalisation code stolen from here:
-- http://stackoverflow.com/questions/6364783/capitalize-the-first-letter-of-both-words-in-a-two-word-string
EXEC sp_execute_external_script
@language = N'R',
@script = N'
simpleCap <- function(x) {
s <- strsplit(x, " ")[[1]]
paste(toupper(substring(s, 1,1)), substring(s, 2),
sep="", collapse=" ")
}
OutputDataSet <- as.data.frame((sapply(as.vector(InputDataSet$xtext), simpleCap)))',
@input_data_1 = N'SELECT LOWER(testString) xtext FROM dbo.testStrings'
WITH RESULT SETS ( ( properCase VARCHAR(50) NOT NULL ) );
Whether you should or not is a different question : )
add a comment |
In SQL Server 2016 you can do this with R, eg
-- R capitalisation code stolen from here:
-- http://stackoverflow.com/questions/6364783/capitalize-the-first-letter-of-both-words-in-a-two-word-string
EXEC sp_execute_external_script
@language = N'R',
@script = N'
simpleCap <- function(x) {
s <- strsplit(x, " ")[[1]]
paste(toupper(substring(s, 1,1)), substring(s, 2),
sep="", collapse=" ")
}
OutputDataSet <- as.data.frame((sapply(as.vector(InputDataSet$xtext), simpleCap)))',
@input_data_1 = N'SELECT LOWER(testString) xtext FROM dbo.testStrings'
WITH RESULT SETS ( ( properCase VARCHAR(50) NOT NULL ) );
Whether you should or not is a different question : )
In SQL Server 2016 you can do this with R, eg
-- R capitalisation code stolen from here:
-- http://stackoverflow.com/questions/6364783/capitalize-the-first-letter-of-both-words-in-a-two-word-string
EXEC sp_execute_external_script
@language = N'R',
@script = N'
simpleCap <- function(x) {
s <- strsplit(x, " ")[[1]]
paste(toupper(substring(s, 1,1)), substring(s, 2),
sep="", collapse=" ")
}
OutputDataSet <- as.data.frame((sapply(as.vector(InputDataSet$xtext), simpleCap)))',
@input_data_1 = N'SELECT LOWER(testString) xtext FROM dbo.testStrings'
WITH RESULT SETS ( ( properCase VARCHAR(50) NOT NULL ) );
Whether you should or not is a different question : )
answered May 25 '16 at 15:37
wBobwBob
9,53221738
9,53221738
add a comment |
add a comment |
Maybe I'm being silly but checking the below query I've written against some of the provided, this seems to be a bit more efficient (depending on indexing).
The code is a bit stupid, but isn't there a saying that if it looks stupid but it works then it's not stupid.
Begin
Declare @text Varchar(30);
Set @text = 'qWeRtY kEyBoArD TEST<>&''"X';
Declare @1 Varchar(2)= ' a'
, @2 Varchar(2)= ' b'
, @3 Varchar(2)= ' c'
, @4 Varchar(2)= ' d'
, @5 Varchar(2)= ' e'
, @6 Varchar(2)= ' f'
, @7 Varchar(2)= ' g'
, @8 Varchar(2)= ' h'
, @9 Varchar(2)= ' i'
, @10 Varchar(2)= ' j'
, @11 Varchar(2)= ' k'
, @12 Varchar(2)= ' l'
, @13 Varchar(2)= ' m'
, @14 Varchar(2)= ' n'
, @15 Varchar(2)= ' o'
, @16 Varchar(2)= ' p'
, @17 Varchar(2)= ' q'
, @18 Varchar(2)= ' r'
, @19 Varchar(2)= ' s'
, @20 Varchar(2)= ' t'
, @21 Varchar(2)= ' u'
, @22 Varchar(2)= ' v'
, @23 Varchar(2)= ' w'
, @24 Varchar(2)= ' x'
, @25 Varchar(2)= ' y'
, @26 Varchar(2)= ' z';
Set @text=' '+@text
Select LTrim(Replace(Replace(Replace(Replace(Replace(Replace(Replace(Replace(Replace(Replace(Replace(Replace(Replace(Replace(Replace(Replace(Replace(Replace(Replace(Replace(Replace(Replace(Replace(Replace(Replace(Replace(Lower(@text) ,
@1 , Upper(@1)) ,
@2 , Upper(@2)) ,
@3 , Upper(@3)) ,
@4 , Upper(@4)) ,
@5 , Upper(@5)) ,
@6 , Upper(@6)) ,
@7 , Upper(@7)) ,
@8 , Upper(@8)) ,
@9 , Upper(@9)) ,
@10 , Upper(@10)) ,
@11 , Upper(@11)) ,
@12 , Upper(@12)) ,
@13 , Upper(@13)) ,
@14 , Upper(@14)) ,
@15 , Upper(@15)) ,
@16 , Upper(@16)) ,
@17 , Upper(@17)) ,
@18 , Upper(@18)) ,
@19 , Upper(@19)) ,
@20 , Upper(@20)) ,
@21 , Upper(@21)) ,
@22 , Upper(@22)) , @23 ,
Upper(@23)) , @24 , Upper(@24)) ,
@25 , Upper(@25)) , @26 , Upper(@26)));
end
2
This is a great, and horrible, answer. I particularly like the space you've tacked on at the beginning and then strip off at the end.
– BradC
Jun 14 '16 at 17:03
2
@BradC it is hideous, but when I've tried it compared to XML method against a data set it seems to run at a fraction of the cost!
– Chris J
Jun 14 '16 at 18:31
Haha! Beautiful! +1
– Nelz
Jul 27 '17 at 9:50
add a comment |
Maybe I'm being silly but checking the below query I've written against some of the provided, this seems to be a bit more efficient (depending on indexing).
The code is a bit stupid, but isn't there a saying that if it looks stupid but it works then it's not stupid.
Begin
Declare @text Varchar(30);
Set @text = 'qWeRtY kEyBoArD TEST<>&''"X';
Declare @1 Varchar(2)= ' a'
, @2 Varchar(2)= ' b'
, @3 Varchar(2)= ' c'
, @4 Varchar(2)= ' d'
, @5 Varchar(2)= ' e'
, @6 Varchar(2)= ' f'
, @7 Varchar(2)= ' g'
, @8 Varchar(2)= ' h'
, @9 Varchar(2)= ' i'
, @10 Varchar(2)= ' j'
, @11 Varchar(2)= ' k'
, @12 Varchar(2)= ' l'
, @13 Varchar(2)= ' m'
, @14 Varchar(2)= ' n'
, @15 Varchar(2)= ' o'
, @16 Varchar(2)= ' p'
, @17 Varchar(2)= ' q'
, @18 Varchar(2)= ' r'
, @19 Varchar(2)= ' s'
, @20 Varchar(2)= ' t'
, @21 Varchar(2)= ' u'
, @22 Varchar(2)= ' v'
, @23 Varchar(2)= ' w'
, @24 Varchar(2)= ' x'
, @25 Varchar(2)= ' y'
, @26 Varchar(2)= ' z';
Set @text=' '+@text
Select LTrim(Replace(Replace(Replace(Replace(Replace(Replace(Replace(Replace(Replace(Replace(Replace(Replace(Replace(Replace(Replace(Replace(Replace(Replace(Replace(Replace(Replace(Replace(Replace(Replace(Replace(Replace(Lower(@text) ,
@1 , Upper(@1)) ,
@2 , Upper(@2)) ,
@3 , Upper(@3)) ,
@4 , Upper(@4)) ,
@5 , Upper(@5)) ,
@6 , Upper(@6)) ,
@7 , Upper(@7)) ,
@8 , Upper(@8)) ,
@9 , Upper(@9)) ,
@10 , Upper(@10)) ,
@11 , Upper(@11)) ,
@12 , Upper(@12)) ,
@13 , Upper(@13)) ,
@14 , Upper(@14)) ,
@15 , Upper(@15)) ,
@16 , Upper(@16)) ,
@17 , Upper(@17)) ,
@18 , Upper(@18)) ,
@19 , Upper(@19)) ,
@20 , Upper(@20)) ,
@21 , Upper(@21)) ,
@22 , Upper(@22)) , @23 ,
Upper(@23)) , @24 , Upper(@24)) ,
@25 , Upper(@25)) , @26 , Upper(@26)));
end
2
This is a great, and horrible, answer. I particularly like the space you've tacked on at the beginning and then strip off at the end.
– BradC
Jun 14 '16 at 17:03
2
@BradC it is hideous, but when I've tried it compared to XML method against a data set it seems to run at a fraction of the cost!
– Chris J
Jun 14 '16 at 18:31
Haha! Beautiful! +1
– Nelz
Jul 27 '17 at 9:50
add a comment |
Maybe I'm being silly but checking the below query I've written against some of the provided, this seems to be a bit more efficient (depending on indexing).
The code is a bit stupid, but isn't there a saying that if it looks stupid but it works then it's not stupid.
Begin
Declare @text Varchar(30);
Set @text = 'qWeRtY kEyBoArD TEST<>&''"X';
Declare @1 Varchar(2)= ' a'
, @2 Varchar(2)= ' b'
, @3 Varchar(2)= ' c'
, @4 Varchar(2)= ' d'
, @5 Varchar(2)= ' e'
, @6 Varchar(2)= ' f'
, @7 Varchar(2)= ' g'
, @8 Varchar(2)= ' h'
, @9 Varchar(2)= ' i'
, @10 Varchar(2)= ' j'
, @11 Varchar(2)= ' k'
, @12 Varchar(2)= ' l'
, @13 Varchar(2)= ' m'
, @14 Varchar(2)= ' n'
, @15 Varchar(2)= ' o'
, @16 Varchar(2)= ' p'
, @17 Varchar(2)= ' q'
, @18 Varchar(2)= ' r'
, @19 Varchar(2)= ' s'
, @20 Varchar(2)= ' t'
, @21 Varchar(2)= ' u'
, @22 Varchar(2)= ' v'
, @23 Varchar(2)= ' w'
, @24 Varchar(2)= ' x'
, @25 Varchar(2)= ' y'
, @26 Varchar(2)= ' z';
Set @text=' '+@text
Select LTrim(Replace(Replace(Replace(Replace(Replace(Replace(Replace(Replace(Replace(Replace(Replace(Replace(Replace(Replace(Replace(Replace(Replace(Replace(Replace(Replace(Replace(Replace(Replace(Replace(Replace(Replace(Lower(@text) ,
@1 , Upper(@1)) ,
@2 , Upper(@2)) ,
@3 , Upper(@3)) ,
@4 , Upper(@4)) ,
@5 , Upper(@5)) ,
@6 , Upper(@6)) ,
@7 , Upper(@7)) ,
@8 , Upper(@8)) ,
@9 , Upper(@9)) ,
@10 , Upper(@10)) ,
@11 , Upper(@11)) ,
@12 , Upper(@12)) ,
@13 , Upper(@13)) ,
@14 , Upper(@14)) ,
@15 , Upper(@15)) ,
@16 , Upper(@16)) ,
@17 , Upper(@17)) ,
@18 , Upper(@18)) ,
@19 , Upper(@19)) ,
@20 , Upper(@20)) ,
@21 , Upper(@21)) ,
@22 , Upper(@22)) , @23 ,
Upper(@23)) , @24 , Upper(@24)) ,
@25 , Upper(@25)) , @26 , Upper(@26)));
end
Maybe I'm being silly but checking the below query I've written against some of the provided, this seems to be a bit more efficient (depending on indexing).
The code is a bit stupid, but isn't there a saying that if it looks stupid but it works then it's not stupid.
Begin
Declare @text Varchar(30);
Set @text = 'qWeRtY kEyBoArD TEST<>&''"X';
Declare @1 Varchar(2)= ' a'
, @2 Varchar(2)= ' b'
, @3 Varchar(2)= ' c'
, @4 Varchar(2)= ' d'
, @5 Varchar(2)= ' e'
, @6 Varchar(2)= ' f'
, @7 Varchar(2)= ' g'
, @8 Varchar(2)= ' h'
, @9 Varchar(2)= ' i'
, @10 Varchar(2)= ' j'
, @11 Varchar(2)= ' k'
, @12 Varchar(2)= ' l'
, @13 Varchar(2)= ' m'
, @14 Varchar(2)= ' n'
, @15 Varchar(2)= ' o'
, @16 Varchar(2)= ' p'
, @17 Varchar(2)= ' q'
, @18 Varchar(2)= ' r'
, @19 Varchar(2)= ' s'
, @20 Varchar(2)= ' t'
, @21 Varchar(2)= ' u'
, @22 Varchar(2)= ' v'
, @23 Varchar(2)= ' w'
, @24 Varchar(2)= ' x'
, @25 Varchar(2)= ' y'
, @26 Varchar(2)= ' z';
Set @text=' '+@text
Select LTrim(Replace(Replace(Replace(Replace(Replace(Replace(Replace(Replace(Replace(Replace(Replace(Replace(Replace(Replace(Replace(Replace(Replace(Replace(Replace(Replace(Replace(Replace(Replace(Replace(Replace(Replace(Lower(@text) ,
@1 , Upper(@1)) ,
@2 , Upper(@2)) ,
@3 , Upper(@3)) ,
@4 , Upper(@4)) ,
@5 , Upper(@5)) ,
@6 , Upper(@6)) ,
@7 , Upper(@7)) ,
@8 , Upper(@8)) ,
@9 , Upper(@9)) ,
@10 , Upper(@10)) ,
@11 , Upper(@11)) ,
@12 , Upper(@12)) ,
@13 , Upper(@13)) ,
@14 , Upper(@14)) ,
@15 , Upper(@15)) ,
@16 , Upper(@16)) ,
@17 , Upper(@17)) ,
@18 , Upper(@18)) ,
@19 , Upper(@19)) ,
@20 , Upper(@20)) ,
@21 , Upper(@21)) ,
@22 , Upper(@22)) , @23 ,
Upper(@23)) , @24 , Upper(@24)) ,
@25 , Upper(@25)) , @26 , Upper(@26)));
end
answered Jun 14 '16 at 13:54
Chris JChris J
22912
22912
2
This is a great, and horrible, answer. I particularly like the space you've tacked on at the beginning and then strip off at the end.
– BradC
Jun 14 '16 at 17:03
2
@BradC it is hideous, but when I've tried it compared to XML method against a data set it seems to run at a fraction of the cost!
– Chris J
Jun 14 '16 at 18:31
Haha! Beautiful! +1
– Nelz
Jul 27 '17 at 9:50
add a comment |
2
This is a great, and horrible, answer. I particularly like the space you've tacked on at the beginning and then strip off at the end.
– BradC
Jun 14 '16 at 17:03
2
@BradC it is hideous, but when I've tried it compared to XML method against a data set it seems to run at a fraction of the cost!
– Chris J
Jun 14 '16 at 18:31
Haha! Beautiful! +1
– Nelz
Jul 27 '17 at 9:50
2
2
This is a great, and horrible, answer. I particularly like the space you've tacked on at the beginning and then strip off at the end.
– BradC
Jun 14 '16 at 17:03
This is a great, and horrible, answer. I particularly like the space you've tacked on at the beginning and then strip off at the end.
– BradC
Jun 14 '16 at 17:03
2
2
@BradC it is hideous, but when I've tried it compared to XML method against a data set it seems to run at a fraction of the cost!
– Chris J
Jun 14 '16 at 18:31
@BradC it is hideous, but when I've tried it compared to XML method against a data set it seems to run at a fraction of the cost!
– Chris J
Jun 14 '16 at 18:31
Haha! Beautiful! +1
– Nelz
Jul 27 '17 at 9:50
Haha! Beautiful! +1
– Nelz
Jul 27 '17 at 9:50
add a comment |
Another option is to handle this via SQLCLR. There is even a method already available in .NET that does this: TextInfo.ToTitleCase (in System.Globalization
). This method will Upper-Case the first letter of each word, and Lower-Case the remaining letters. Unlike the other proposals here, it also skips words that are in all upper-case, assuming them to be acronyms. Of course, if this behavior is desired, it would be easy enough to update any of the T-SQL suggestions to do this as well.
One benefit of the .NET method is that it can Upper-Case letters that are Supplementary Characters. For example: DESERET SMALL LETTER OW has an upper-case mapping of DESERET CAPITAL LETTER OW (both show up as boxes when I paste them into here), but the UPPER()
function does not change the lower-case version to upper-case, even when the default Collation for the current Database is set to Latin1_General_100_CI_AS_SC
. This seems consistent with the MSDN documentation which does not list UPPER
and LOWER
in the chart of functions that behave differently when using an _SC
Collation: Collation and Unicode Support: Supplementary Characters.
SELECT N'DESERET SMALL LETTER OW' AS [Label], NCHAR(0xD801)+NCHAR(0xDC35) AS [Thing]
UNION ALL
SELECT N'DESERET CAPITAL LETTER OW' AS [Label], NCHAR(0xD801)+NCHAR(0xDC0D) AS [Thing]
UNION ALL
SELECT N'SmallButShouldBeCapital' AS [Label], UPPER(NCHAR(0xD801)+NCHAR(0xDC35)) AS [Thing]
Returns (enlarged so you can actually see the Supplementary Character):
You can see the full (and current) list of characters that are lower-case and change to upper-case using the following search feature at Unicode.org (you can see the Supplementary Characters by scrolling down until you get to the "DESERET" section, or just hit Control-F and search for that word):
http://unicode.org/cldr/utility/list-unicodeset.jsp?a=%5B%3AChanges_When_Titlecased%3DYes%3A%5D
Though to be honest, this isn't a huge benefit since it is doubtful that anyone is actually using any of the Supplementary Characters that can be title-cased. Either way, here is the SQLCLR code:
using System.Data.SqlTypes;
using System.Globalization;
using Microsoft.SqlServer.Server;
public class TitleCasing
{
[return: SqlFacet(MaxSize = 4000)]
[Microsoft.SqlServer.Server.SqlFunction(IsDeterministic = true, IsPrecise = true)]
public static SqlString TitleCase([SqlFacet(MaxSize = 4000)] SqlString InputString)
{
TextInfo _TxtInf = new CultureInfo(InputString.LCID).TextInfo;
return new SqlString (_TxtInf.ToTitleCase(InputString.Value));
}
}
Here is @MikaelEriksson's suggestion -- modified slightly to handle NVARCHAR
data as well as skip words that are all upper-case (to more closely match the behavior of the .NET method) -- along with a test of that T-SQL implementation and of the SQLCLR implementation:
SET NOCOUNT ON;
DECLARE @a NVARCHAR(50);
SET @a = N'qWeRtY kEyBoArD TEST<>&''"X one&TWO '
+ NCHAR(0xD801)+NCHAR(0xDC28)
+ N'pPLe '
+ NCHAR(0x24D0) -- ⓐ Circled "a"
+ NCHAR(0xFF24) -- D Full-width "D"
+ N'D u'
+ NCHAR(0x0308) -- ̈ (combining diaeresis / umlaut)
+ N'vU'
+ NCHAR(0x0308) -- ̈ (combining diaeresis / umlaut)
+ N'lA';
SELECT @a AS [Original];
SELECT STUFF((
SELECT N' '
+ IIF(UPPER(T3.V) <> T3.V COLLATE Latin1_General_100_BIN2,
UPPER(LEFT(T3.V COLLATE Latin1_General_100_CI_AS_SC, 1))
+ LOWER(STUFF(T3.V COLLATE Latin1_General_100_CI_AS_SC, 1, 1, N'')),
T3.V)
FROM (SELECT CAST(REPLACE((SELECT @a AS N'*' FOR XML PATH('')), N' ', N'<X/>')
AS XML).query('.')) AS T1(X)
CROSS APPLY T1.X.nodes('text()') AS T2(X)
CROSS APPLY (SELECT T2.X.value('.', 'NVARCHAR(70)')) AS T3(V)
FOR XML PATH(''), TYPE
).value('text()[1]', 'NVARCHAR(70)') COLLATE Latin1_General_100_CI_AS_SC, 1, 1, N'')
AS [Capitalize first letter only];
SELECT dbo.TitleCase(@a) AS [ToTitleCase];
Another difference in behavior is that this particular T-SQL implementation splits on only spaces, whereas the ToTitleCase()
method considers most non-letters to be word separators (hence the difference in handling of the "one&TWO" part).
Both implementations handle combining sequences correctly. Each of the accented letters in "üvÜlA" are comprised of a base letter and a combining diaeresis / umlaut (the two dots above each letter), and they are correctly converted to the other case in both tests.
Finally, one unexpected disadvantage to the SQLCLR version is that in coming up with various tests, I found a bug in the .NET code related to its handling of the Circled Letters (which has now been reported on Microsoft Connect — UPDATE: Connect has been moved to /dev/null
-- literally -- so I might need to resubmit this if the problem still exists). The .NET library treats the Circled Letters as word separators, which is why it does not turn the "ⓐDD" into "Ⓐdd" as it should.
FYI
A pre-done SQLCLR function encapsulating the TextInfo.ToTitleCase
method mentioned above is now available in the Free version of SQL# (which I wrote) as String_ToTitleCase and String_ToTitleCase4k.
😺
Should be way up there.
– Nelz
Jul 27 '17 at 9:51
add a comment |
Another option is to handle this via SQLCLR. There is even a method already available in .NET that does this: TextInfo.ToTitleCase (in System.Globalization
). This method will Upper-Case the first letter of each word, and Lower-Case the remaining letters. Unlike the other proposals here, it also skips words that are in all upper-case, assuming them to be acronyms. Of course, if this behavior is desired, it would be easy enough to update any of the T-SQL suggestions to do this as well.
One benefit of the .NET method is that it can Upper-Case letters that are Supplementary Characters. For example: DESERET SMALL LETTER OW has an upper-case mapping of DESERET CAPITAL LETTER OW (both show up as boxes when I paste them into here), but the UPPER()
function does not change the lower-case version to upper-case, even when the default Collation for the current Database is set to Latin1_General_100_CI_AS_SC
. This seems consistent with the MSDN documentation which does not list UPPER
and LOWER
in the chart of functions that behave differently when using an _SC
Collation: Collation and Unicode Support: Supplementary Characters.
SELECT N'DESERET SMALL LETTER OW' AS [Label], NCHAR(0xD801)+NCHAR(0xDC35) AS [Thing]
UNION ALL
SELECT N'DESERET CAPITAL LETTER OW' AS [Label], NCHAR(0xD801)+NCHAR(0xDC0D) AS [Thing]
UNION ALL
SELECT N'SmallButShouldBeCapital' AS [Label], UPPER(NCHAR(0xD801)+NCHAR(0xDC35)) AS [Thing]
Returns (enlarged so you can actually see the Supplementary Character):
You can see the full (and current) list of characters that are lower-case and change to upper-case using the following search feature at Unicode.org (you can see the Supplementary Characters by scrolling down until you get to the "DESERET" section, or just hit Control-F and search for that word):
http://unicode.org/cldr/utility/list-unicodeset.jsp?a=%5B%3AChanges_When_Titlecased%3DYes%3A%5D
Though to be honest, this isn't a huge benefit since it is doubtful that anyone is actually using any of the Supplementary Characters that can be title-cased. Either way, here is the SQLCLR code:
using System.Data.SqlTypes;
using System.Globalization;
using Microsoft.SqlServer.Server;
public class TitleCasing
{
[return: SqlFacet(MaxSize = 4000)]
[Microsoft.SqlServer.Server.SqlFunction(IsDeterministic = true, IsPrecise = true)]
public static SqlString TitleCase([SqlFacet(MaxSize = 4000)] SqlString InputString)
{
TextInfo _TxtInf = new CultureInfo(InputString.LCID).TextInfo;
return new SqlString (_TxtInf.ToTitleCase(InputString.Value));
}
}
Here is @MikaelEriksson's suggestion -- modified slightly to handle NVARCHAR
data as well as skip words that are all upper-case (to more closely match the behavior of the .NET method) -- along with a test of that T-SQL implementation and of the SQLCLR implementation:
SET NOCOUNT ON;
DECLARE @a NVARCHAR(50);
SET @a = N'qWeRtY kEyBoArD TEST<>&''"X one&TWO '
+ NCHAR(0xD801)+NCHAR(0xDC28)
+ N'pPLe '
+ NCHAR(0x24D0) -- ⓐ Circled "a"
+ NCHAR(0xFF24) -- D Full-width "D"
+ N'D u'
+ NCHAR(0x0308) -- ̈ (combining diaeresis / umlaut)
+ N'vU'
+ NCHAR(0x0308) -- ̈ (combining diaeresis / umlaut)
+ N'lA';
SELECT @a AS [Original];
SELECT STUFF((
SELECT N' '
+ IIF(UPPER(T3.V) <> T3.V COLLATE Latin1_General_100_BIN2,
UPPER(LEFT(T3.V COLLATE Latin1_General_100_CI_AS_SC, 1))
+ LOWER(STUFF(T3.V COLLATE Latin1_General_100_CI_AS_SC, 1, 1, N'')),
T3.V)
FROM (SELECT CAST(REPLACE((SELECT @a AS N'*' FOR XML PATH('')), N' ', N'<X/>')
AS XML).query('.')) AS T1(X)
CROSS APPLY T1.X.nodes('text()') AS T2(X)
CROSS APPLY (SELECT T2.X.value('.', 'NVARCHAR(70)')) AS T3(V)
FOR XML PATH(''), TYPE
).value('text()[1]', 'NVARCHAR(70)') COLLATE Latin1_General_100_CI_AS_SC, 1, 1, N'')
AS [Capitalize first letter only];
SELECT dbo.TitleCase(@a) AS [ToTitleCase];
Another difference in behavior is that this particular T-SQL implementation splits on only spaces, whereas the ToTitleCase()
method considers most non-letters to be word separators (hence the difference in handling of the "one&TWO" part).
Both implementations handle combining sequences correctly. Each of the accented letters in "üvÜlA" are comprised of a base letter and a combining diaeresis / umlaut (the two dots above each letter), and they are correctly converted to the other case in both tests.
Finally, one unexpected disadvantage to the SQLCLR version is that in coming up with various tests, I found a bug in the .NET code related to its handling of the Circled Letters (which has now been reported on Microsoft Connect — UPDATE: Connect has been moved to /dev/null
-- literally -- so I might need to resubmit this if the problem still exists). The .NET library treats the Circled Letters as word separators, which is why it does not turn the "ⓐDD" into "Ⓐdd" as it should.
FYI
A pre-done SQLCLR function encapsulating the TextInfo.ToTitleCase
method mentioned above is now available in the Free version of SQL# (which I wrote) as String_ToTitleCase and String_ToTitleCase4k.
😺
Should be way up there.
– Nelz
Jul 27 '17 at 9:51
add a comment |
Another option is to handle this via SQLCLR. There is even a method already available in .NET that does this: TextInfo.ToTitleCase (in System.Globalization
). This method will Upper-Case the first letter of each word, and Lower-Case the remaining letters. Unlike the other proposals here, it also skips words that are in all upper-case, assuming them to be acronyms. Of course, if this behavior is desired, it would be easy enough to update any of the T-SQL suggestions to do this as well.
One benefit of the .NET method is that it can Upper-Case letters that are Supplementary Characters. For example: DESERET SMALL LETTER OW has an upper-case mapping of DESERET CAPITAL LETTER OW (both show up as boxes when I paste them into here), but the UPPER()
function does not change the lower-case version to upper-case, even when the default Collation for the current Database is set to Latin1_General_100_CI_AS_SC
. This seems consistent with the MSDN documentation which does not list UPPER
and LOWER
in the chart of functions that behave differently when using an _SC
Collation: Collation and Unicode Support: Supplementary Characters.
SELECT N'DESERET SMALL LETTER OW' AS [Label], NCHAR(0xD801)+NCHAR(0xDC35) AS [Thing]
UNION ALL
SELECT N'DESERET CAPITAL LETTER OW' AS [Label], NCHAR(0xD801)+NCHAR(0xDC0D) AS [Thing]
UNION ALL
SELECT N'SmallButShouldBeCapital' AS [Label], UPPER(NCHAR(0xD801)+NCHAR(0xDC35)) AS [Thing]
Returns (enlarged so you can actually see the Supplementary Character):
You can see the full (and current) list of characters that are lower-case and change to upper-case using the following search feature at Unicode.org (you can see the Supplementary Characters by scrolling down until you get to the "DESERET" section, or just hit Control-F and search for that word):
http://unicode.org/cldr/utility/list-unicodeset.jsp?a=%5B%3AChanges_When_Titlecased%3DYes%3A%5D
Though to be honest, this isn't a huge benefit since it is doubtful that anyone is actually using any of the Supplementary Characters that can be title-cased. Either way, here is the SQLCLR code:
using System.Data.SqlTypes;
using System.Globalization;
using Microsoft.SqlServer.Server;
public class TitleCasing
{
[return: SqlFacet(MaxSize = 4000)]
[Microsoft.SqlServer.Server.SqlFunction(IsDeterministic = true, IsPrecise = true)]
public static SqlString TitleCase([SqlFacet(MaxSize = 4000)] SqlString InputString)
{
TextInfo _TxtInf = new CultureInfo(InputString.LCID).TextInfo;
return new SqlString (_TxtInf.ToTitleCase(InputString.Value));
}
}
Here is @MikaelEriksson's suggestion -- modified slightly to handle NVARCHAR
data as well as skip words that are all upper-case (to more closely match the behavior of the .NET method) -- along with a test of that T-SQL implementation and of the SQLCLR implementation:
SET NOCOUNT ON;
DECLARE @a NVARCHAR(50);
SET @a = N'qWeRtY kEyBoArD TEST<>&''"X one&TWO '
+ NCHAR(0xD801)+NCHAR(0xDC28)
+ N'pPLe '
+ NCHAR(0x24D0) -- ⓐ Circled "a"
+ NCHAR(0xFF24) -- D Full-width "D"
+ N'D u'
+ NCHAR(0x0308) -- ̈ (combining diaeresis / umlaut)
+ N'vU'
+ NCHAR(0x0308) -- ̈ (combining diaeresis / umlaut)
+ N'lA';
SELECT @a AS [Original];
SELECT STUFF((
SELECT N' '
+ IIF(UPPER(T3.V) <> T3.V COLLATE Latin1_General_100_BIN2,
UPPER(LEFT(T3.V COLLATE Latin1_General_100_CI_AS_SC, 1))
+ LOWER(STUFF(T3.V COLLATE Latin1_General_100_CI_AS_SC, 1, 1, N'')),
T3.V)
FROM (SELECT CAST(REPLACE((SELECT @a AS N'*' FOR XML PATH('')), N' ', N'<X/>')
AS XML).query('.')) AS T1(X)
CROSS APPLY T1.X.nodes('text()') AS T2(X)
CROSS APPLY (SELECT T2.X.value('.', 'NVARCHAR(70)')) AS T3(V)
FOR XML PATH(''), TYPE
).value('text()[1]', 'NVARCHAR(70)') COLLATE Latin1_General_100_CI_AS_SC, 1, 1, N'')
AS [Capitalize first letter only];
SELECT dbo.TitleCase(@a) AS [ToTitleCase];
Another difference in behavior is that this particular T-SQL implementation splits on only spaces, whereas the ToTitleCase()
method considers most non-letters to be word separators (hence the difference in handling of the "one&TWO" part).
Both implementations handle combining sequences correctly. Each of the accented letters in "üvÜlA" are comprised of a base letter and a combining diaeresis / umlaut (the two dots above each letter), and they are correctly converted to the other case in both tests.
Finally, one unexpected disadvantage to the SQLCLR version is that in coming up with various tests, I found a bug in the .NET code related to its handling of the Circled Letters (which has now been reported on Microsoft Connect — UPDATE: Connect has been moved to /dev/null
-- literally -- so I might need to resubmit this if the problem still exists). The .NET library treats the Circled Letters as word separators, which is why it does not turn the "ⓐDD" into "Ⓐdd" as it should.
FYI
A pre-done SQLCLR function encapsulating the TextInfo.ToTitleCase
method mentioned above is now available in the Free version of SQL# (which I wrote) as String_ToTitleCase and String_ToTitleCase4k.
😺
Another option is to handle this via SQLCLR. There is even a method already available in .NET that does this: TextInfo.ToTitleCase (in System.Globalization
). This method will Upper-Case the first letter of each word, and Lower-Case the remaining letters. Unlike the other proposals here, it also skips words that are in all upper-case, assuming them to be acronyms. Of course, if this behavior is desired, it would be easy enough to update any of the T-SQL suggestions to do this as well.
One benefit of the .NET method is that it can Upper-Case letters that are Supplementary Characters. For example: DESERET SMALL LETTER OW has an upper-case mapping of DESERET CAPITAL LETTER OW (both show up as boxes when I paste them into here), but the UPPER()
function does not change the lower-case version to upper-case, even when the default Collation for the current Database is set to Latin1_General_100_CI_AS_SC
. This seems consistent with the MSDN documentation which does not list UPPER
and LOWER
in the chart of functions that behave differently when using an _SC
Collation: Collation and Unicode Support: Supplementary Characters.
SELECT N'DESERET SMALL LETTER OW' AS [Label], NCHAR(0xD801)+NCHAR(0xDC35) AS [Thing]
UNION ALL
SELECT N'DESERET CAPITAL LETTER OW' AS [Label], NCHAR(0xD801)+NCHAR(0xDC0D) AS [Thing]
UNION ALL
SELECT N'SmallButShouldBeCapital' AS [Label], UPPER(NCHAR(0xD801)+NCHAR(0xDC35)) AS [Thing]
Returns (enlarged so you can actually see the Supplementary Character):
You can see the full (and current) list of characters that are lower-case and change to upper-case using the following search feature at Unicode.org (you can see the Supplementary Characters by scrolling down until you get to the "DESERET" section, or just hit Control-F and search for that word):
http://unicode.org/cldr/utility/list-unicodeset.jsp?a=%5B%3AChanges_When_Titlecased%3DYes%3A%5D
Though to be honest, this isn't a huge benefit since it is doubtful that anyone is actually using any of the Supplementary Characters that can be title-cased. Either way, here is the SQLCLR code:
using System.Data.SqlTypes;
using System.Globalization;
using Microsoft.SqlServer.Server;
public class TitleCasing
{
[return: SqlFacet(MaxSize = 4000)]
[Microsoft.SqlServer.Server.SqlFunction(IsDeterministic = true, IsPrecise = true)]
public static SqlString TitleCase([SqlFacet(MaxSize = 4000)] SqlString InputString)
{
TextInfo _TxtInf = new CultureInfo(InputString.LCID).TextInfo;
return new SqlString (_TxtInf.ToTitleCase(InputString.Value));
}
}
Here is @MikaelEriksson's suggestion -- modified slightly to handle NVARCHAR
data as well as skip words that are all upper-case (to more closely match the behavior of the .NET method) -- along with a test of that T-SQL implementation and of the SQLCLR implementation:
SET NOCOUNT ON;
DECLARE @a NVARCHAR(50);
SET @a = N'qWeRtY kEyBoArD TEST<>&''"X one&TWO '
+ NCHAR(0xD801)+NCHAR(0xDC28)
+ N'pPLe '
+ NCHAR(0x24D0) -- ⓐ Circled "a"
+ NCHAR(0xFF24) -- D Full-width "D"
+ N'D u'
+ NCHAR(0x0308) -- ̈ (combining diaeresis / umlaut)
+ N'vU'
+ NCHAR(0x0308) -- ̈ (combining diaeresis / umlaut)
+ N'lA';
SELECT @a AS [Original];
SELECT STUFF((
SELECT N' '
+ IIF(UPPER(T3.V) <> T3.V COLLATE Latin1_General_100_BIN2,
UPPER(LEFT(T3.V COLLATE Latin1_General_100_CI_AS_SC, 1))
+ LOWER(STUFF(T3.V COLLATE Latin1_General_100_CI_AS_SC, 1, 1, N'')),
T3.V)
FROM (SELECT CAST(REPLACE((SELECT @a AS N'*' FOR XML PATH('')), N' ', N'<X/>')
AS XML).query('.')) AS T1(X)
CROSS APPLY T1.X.nodes('text()') AS T2(X)
CROSS APPLY (SELECT T2.X.value('.', 'NVARCHAR(70)')) AS T3(V)
FOR XML PATH(''), TYPE
).value('text()[1]', 'NVARCHAR(70)') COLLATE Latin1_General_100_CI_AS_SC, 1, 1, N'')
AS [Capitalize first letter only];
SELECT dbo.TitleCase(@a) AS [ToTitleCase];
Another difference in behavior is that this particular T-SQL implementation splits on only spaces, whereas the ToTitleCase()
method considers most non-letters to be word separators (hence the difference in handling of the "one&TWO" part).
Both implementations handle combining sequences correctly. Each of the accented letters in "üvÜlA" are comprised of a base letter and a combining diaeresis / umlaut (the two dots above each letter), and they are correctly converted to the other case in both tests.
Finally, one unexpected disadvantage to the SQLCLR version is that in coming up with various tests, I found a bug in the .NET code related to its handling of the Circled Letters (which has now been reported on Microsoft Connect — UPDATE: Connect has been moved to /dev/null
-- literally -- so I might need to resubmit this if the problem still exists). The .NET library treats the Circled Letters as word separators, which is why it does not turn the "ⓐDD" into "Ⓐdd" as it should.
FYI
A pre-done SQLCLR function encapsulating the TextInfo.ToTitleCase
method mentioned above is now available in the Free version of SQL# (which I wrote) as String_ToTitleCase and String_ToTitleCase4k.
😺
edited Feb 23 '18 at 21:52
answered Jun 28 '16 at 7:07
Solomon RutzkySolomon Rutzky
48.5k581177
48.5k581177
Should be way up there.
– Nelz
Jul 27 '17 at 9:51
add a comment |
Should be way up there.
– Nelz
Jul 27 '17 at 9:51
Should be way up there.
– Nelz
Jul 27 '17 at 9:51
Should be way up there.
– Nelz
Jul 27 '17 at 9:51
add a comment |
As an alternative to Mikael Eriksson's answer, you could consider using the proprietary T-SQL handling of variable setting in multi-row select statements.
In SQL Server, when a variable is being set as part of a SELECT statement, each row will execute an iteration of the set logic.
Folks often use this method for concatenating strings, though it's unsupported and there are some officially documented issues with it. The official problem relates to particular ORDER BY characteristics, and we don't need that here, so perhaps it's a safe option.
Here, we iterate over the 26 letters of the alphabet and replace them with an upper case version if they are preceded by a space. (We prep the string initially by capitalizing the first letter and making the rest lower case, as you did in your question.)
The SQL is a little complex because it requires the use of a Tally Table-- a table of numbers-- to generate the 26 iterations of replacing that it's doing. You can make a handy inline table-valued user defined function (TVF) to produce that table of numbers or you could even use a physical table.
A drawback of this option is that it can't be part of an inline TVF as it needs to involve setting a variable. So if you wanted to apply this method to a column of your output, you would need to wrap it into a multi-statement TVF or a scalar user defined function.
However, its query plan is much simpler and it is probably significantly faster than the XML method. You could argue it's easier to understand, too (especially if you have your own tally table).
DECLARE
@a VARCHAR(15) = 'qWeRtY kEyBoArD';
SELECT
@a = UPPER(LEFT(@a,1)) + LOWER(SUBSTRING(@a,2,LEN(@a)));
WITH TallyTableBase AS
(
SELECT
0 AS n
FROM (VALUES(0),(0),(0),(0),(0),(0),(0),(0),(0),(0)) AS t(n)
)
SELECT
@a = REPLACE(@a, ' ' + CHAR(n.n), ' ' + CHAR(n.n))
FROM (
SELECT TOP 26 ROW_NUMBER() OVER (ORDER BY (SELECT 1)) + 64 AS n
FROM TallyTableBase a
CROSS JOIN TallyTableBase b
) AS n;
SELECT
@a AS [NewValue];
(I tested this using a much larger string and it was about 6ms vs 14ms for the XML solution.)
There are a number of additional limitations with this solution. As written, it assumes a case insensitive collation, though you could eliminate that issue by specifying a collation or running LCASE on the search term, at the cost of some performance. It also only addresses standard ASCII letters and relies on their placement in the character set, so it would do nothing with ñ.
add a comment |
As an alternative to Mikael Eriksson's answer, you could consider using the proprietary T-SQL handling of variable setting in multi-row select statements.
In SQL Server, when a variable is being set as part of a SELECT statement, each row will execute an iteration of the set logic.
Folks often use this method for concatenating strings, though it's unsupported and there are some officially documented issues with it. The official problem relates to particular ORDER BY characteristics, and we don't need that here, so perhaps it's a safe option.
Here, we iterate over the 26 letters of the alphabet and replace them with an upper case version if they are preceded by a space. (We prep the string initially by capitalizing the first letter and making the rest lower case, as you did in your question.)
The SQL is a little complex because it requires the use of a Tally Table-- a table of numbers-- to generate the 26 iterations of replacing that it's doing. You can make a handy inline table-valued user defined function (TVF) to produce that table of numbers or you could even use a physical table.
A drawback of this option is that it can't be part of an inline TVF as it needs to involve setting a variable. So if you wanted to apply this method to a column of your output, you would need to wrap it into a multi-statement TVF or a scalar user defined function.
However, its query plan is much simpler and it is probably significantly faster than the XML method. You could argue it's easier to understand, too (especially if you have your own tally table).
DECLARE
@a VARCHAR(15) = 'qWeRtY kEyBoArD';
SELECT
@a = UPPER(LEFT(@a,1)) + LOWER(SUBSTRING(@a,2,LEN(@a)));
WITH TallyTableBase AS
(
SELECT
0 AS n
FROM (VALUES(0),(0),(0),(0),(0),(0),(0),(0),(0),(0)) AS t(n)
)
SELECT
@a = REPLACE(@a, ' ' + CHAR(n.n), ' ' + CHAR(n.n))
FROM (
SELECT TOP 26 ROW_NUMBER() OVER (ORDER BY (SELECT 1)) + 64 AS n
FROM TallyTableBase a
CROSS JOIN TallyTableBase b
) AS n;
SELECT
@a AS [NewValue];
(I tested this using a much larger string and it was about 6ms vs 14ms for the XML solution.)
There are a number of additional limitations with this solution. As written, it assumes a case insensitive collation, though you could eliminate that issue by specifying a collation or running LCASE on the search term, at the cost of some performance. It also only addresses standard ASCII letters and relies on their placement in the character set, so it would do nothing with ñ.
add a comment |
As an alternative to Mikael Eriksson's answer, you could consider using the proprietary T-SQL handling of variable setting in multi-row select statements.
In SQL Server, when a variable is being set as part of a SELECT statement, each row will execute an iteration of the set logic.
Folks often use this method for concatenating strings, though it's unsupported and there are some officially documented issues with it. The official problem relates to particular ORDER BY characteristics, and we don't need that here, so perhaps it's a safe option.
Here, we iterate over the 26 letters of the alphabet and replace them with an upper case version if they are preceded by a space. (We prep the string initially by capitalizing the first letter and making the rest lower case, as you did in your question.)
The SQL is a little complex because it requires the use of a Tally Table-- a table of numbers-- to generate the 26 iterations of replacing that it's doing. You can make a handy inline table-valued user defined function (TVF) to produce that table of numbers or you could even use a physical table.
A drawback of this option is that it can't be part of an inline TVF as it needs to involve setting a variable. So if you wanted to apply this method to a column of your output, you would need to wrap it into a multi-statement TVF or a scalar user defined function.
However, its query plan is much simpler and it is probably significantly faster than the XML method. You could argue it's easier to understand, too (especially if you have your own tally table).
DECLARE
@a VARCHAR(15) = 'qWeRtY kEyBoArD';
SELECT
@a = UPPER(LEFT(@a,1)) + LOWER(SUBSTRING(@a,2,LEN(@a)));
WITH TallyTableBase AS
(
SELECT
0 AS n
FROM (VALUES(0),(0),(0),(0),(0),(0),(0),(0),(0),(0)) AS t(n)
)
SELECT
@a = REPLACE(@a, ' ' + CHAR(n.n), ' ' + CHAR(n.n))
FROM (
SELECT TOP 26 ROW_NUMBER() OVER (ORDER BY (SELECT 1)) + 64 AS n
FROM TallyTableBase a
CROSS JOIN TallyTableBase b
) AS n;
SELECT
@a AS [NewValue];
(I tested this using a much larger string and it was about 6ms vs 14ms for the XML solution.)
There are a number of additional limitations with this solution. As written, it assumes a case insensitive collation, though you could eliminate that issue by specifying a collation or running LCASE on the search term, at the cost of some performance. It also only addresses standard ASCII letters and relies on their placement in the character set, so it would do nothing with ñ.
As an alternative to Mikael Eriksson's answer, you could consider using the proprietary T-SQL handling of variable setting in multi-row select statements.
In SQL Server, when a variable is being set as part of a SELECT statement, each row will execute an iteration of the set logic.
Folks often use this method for concatenating strings, though it's unsupported and there are some officially documented issues with it. The official problem relates to particular ORDER BY characteristics, and we don't need that here, so perhaps it's a safe option.
Here, we iterate over the 26 letters of the alphabet and replace them with an upper case version if they are preceded by a space. (We prep the string initially by capitalizing the first letter and making the rest lower case, as you did in your question.)
The SQL is a little complex because it requires the use of a Tally Table-- a table of numbers-- to generate the 26 iterations of replacing that it's doing. You can make a handy inline table-valued user defined function (TVF) to produce that table of numbers or you could even use a physical table.
A drawback of this option is that it can't be part of an inline TVF as it needs to involve setting a variable. So if you wanted to apply this method to a column of your output, you would need to wrap it into a multi-statement TVF or a scalar user defined function.
However, its query plan is much simpler and it is probably significantly faster than the XML method. You could argue it's easier to understand, too (especially if you have your own tally table).
DECLARE
@a VARCHAR(15) = 'qWeRtY kEyBoArD';
SELECT
@a = UPPER(LEFT(@a,1)) + LOWER(SUBSTRING(@a,2,LEN(@a)));
WITH TallyTableBase AS
(
SELECT
0 AS n
FROM (VALUES(0),(0),(0),(0),(0),(0),(0),(0),(0),(0)) AS t(n)
)
SELECT
@a = REPLACE(@a, ' ' + CHAR(n.n), ' ' + CHAR(n.n))
FROM (
SELECT TOP 26 ROW_NUMBER() OVER (ORDER BY (SELECT 1)) + 64 AS n
FROM TallyTableBase a
CROSS JOIN TallyTableBase b
) AS n;
SELECT
@a AS [NewValue];
(I tested this using a much larger string and it was about 6ms vs 14ms for the XML solution.)
There are a number of additional limitations with this solution. As written, it assumes a case insensitive collation, though you could eliminate that issue by specifying a collation or running LCASE on the search term, at the cost of some performance. It also only addresses standard ASCII letters and relies on their placement in the character set, so it would do nothing with ñ.
edited May 23 '17 at 12:40
Community♦
1
1
answered May 27 '16 at 15:48
Riley MajorRiley Major
9381818
9381818
add a comment |
add a comment |
Assuming you are only looking to capitalize words following a space, here is an another way you could do it.
DECLARE @String VARCHAR(1000)
SET @String = 'qWeRtY kEyBoArD tEst'
/*
Set the string to all lower case and
add a space at the beginning to ensure
the first letter gets capitalized
in the CTE
*/
SET @String = LOWER(' ' + @String)
/*
Use a Tally "Table" as a means of
replacing the letter after the space
with the capitalize version of the
letter
*/
;WITH TallyTable
AS
(
SELECT TOP 1000 ROW_NUMBER() OVER (ORDER BY (SELECT NULL)) as N
FROM master.sys.all_columns a CROSS JOIN master.sys.all_columns b
)
SELECT @String = REPLACE(@String,SUBSTRING(@String,CHARINDEX(' ',@String,N), 2),UPPER(SUBSTRING(@String,CHARINDEX(' ',@String,N), 2)))
FROM TallyTable
WHERE CHARINDEX(' ',@String,N) <> 0
--Remove the space added to the beginning of the string earlier
SET @String = RIGHT(@String,LEN(@String) - 1)
add a comment |
Assuming you are only looking to capitalize words following a space, here is an another way you could do it.
DECLARE @String VARCHAR(1000)
SET @String = 'qWeRtY kEyBoArD tEst'
/*
Set the string to all lower case and
add a space at the beginning to ensure
the first letter gets capitalized
in the CTE
*/
SET @String = LOWER(' ' + @String)
/*
Use a Tally "Table" as a means of
replacing the letter after the space
with the capitalize version of the
letter
*/
;WITH TallyTable
AS
(
SELECT TOP 1000 ROW_NUMBER() OVER (ORDER BY (SELECT NULL)) as N
FROM master.sys.all_columns a CROSS JOIN master.sys.all_columns b
)
SELECT @String = REPLACE(@String,SUBSTRING(@String,CHARINDEX(' ',@String,N), 2),UPPER(SUBSTRING(@String,CHARINDEX(' ',@String,N), 2)))
FROM TallyTable
WHERE CHARINDEX(' ',@String,N) <> 0
--Remove the space added to the beginning of the string earlier
SET @String = RIGHT(@String,LEN(@String) - 1)
add a comment |
Assuming you are only looking to capitalize words following a space, here is an another way you could do it.
DECLARE @String VARCHAR(1000)
SET @String = 'qWeRtY kEyBoArD tEst'
/*
Set the string to all lower case and
add a space at the beginning to ensure
the first letter gets capitalized
in the CTE
*/
SET @String = LOWER(' ' + @String)
/*
Use a Tally "Table" as a means of
replacing the letter after the space
with the capitalize version of the
letter
*/
;WITH TallyTable
AS
(
SELECT TOP 1000 ROW_NUMBER() OVER (ORDER BY (SELECT NULL)) as N
FROM master.sys.all_columns a CROSS JOIN master.sys.all_columns b
)
SELECT @String = REPLACE(@String,SUBSTRING(@String,CHARINDEX(' ',@String,N), 2),UPPER(SUBSTRING(@String,CHARINDEX(' ',@String,N), 2)))
FROM TallyTable
WHERE CHARINDEX(' ',@String,N) <> 0
--Remove the space added to the beginning of the string earlier
SET @String = RIGHT(@String,LEN(@String) - 1)
Assuming you are only looking to capitalize words following a space, here is an another way you could do it.
DECLARE @String VARCHAR(1000)
SET @String = 'qWeRtY kEyBoArD tEst'
/*
Set the string to all lower case and
add a space at the beginning to ensure
the first letter gets capitalized
in the CTE
*/
SET @String = LOWER(' ' + @String)
/*
Use a Tally "Table" as a means of
replacing the letter after the space
with the capitalize version of the
letter
*/
;WITH TallyTable
AS
(
SELECT TOP 1000 ROW_NUMBER() OVER (ORDER BY (SELECT NULL)) as N
FROM master.sys.all_columns a CROSS JOIN master.sys.all_columns b
)
SELECT @String = REPLACE(@String,SUBSTRING(@String,CHARINDEX(' ',@String,N), 2),UPPER(SUBSTRING(@String,CHARINDEX(' ',@String,N), 2)))
FROM TallyTable
WHERE CHARINDEX(' ',@String,N) <> 0
--Remove the space added to the beginning of the string earlier
SET @String = RIGHT(@String,LEN(@String) - 1)
answered Jun 14 '16 at 18:47
TLaVTLaV
1411
1411
add a comment |
add a comment |
Might not be bullet-proof but I hope it's a helpful contribution to this thread.
DECLARE @t VARCHAR(50) = 'the quick brown fox jumps over the lazy dog', @i INT = 0
DECLARE @chk VARCHAR(1)
WHILE @i <= LEN(@t)
BEGIN
SELECT @chk=SUBSTRING(@t,@i,1)
IF @chk = CHAR(32)
BEGIN
SET @t = STUFF(@t,@i+1,1,UPPER(SUBSTRING(@t,@i+1,1)))
END
SET @i=@i+1
END
PRINT @t
add a comment |
Might not be bullet-proof but I hope it's a helpful contribution to this thread.
DECLARE @t VARCHAR(50) = 'the quick brown fox jumps over the lazy dog', @i INT = 0
DECLARE @chk VARCHAR(1)
WHILE @i <= LEN(@t)
BEGIN
SELECT @chk=SUBSTRING(@t,@i,1)
IF @chk = CHAR(32)
BEGIN
SET @t = STUFF(@t,@i+1,1,UPPER(SUBSTRING(@t,@i+1,1)))
END
SET @i=@i+1
END
PRINT @t
add a comment |
Might not be bullet-proof but I hope it's a helpful contribution to this thread.
DECLARE @t VARCHAR(50) = 'the quick brown fox jumps over the lazy dog', @i INT = 0
DECLARE @chk VARCHAR(1)
WHILE @i <= LEN(@t)
BEGIN
SELECT @chk=SUBSTRING(@t,@i,1)
IF @chk = CHAR(32)
BEGIN
SET @t = STUFF(@t,@i+1,1,UPPER(SUBSTRING(@t,@i+1,1)))
END
SET @i=@i+1
END
PRINT @t
Might not be bullet-proof but I hope it's a helpful contribution to this thread.
DECLARE @t VARCHAR(50) = 'the quick brown fox jumps over the lazy dog', @i INT = 0
DECLARE @chk VARCHAR(1)
WHILE @i <= LEN(@t)
BEGIN
SELECT @chk=SUBSTRING(@t,@i,1)
IF @chk = CHAR(32)
BEGIN
SET @t = STUFF(@t,@i+1,1,UPPER(SUBSTRING(@t,@i+1,1)))
END
SET @i=@i+1
END
PRINT @t
edited Jun 28 '16 at 10:48
answered Jun 28 '16 at 10:30
Simon JonesSimon Jones
756
756
add a comment |
add a comment |
Below is the procedure I used in a Firebird database to do this.
Probably can be cleaned up a lot but it got the job done for me.
set term ~;
Create Procedure EachWordCap
As
Declare Variable lcaption varchar(33);
Declare Variable lcurrentpos integer;
Declare Variable lstringlen integer;
begin
for select ' ' || trim(lower(imagedata.imagename)) from imagedata
where imagedata.imagename is not null and imagedata.imagename != ''
into :lcaption
do
begin
lcurrentpos = 0;
lstringlen = char_length(lcaption);
while (lcurrentpos != 1) do
begin
lcurrentpos = position(' ', lcaption, iif(lcurrentpos = 0, 1,lcurrentpos)) + 1 ;
lcaption = left(lcaption,lcurrentpos - 1) || upper(substring(lcaption from lcurrentpos for 1)) || right(lcaption,lstringlen - lcurrentpos);
end
--Put what you want to do with the text in here
end
end~
set term ;~
add a comment |
Below is the procedure I used in a Firebird database to do this.
Probably can be cleaned up a lot but it got the job done for me.
set term ~;
Create Procedure EachWordCap
As
Declare Variable lcaption varchar(33);
Declare Variable lcurrentpos integer;
Declare Variable lstringlen integer;
begin
for select ' ' || trim(lower(imagedata.imagename)) from imagedata
where imagedata.imagename is not null and imagedata.imagename != ''
into :lcaption
do
begin
lcurrentpos = 0;
lstringlen = char_length(lcaption);
while (lcurrentpos != 1) do
begin
lcurrentpos = position(' ', lcaption, iif(lcurrentpos = 0, 1,lcurrentpos)) + 1 ;
lcaption = left(lcaption,lcurrentpos - 1) || upper(substring(lcaption from lcurrentpos for 1)) || right(lcaption,lstringlen - lcurrentpos);
end
--Put what you want to do with the text in here
end
end~
set term ;~
add a comment |
Below is the procedure I used in a Firebird database to do this.
Probably can be cleaned up a lot but it got the job done for me.
set term ~;
Create Procedure EachWordCap
As
Declare Variable lcaption varchar(33);
Declare Variable lcurrentpos integer;
Declare Variable lstringlen integer;
begin
for select ' ' || trim(lower(imagedata.imagename)) from imagedata
where imagedata.imagename is not null and imagedata.imagename != ''
into :lcaption
do
begin
lcurrentpos = 0;
lstringlen = char_length(lcaption);
while (lcurrentpos != 1) do
begin
lcurrentpos = position(' ', lcaption, iif(lcurrentpos = 0, 1,lcurrentpos)) + 1 ;
lcaption = left(lcaption,lcurrentpos - 1) || upper(substring(lcaption from lcurrentpos for 1)) || right(lcaption,lstringlen - lcurrentpos);
end
--Put what you want to do with the text in here
end
end~
set term ;~
Below is the procedure I used in a Firebird database to do this.
Probably can be cleaned up a lot but it got the job done for me.
set term ~;
Create Procedure EachWordCap
As
Declare Variable lcaption varchar(33);
Declare Variable lcurrentpos integer;
Declare Variable lstringlen integer;
begin
for select ' ' || trim(lower(imagedata.imagename)) from imagedata
where imagedata.imagename is not null and imagedata.imagename != ''
into :lcaption
do
begin
lcurrentpos = 0;
lstringlen = char_length(lcaption);
while (lcurrentpos != 1) do
begin
lcurrentpos = position(' ', lcaption, iif(lcurrentpos = 0, 1,lcurrentpos)) + 1 ;
lcaption = left(lcaption,lcurrentpos - 1) || upper(substring(lcaption from lcurrentpos for 1)) || right(lcaption,lstringlen - lcurrentpos);
end
--Put what you want to do with the text in here
end
end~
set term ;~
answered Jan 20 '17 at 3:00
Jeffrey ElkinsJeffrey Elkins
1
1
add a comment |
add a comment |
Recursive CTEs are quite good for this sort of thing.
Probably not particularly efficient for large operations, but does allow for this kind of operation in a pure SQL select statement:
declare @a varchar(100)
set @a = 'tHe qUiCk bRoWn FOX jumps OvEr The lAZy dOG';
WITH [CTE] AS (
SELECT CAST(upper(Left(@a,1)) + lower(substring(@a,2,len(@a))) AS VARCHAR(100)) AS TEXT,
CHARINDEX(' ',@a) AS NEXT_SPACE
UNION ALL
SELECT CAST(Left(TEXT,NEXT_SPACE) + upper(SubString(TEXT,NEXT_SPACE+1,1)) + SubString(TEXT,NEXT_SPACE+2,1000) AS VARCHAR(100)),
CHARINDEX(' ',TEXT, NEXT_SPACE+1)
FROM [CTE]
WHERE NEXT_SPACE <> 0
)
SELECT TEXT
FROM [CTE]
WHERE NEXT_SPACE = 0
Output:
The Quick Brown Fox Jumps Over The Lazy Dog
add a comment |
Recursive CTEs are quite good for this sort of thing.
Probably not particularly efficient for large operations, but does allow for this kind of operation in a pure SQL select statement:
declare @a varchar(100)
set @a = 'tHe qUiCk bRoWn FOX jumps OvEr The lAZy dOG';
WITH [CTE] AS (
SELECT CAST(upper(Left(@a,1)) + lower(substring(@a,2,len(@a))) AS VARCHAR(100)) AS TEXT,
CHARINDEX(' ',@a) AS NEXT_SPACE
UNION ALL
SELECT CAST(Left(TEXT,NEXT_SPACE) + upper(SubString(TEXT,NEXT_SPACE+1,1)) + SubString(TEXT,NEXT_SPACE+2,1000) AS VARCHAR(100)),
CHARINDEX(' ',TEXT, NEXT_SPACE+1)
FROM [CTE]
WHERE NEXT_SPACE <> 0
)
SELECT TEXT
FROM [CTE]
WHERE NEXT_SPACE = 0
Output:
The Quick Brown Fox Jumps Over The Lazy Dog
add a comment |
Recursive CTEs are quite good for this sort of thing.
Probably not particularly efficient for large operations, but does allow for this kind of operation in a pure SQL select statement:
declare @a varchar(100)
set @a = 'tHe qUiCk bRoWn FOX jumps OvEr The lAZy dOG';
WITH [CTE] AS (
SELECT CAST(upper(Left(@a,1)) + lower(substring(@a,2,len(@a))) AS VARCHAR(100)) AS TEXT,
CHARINDEX(' ',@a) AS NEXT_SPACE
UNION ALL
SELECT CAST(Left(TEXT,NEXT_SPACE) + upper(SubString(TEXT,NEXT_SPACE+1,1)) + SubString(TEXT,NEXT_SPACE+2,1000) AS VARCHAR(100)),
CHARINDEX(' ',TEXT, NEXT_SPACE+1)
FROM [CTE]
WHERE NEXT_SPACE <> 0
)
SELECT TEXT
FROM [CTE]
WHERE NEXT_SPACE = 0
Output:
The Quick Brown Fox Jumps Over The Lazy Dog
Recursive CTEs are quite good for this sort of thing.
Probably not particularly efficient for large operations, but does allow for this kind of operation in a pure SQL select statement:
declare @a varchar(100)
set @a = 'tHe qUiCk bRoWn FOX jumps OvEr The lAZy dOG';
WITH [CTE] AS (
SELECT CAST(upper(Left(@a,1)) + lower(substring(@a,2,len(@a))) AS VARCHAR(100)) AS TEXT,
CHARINDEX(' ',@a) AS NEXT_SPACE
UNION ALL
SELECT CAST(Left(TEXT,NEXT_SPACE) + upper(SubString(TEXT,NEXT_SPACE+1,1)) + SubString(TEXT,NEXT_SPACE+2,1000) AS VARCHAR(100)),
CHARINDEX(' ',TEXT, NEXT_SPACE+1)
FROM [CTE]
WHERE NEXT_SPACE <> 0
)
SELECT TEXT
FROM [CTE]
WHERE NEXT_SPACE = 0
Output:
The Quick Brown Fox Jumps Over The Lazy Dog
answered Jul 27 '17 at 9:48
JerbJerb
49517
49517
add a comment |
add a comment |
I like this version. It is simple, and can be used to create a function, you just have to have the right version of SQL Server:
WITH words
AS (
SELECT upper(left(Value, 1)) + lower(substring(Value, 2, len(Value))) AS word
FROM STRING_SPLIT('Lorem ipsum dolor sit amet.', ' ')
)
SELECT STRING_AGG(words.word, ' ')
FROM words
New contributor
Which one is the right version?
– dezso
3 hours ago
add a comment |
I like this version. It is simple, and can be used to create a function, you just have to have the right version of SQL Server:
WITH words
AS (
SELECT upper(left(Value, 1)) + lower(substring(Value, 2, len(Value))) AS word
FROM STRING_SPLIT('Lorem ipsum dolor sit amet.', ' ')
)
SELECT STRING_AGG(words.word, ' ')
FROM words
New contributor
Which one is the right version?
– dezso
3 hours ago
add a comment |
I like this version. It is simple, and can be used to create a function, you just have to have the right version of SQL Server:
WITH words
AS (
SELECT upper(left(Value, 1)) + lower(substring(Value, 2, len(Value))) AS word
FROM STRING_SPLIT('Lorem ipsum dolor sit amet.', ' ')
)
SELECT STRING_AGG(words.word, ' ')
FROM words
New contributor
I like this version. It is simple, and can be used to create a function, you just have to have the right version of SQL Server:
WITH words
AS (
SELECT upper(left(Value, 1)) + lower(substring(Value, 2, len(Value))) AS word
FROM STRING_SPLIT('Lorem ipsum dolor sit amet.', ' ')
)
SELECT STRING_AGG(words.word, ' ')
FROM words
New contributor
edited 3 hours ago
Tony Hinkle
2,5051422
2,5051422
New contributor
answered 4 hours ago
CristiCristi
1
1
New contributor
New contributor
Which one is the right version?
– dezso
3 hours ago
add a comment |
Which one is the right version?
– dezso
3 hours ago
Which one is the right version?
– dezso
3 hours ago
Which one is the right version?
– dezso
3 hours ago
add a comment |
Test Data
declare @word varchar(100)
with good as (select 'good' as a union select 'nice' union select 'fine')
select @word = (SELECT TOP 1 a FROM good ORDER BY NEWID())
Implementation
select substring(Upper(@word),1,1) + substring(@word, 2, LEN(@word))
Capitalizing words which are already separate is easy. I believe the OP is interested in how to identify words within a string, and capitalize each of them.
– Jon of All Trades
Feb 26 '18 at 14:36
add a comment |
Test Data
declare @word varchar(100)
with good as (select 'good' as a union select 'nice' union select 'fine')
select @word = (SELECT TOP 1 a FROM good ORDER BY NEWID())
Implementation
select substring(Upper(@word),1,1) + substring(@word, 2, LEN(@word))
Capitalizing words which are already separate is easy. I believe the OP is interested in how to identify words within a string, and capitalize each of them.
– Jon of All Trades
Feb 26 '18 at 14:36
add a comment |
Test Data
declare @word varchar(100)
with good as (select 'good' as a union select 'nice' union select 'fine')
select @word = (SELECT TOP 1 a FROM good ORDER BY NEWID())
Implementation
select substring(Upper(@word),1,1) + substring(@word, 2, LEN(@word))
Test Data
declare @word varchar(100)
with good as (select 'good' as a union select 'nice' union select 'fine')
select @word = (SELECT TOP 1 a FROM good ORDER BY NEWID())
Implementation
select substring(Upper(@word),1,1) + substring(@word, 2, LEN(@word))
edited Jul 27 '17 at 8:05
dezso
22.2k116096
22.2k116096
answered Jul 27 '17 at 5:05
Romiko DerbynewRomiko Derbynew
1
1
Capitalizing words which are already separate is easy. I believe the OP is interested in how to identify words within a string, and capitalize each of them.
– Jon of All Trades
Feb 26 '18 at 14:36
add a comment |
Capitalizing words which are already separate is easy. I believe the OP is interested in how to identify words within a string, and capitalize each of them.
– Jon of All Trades
Feb 26 '18 at 14:36
Capitalizing words which are already separate is easy. I believe the OP is interested in how to identify words within a string, and capitalize each of them.
– Jon of All Trades
Feb 26 '18 at 14:36
Capitalizing words which are already separate is easy. I believe the OP is interested in how to identify words within a string, and capitalize each of them.
– Jon of All Trades
Feb 26 '18 at 14:36
add a comment |
Thanks for contributing an answer to Database Administrators Stack Exchange!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fdba.stackexchange.com%2fquestions%2f139382%2fcapitalize-only-the-first-letter-of-each-word-of-each-sentence-in-sql-server%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
11
Why you do want to do this within sql server ? Your presentation layer should handle that efficiently !
– Kin
May 24 '16 at 15:53