May 5, 2004 at 11:37 am
We have UPPER() and LOWER() but SQL Svr 2k does not have a function to put strings into their proper case. i.e. Bob vs bob or BOB, O'Mally vs o'mally or O'MALLY or O'mally, etc. Does anyone have a good (read fast) function to do this?
URGENT
Kurt Allebach
May 6, 2004 at 4:12 am
Well, it doesn't treat o'malley as O'Malley, but it's close..
(you have to modify yourself for that)
Anyway, here's a combined properCase and whitespace trimmer UDF I wrote. Use it if you like it.
-- Script downloaded 5/6/2004 5:06:34 AM
-- From The SQL Server Worldwide User's Group (www.sswug.org)
-- Scripts provided AS-IS without warranty of any kind use at your own risk
if object_id('dbo.properCase') is not null drop function dbo.properCase
go
create function dbo.properCase ( @string varchar(8000) )
returns varchar(8000)
as
-- T-SQL combined whitespace trimmer and 'proper case' function - SQL Server 2000
-- 2002-10-23 © Kenneth Wilhelmsson
-- Example: Select dbo.properCase(notes) from pubs..titles to see all notes proper cased.
-- Example2: select dbo.properCase(' a somewhat irregular string ')
begin
-- return null if input is null
if ( @string is null ) return null
declare @test varchar(8000), @propcase varchar(8000)
-- init
select @propcase = ''
-- remove embedded multiple spaces between words
-- we do this by replacing 2 spaces with 1 as long as there are pairs...
while patindex('% %', @string) > 0
begin
select @string = replace(@string,' ',' ')
end
-- if we still have leading spaces..
while substring(@string,1,1) = ' '
begin
set @string = substring(@string,2,8000)
end
-- or trailing spaces...
set @string = reverse(@string)
while substring(@string,1,1) = ' '
begin
set @string = substring(@string,2,8000)
end
set @string = reverse(@string)
-- done, if there still are spaces inside, begin...
while patindex('% %',@string) > 0
begin
-- grab the first 'word'
set @test = substring(@string,1,charindex(' ',@string))
-- then propCase it
set @test = upper(substring(@test,1,1)) +
lower(substring(@test,2,len(@test)-1)) + ' '
-- save away the cased word
set @propcase = @propcase + @test
-- trim the string from the used 'word'
set @string = substring(@string,(len(@test)+2),8000)
-- if there are more spaces - do it all over again with the next 'word'....
-- except, if the 2nd next char is a space - then trim away one
while substring(@string,1,1) = ' ' and substring(@string,2,1) = ' '
begin
set @string = substring(@string,2,8000)
end
end
-- if no spaces, it's a single word, or the last word from the loop....
if patindex('% %',@string) = 0
begin
-- then just propCase the single word
set @test = upper(substring(@string,1,1)) +
lower(substring(@string,2,len(@string)-1))
-- save away the cased word
set @propcase = @propcase + @test
end
-- done
return @propcase
end
go
May 6, 2004 at 5:28 am
CREATE FUNCTION xProper(@StringVal AS Varchar(8000)) RETURNS Varchar(8000)
BEGIN
Declare @Char As Varchar(1), @Len As Int, @NewVal As Varchar(8000), @Pos As Int, @PrevChar AS Varchar(1)
If @StringVal Is Null Return Null
Select @Char='', @NewVal='', @Pos = 1, @Len=DATALENGTH(@StringVal), @StringVal=Upper(@StringVal)
WHILE @Pos <= @Len BEGIN
Set @Char=SUBSTRING(@StringVal, @Pos, 1)
Set @PrevChar=SUBSTRING(@StringVal, @Pos-1, 1)
If ASCII(@PrevChar) Between 65 And 90 OR ASCII(@PrevChar) Between 97 And 122 Set @Char=Lower(@Char)
Set @NewVal=@NewVal + @Char
SET @Pos = @Pos + 1
END
RETURN @NewVal
END
May 6, 2004 at 6:44 am
A nice and short UDF.
It does have some limitations, though.
While it cases o'malley as O'Malley successfully, it also cases words like don't and can't as Don'T and Can'T.
For many of you a-z speaking guys the method of using ascii ranges is good enough, however for us with extended ascii in our languages, this won't work. The lack of extended ascii support makes casing rather eLiTe looking.
eg 'jag äter rökt ål' becomes 'Jag ÄTer RöKt ÅL'
..for the curious this means 'I Eat Smoked Eel'
Anyway, bottom line is that I don't think there is any perfect 'propcaser' anywhere. It's always difficult to handle the exceptions. (like MacDuff or McDuff etc..)
/Kenneth
May 6, 2004 at 7:03 am
Thx to all. To date I have recieved 6 scripts and we are testing each for function and performance. We may use one as is or combine with elements from many. In any case I will be posting my results shortly. Stay tuned.
Kurt Allebach
May 7, 2004 at 1:17 am
Kurt,
You may also want to try this:
This function will evaluate an input string and convert it to title-case format. It uses the delimchars parameter to determine what are the triggering characters to indicate capitalization of the subsequent character.<BR>I am using it in a DTS package to convert data in CAPS to Title/Proper case as I output the data to an Excel file.
/*This function will evaluate an input string and convert it to title-case format.
it uses the delimchars parameter to determine what are the triggering characters
to indicate capitalization of the subsequent character*/
CREATE FUNCTION fnTitleCase (@instring nvarchar(256))
RETURNS nvarchar(256)
AS
BEGIN
DECLARE @strptr INT
DECLARE @outstring nvarchar(255)
DECLARE @strChar char(1)
DECLARE @delimchars nvarchar(256)
SET @outstring = ''
SET @strptr = 0
IF @delimchars is NULL
/* Plug in typical upper-case delimiters
NOTE: For localization purposes, you may wish to modify this */
SET @delimchars = ' ''-_.,'
/* Loop through the entire string */
WHILE @strPtr < len(RTRIM(@instring))
BEGIN
SET @strptr = @strptr + 1
SET @strchar = SUBSTRING(@instring,@strptr,1)
IF @strptr = 1
/* Assume that first character must always being upper-cased*/
SET @outstring = UPPER(@strchar)
ELSE
/*Check for other upper-case trigger character */
IF CHARINDEX(SUBSTRING(@instring,(@strptr - 1),1),@delimchars) > 0
-- SET @outstring = SUBSTRING(@outstring,1,@strptr)+UPPER(@strchar)
SET @outstring = @outstring+UPPER(@strchar)
ELSE
SET @outstring = @outstring+LOWER(@strchar)
END
RETURN @outstring
END
Cheers,
Angela
June 9, 2004 at 11:05 am
Here is my contribution to this old question:
CREATE FUNCTION dbo.udf_ProperCase
(@StringVal AS Varchar(8000))
RETURNS Varchar(8000)
AS
/*******************************************************************************************
<cdCmnt>
<descr>Returns a string as proper case using ASCII values
After scouring the internet, found many, many proper case functions
but this was the only one that handled all of the following:
B.C., N.W.T., A.J.M., G/L, R.C.M.P., C E, Brenda J., Jo-Anne, Donald Brian, Nikka L. A., Allan (Harland)
The contribution was from:
http://www.sqlservercentral.com/forums/shwmessage.aspx?forumid=8&messageid=114551#bm114674
Contributor RobertPaquette
...HOWEVER, it DID NOT handle JAY'S or addresses like 8th. So, I customized it to handle this
Examples:
SELECT dbo.udf_ProperCase('hi')
SELECT dbo.udf_ProperCase('')
SELECT dbo.udf_ProperCase('O''Reilly')
SELECT dbo.udf_ProperCase('Jay''s')
SELECT dbo.udf_ProperCase('JAY''S')
SELECT dbo.udf_ProperCase('Jay''s Moving')
SELECT dbo.udf_ProperCase('R.C.M.P')
SELECT dbo.udf_ProperCase('R.C.M.P.')
SELECT dbo.udf_ProperCase('G/L')
SELECT dbo.udf_ProperCase('8TH')
</descr>
<parm nm='@StringVal'>
<descr>Input string</descr>
</parm>
<rvsn>
<auth>dtomyn</auth>
<dt>2004/05/12</dt>
<descr>Created</descr>
</rvsn>
</cdCmnt>
*******************************************************************************************/
BEGIN
DECLARE
@Char AS VARCHAR(1)
, @Len AS INT
, @NewVal AS VARCHAR(8000)
, @Pos AS INT
, @PrevChar AS VARCHAR(1)
, @NextChar AS VARCHAR(1) --added
IF @StringVal IS NULL
RETURN NULL
SELECT
@Char=''
, @NewVal=''
, @Pos = 1
, @Len=DATALENGTH(@StringVal)
, @StringVal=Upper(@StringVal)
WHILE @Pos <= @Len
BEGIN
SET @Char=SUBSTRING(@StringVal, @Pos, 1)
SET @PrevChar=SUBSTRING(@StringVal, @Pos-1, 1)
SET @NextChar=SUBSTRING(@StringVal, @Pos+1, 1) --added
IF ASCII(@PrevChar) = 39 --if ' added
BEGIN --added
--if at end of string then datalength will be 0 and this character should NOT be capitalized
IF DATALENGTH(@NextChar) = 0 --added
SET @Char=LOWER(@Char) --added
ELSE
BEGIN
--if next character is a space than the letter should NOT be capitalized
IF ASCII(@NextChar) = 32 --added
SET @Char=LOWER(@Char) --added
ELSE
SET @Char=UPPER(@Char) --added
END
END --added
ELSE
BEGIN
IF ASCII(@PrevChar) Between 65 And 90 OR ASCII(@PrevChar) Between 97 And 122
SET @Char=LOWER(@Char)
ELSE --added
BEGIN --added
--if previous character was a number then change the case to a lower
IF ASCII(@PrevChar) Between 48 And 57 --added
SET @Char = LOWER(@Char) --added
ELSE --added
SET @Char=UPPER(@Char) --added
END
END
SET @NewVal=@NewVal + @Char
SET @Pos = @Pos + 1
END
RETURN RTRIM(LTRIM(@NewVal))
-- RETURN @NewVal
END
Viewing 7 posts - 1 through 6 (of 6 total)
You must be logged in to reply to this topic. Login to reply