programing

SQL Server에서 문자열에 포함된 각 단어의 첫 글자를 대문자로 표시하는 방법

powerit 2023. 6. 22. 22:32
반응형

SQL Server에서 문자열에 포함된 각 단어의 첫 글자를 대문자로 표시하는 방법

SQL Server에서 문자열에 있는 각 단어의 첫 번째 문자를 대문자로 표시하는 가장 좋은 방법은 무엇입니까?

출처: http://www.sql-server-helper.com/functions/initcap.aspx

CREATE FUNCTION [dbo].[InitCap] ( @InputString varchar(4000) ) 
RETURNS VARCHAR(4000)
AS
BEGIN

DECLARE @Index          INT
DECLARE @Char           CHAR(1)
DECLARE @PrevChar       CHAR(1)
DECLARE @OutputString   VARCHAR(255)

SET @OutputString = LOWER(@InputString)
SET @Index = 1

WHILE @Index <= LEN(@InputString)
BEGIN
    SET @Char     = SUBSTRING(@InputString, @Index, 1)
    SET @PrevChar = CASE WHEN @Index = 1 THEN ' '
                         ELSE SUBSTRING(@InputString, @Index - 1, 1)
                    END

    IF @PrevChar IN (' ', ';', ':', '!', '?', ',', '.', '_', '-', '/', '&', '''', '(')
    BEGIN
        IF @PrevChar != '''' OR UPPER(@Char) != 'S'
            SET @OutputString = STUFF(@OutputString, @Index, 1, UPPER(@Char))
    END

    SET @Index = @Index + 1
END

RETURN @OutputString

END
GO

여기에 더 단순하거나 더 작은 것이 있습니다. 그러나 행에 공백이 없으면 작동하지 않습니다. "잘못된 길이 매개 변수가 RIGHT 함수에 전달되었습니다."):

http://www.devx.com/tips/Tip/17608

테이블 값 함수로서:

CREATE FUNCTION dbo.InitCap(@v AS VARCHAR(MAX))
RETURNS TABLE
AS
RETURN 
WITH a AS (
    SELECT (
        SELECT UPPER(LEFT(value, 1)) + LOWER(SUBSTRING(value, 2, LEN(value))) AS 'data()'
        FROM string_split(@v, ' ')
        ORDER BY CHARINDEX(value,@v)
        FOR XML PATH (''), TYPE) ret)

SELECT CAST(a.ret AS varchar(MAX)) ret from a
GO

참고:string_split을 요구합니다.COMPATIBILITY_LEVEL 130.

제가 꽤 오랫동안 사용해온 것의 변형은 다음과 같습니다.

CREATE FUNCTION [widget].[properCase](@string varchar(8000)) RETURNS varchar(8000) AS
BEGIN   
    SET @string = LOWER(@string)
    DECLARE @i INT
    SET @i = ASCII('a')
    WHILE @i <= ASCII('z')
    BEGIN
        SET @string = REPLACE( @string, ' ' + CHAR(@i), ' ' + CHAR(@i-32))
        SET @i = @i + 1
    END
    SET @string = CHAR(ASCII(LEFT(@string, 1))-32) + RIGHT(@string, LEN(@string)-1)
    RETURN @string
END

원하는 경우 공백 이외의 항목 뒤에 있는 문자를 쉽게 수정할 수 있습니다.

반복 CTE를 사용하는 루프 순수 세트 기반 접근 방식을 사용하지 않는 또 다른 솔루션

create function [dbo].InitCap (@value varchar(max))
returns varchar(max) as
begin

    declare
        @separator char(1) = ' ',
        @result varchar(max) = '';

    with r as (
        select value, cast(null as varchar(max)) [x], cast('' as varchar(max)) [char], 0 [no] from (select rtrim(cast(@value as varchar(max))) [value]) as j
        union all
        select right(value, len(value)-case charindex(@separator, value) when 0 then len(value) else charindex(@separator, value) end) [value]
        , left(r.[value], case charindex(@separator, r.value) when 0 then len(r.value) else abs(charindex(@separator, r.[value])-1) end ) [x]
        , left(r.[value], 1)
        , [no] + 1 [no]
        from r where value > '')

    select @result = @result +
    case
        when ascii([char]) between 97 and 122 
            then stuff(x, 1, 1, char(ascii([char])-32))
        else x
    end + @separator
    from r where x is not null;

    set @result = rtrim(@result);

    return @result;
end

Oracle/PLSQL에서 동일한 질문에 대한 답을 찾고 있다면 INITCAP 함수를 사용할 수 있습니다.다음은 테이블 부서의 속성 d 이름에 대한 예로, 값은 '영업', '관리', '생산', '개발'입니다.

SQL> select INITCAP(dname) from department;

INITCAP(DNAME)
--------------------------------------------------
Sales
Management
Production
Development
;WITH StudentList(Name) AS (
      SELECT CONVERT(varchar(50), 'Carl-VAN')
UNION SELECT 'Dean o''brian'
UNION SELECT 'Andrew-le-Smith'
UNION SELECT 'Eddy thompson'
UNION SELECT 'BOBs-your-Uncle'
), Student AS (
    SELECT CONVERT(varchar(50), UPPER(LEFT(Name, 1)) + LOWER(SUBSTRING(Name, 2, LEN(Name)))) Name, 
           pos = PATINDEX('%[-'' ]%', Name)
    FROM StudentList
    UNION ALL
    SELECT CONVERT(varchar(50), LEFT(Name, pos) + UPPER(SUBSTRING(Name, pos + 1, 1)) + SUBSTRING(Name, pos + 2, LEN(Name))) Name, 
           pos = CASE WHEN PATINDEX('%[-'' ]%', RIGHT(Name, LEN(Name) - pos)) = 0 THEN 0 ELSE pos + PATINDEX('%[-'' ]%', RIGHT(Name, LEN(Name) - pos)) END
    FROM Student
    WHERE pos > 0
)
SELECT Name
FROM Student 
WHERE pos = 0
ORDER BY Name 

이로 인해 다음과 같은 결과가 발생합니다.

  • 앤드루 르 스미스
  • 봅-유어-삼촌
  • 칼반
  • 딘 오브라이언
  • 에디 톰슨

재귀 CTE 세트 기반 쿼리를 사용하면 루프 쿼리 중 절차적으로 수행해야 합니다.여기서 나는 또한 나의 분리를 더 발전된 예를 위해 1이 아닌 3개의 다른 문자 [-' ]로 만들었습니다.제가 했던 것처럼 PATINDEX를 사용하면 많은 캐릭터를 찾을 수 있습니다.또한 단일 문자에 대해 CHARINDEX를 사용할 수 있으며 이 함수는 세 번째 매개 변수 StartFromPosition을 제외하므로 (공백 포함) pos = CHARINDEX(', 이름, pos + 1)로의 포스 공식 재귀의 두 번째 부분을 더 간단하게 수행할 수 있습니다.

제안된 기능은 정상적으로 작동하지만, 생성하지 않으려는 기능은 다음과 같습니다.

select ID,Name
,string_agg(concat(upper(substring(value,1,1)),lower(substring(value,2,len(value)-1))),' ') as ModifiedName 
from Table_Customer 
cross apply String_Split(replace(trim(Name),'  ',' '),' ')
where Name is not null
group by ID,Name;

위의 쿼리는 단어를 공백(' ')으로 나누고 하나의 하위 문자열을 가진 각각의 다른 행을 만든 다음 각 하위 문자열의 첫 번째 문자를 위쪽으로 변환하고 아래쪽으로 유지합니다.마지막 단계는 키를 기준으로 집계를 문자열로 묶는 것입니다.

fname은 fname 값이 khil이면 열 이름입니다. UPPER(왼쪽(fname,1))는 대문자(A)와 하위 문자열 함수 SUBSTRING(fname,2,LEN(fname))을 제공합니다. 둘 다 +를 사용하여 (khil)을 제공하고 결과는 (Akhil)입니다.

select UPPER(left(fname,1))+SUBSTRING(fname,2,LEN(fname)) as fname
FROM [dbo].[akhil]
BEGIN
DECLARE @string varchar(100) = 'asdsadsd asdad asd'
DECLARE @ResultString varchar(200) = ''
DECLARE @index int = 1
DECLARE @flag bit = 0
DECLARE @temp varchar(2) = ''
WHILE (@Index <LEN(@string)+1)
    BEGIN
        SET @temp = SUBSTRING(@string, @Index-1, 1)
        --select @temp
        IF @temp = ' ' OR @index = 1
            BEGIN
                SET @ResultString = @ResultString + UPPER(SUBSTRING(@string, @Index, 1))
            END
        ELSE
            BEGIN
                
                SET @ResultString = @ResultString + LOWER(SUBSTRING(@string, @Index, 1)) 
            END 

        SET @Index = @Index+ 1--increase the index
    END
SELECT @ResultString
END

이는 다음과 같이 간단할 수 있습니다.

DECLARE @Name VARCHAR(500) = 'Roger';

SELECT @Name AS Name, UPPER(LEFT(@Name, 1)) + SUBSTRING(@Name, 2, LEN(@Name)) AS CapitalizedName;

enter image description here

JSON을 사용하여 SQL Server 2016+에서 다음과 같은 단어의 순서를 보장합니다.

CREATE FUNCTION [dbo].[InitCap](@Text NVARCHAR(MAX))
RETURNS NVARCHAR(MAX)
AS
BEGIN
    RETURN STUFF((
        SELECT ' ' + UPPER(LEFT(s.value,1)) + LOWER(SUBSTRING(s.value,2,LEN(s.value)))
        FROM OPENJSON('["' + REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(@Text,'\','\\'),'"','\"'),CHAR(9),'\t'),CHAR(10),'\n'),' ','","') + '"]') s
        ORDER BY s.[key]
    FOR XML PATH(''),TYPE).value('(./text())[1]','NVARCHAR(MAX)'),1,1,'');
END
GO
CREATE FUNCTION [dbo].[Capitalize](@text NVARCHAR(MAX)) RETURNS NVARCHAR(MAX) AS
BEGIN
    DECLARE @result NVARCHAR(MAX) = '';
    DECLARE @c NVARCHAR(1);
    DECLARE @i INT = 1;
    DECLARE @isPrevSpace BIT = 1;

    WHILE @i <= LEN(@text)
    BEGIN
        SET @c = SUBSTRING(@text, @i, 1);
        SET @result += IIF(@isPrevSpace = 1, UPPER(@c), LOWER(@c));
        SET @isPrevSpace = IIF(@c LIKE '[    -]', 1, 0);
        SET @i += 1;
    END
    RETURN @result;
END
GO

DECLARE @sentence NVARCHAR(100) = N'i-thINK-this    soLUTION-works-LiKe-a charm';
PRINT dbo.Capitalize(@sentence);
-- I-Think-This Solution-Works-Like-A Charm

이를 위한 가장 간단한 한 줄기 방법은 다음과 같습니다.

SELECT LEFT(column, 1)+ lower(RIGHT(column, len(column)-1) ) FROM [tablename]

단순한 sql 스크립트를 다시 작성하는 가장 좋은 방법을 찾고 있었습니다.

SELECT dbo 사용 방법.Capitalize('이것은 여러 개의 공백이 있는 검정입니다')

결과 "여러 개의 공백이 있는 테스트입니다."

CREATE FUNCTION Capitalyze(@input varchar(100) )
    returns varchar(100)
as
begin
    
    declare @index int=0
    declare @char as varchar(1)=' '
    declare @prevCharIsSpace as bit=1
    declare @Result as varchar(100)=''

    set @input=UPPER(LEFT(@input,1))+LOWER(SUBSTRING(@input, 2, LEN(@input)))
    set @index=PATINDEX('% _%',@input)
    if @index=0
        set @index=len(@input)
    set @Result=substring(@input,0,@index+1)

    WHILE (@index < len(@input))
    BEGIN
        SET @index = @index + 1
        SET @char=substring(@input,@index,1)
        if (@prevCharIsSpace=1)
        begin
            set @char=UPPER(@char)
            if (@char=' ')
                set @char=''
        end

        if (@char=' ')
            set @prevCharIsSpace=1
        else
            set @prevCharIsSpace=0

        set @Result=@Result+@char
        --print @Result
    END
    --print @Result
    return @Result
end
IF OBJECT_ID ('dbo.fnCapitalizeFirstLetterAndChangeDelimiter') IS NOT NULL
    DROP FUNCTION dbo.fnCapitalizeFirstLetterAndChangeDelimiter
GO

CREATE FUNCTION [dbo].[fnCapitalizeFirstLetterAndChangeDelimiter] (@string NVARCHAR(MAX), @delimiter NCHAR(1), @new_delimeter NCHAR(1))
RETURNS NVARCHAR(MAX)
AS 
BEGIN
    DECLARE @result NVARCHAR(MAX)
    SELECT @result = '';
    IF (LEN(@string) > 0)
        DECLARE @curr INT
        DECLARE @next INT
        BEGIN
            SELECT @curr = 1
            SELECT @next = CHARINDEX(@delimiter, @string)
            WHILE (LEN(@string) > 0)
                BEGIN
                    SELECT @result = 
                        @result + 
                        CASE WHEN LEN(@result) > 0 THEN @new_delimeter ELSE '' END +
                        UPPER(SUBSTRING(@string, @curr, 1)) + 
                        CASE 
                            WHEN @next <> 0 
                            THEN LOWER(SUBSTRING(@string, @curr+1, @next-2))
                            ELSE LOWER(SUBSTRING(@string, @curr+1, LEN(@string)-@curr))
                        END
                    IF (@next > 0)
                        BEGIN
                            SELECT @string = SUBSTRING(@string, @next+1, LEN(@string)-@next)
                            SELECT @next = CHARINDEX(@delimiter, @string)
                        END
                    ELSE
                        SELECT @string = ''
                END
        END
    RETURN @result
END
GO

언급URL : https://stackoverflow.com/questions/55054/how-to-capitalize-the-first-letter-of-each-word-in-a-string-in-sql-server

반응형