SQL Server: Biến tất cả trường hợp UPPER thành trường hợp / trường hợp tiêu đề thích hợp


95

Tôi có một bảng đã được nhập dưới dạng tất cả TRƯỜNG HỢP LÊN và tôi muốn chuyển nó thành Trường hợp thích hợp. Bạn đã sử dụng kịch bản nào để hoàn thành việc này?


4
Chỉ cần lưu ý rằng việc thay đổi văn bản viết hoa thành văn bản viết hoa thích hợp có thể yêu cầu sửa chữa thủ công trong một số trường hợp. Ví dụ với tên: Tôi không đánh giá cao các ứng dụng viết sai chính tả tên của tôi.
Dave DuPlantis 23/10/08

2
Sẽ không có chức năng nào trên trái đất hoạt động đúng 'DAVE DUPLANTIS'. Dữ liệu viết hoa tự nó là một WTF lớn, vì hầu hết thời gian nó chỉ là một vấn đề trình bày.
Tomalak 23/10/08

1
Tôi biết một Macdonald trở nên tức giận khi anh ta được phong là MacDonald. Và tôi cũng đánh giá cao vỏ bọc phù hợp của O'Keefe.
DOK

@Tomalak: khá đúng, đó là lý do tại sao bạn nên chấp nhận dữ liệu dạng hỗn hợp và bảo toàn dữ liệu đó khi sự lựa chọn là của bạn. Hoàn toàn đồng ý về phần WTF ... đặc biệt nếu bạn chấp nhận các ký tự "quốc tế".
Dave DuPlantis 23/10/08

Đó cũng là một vấn đề văn hóa. Theo kinh nghiệm của tôi, người Anh và người Pháp có thói quen viết hoa họ ở bất cứ đâu họ có cơ hội. Tôi chỉ không hiểu, nó không có giá trị gì.
Tomalak

Câu trả lời:


88

Đây là một UDF sẽ thực hiện thủ thuật ...

create function ProperCase(@Text as varchar(8000))
returns varchar(8000)
as
begin
  declare @Reset bit;
  declare @Ret varchar(8000);
  declare @i int;
  declare @c char(1);

  if @Text is null
    return null;

  select @Reset = 1, @i = 1, @Ret = '';

  while (@i <= len(@Text))
    select @c = substring(@Text, @i, 1),
      @Ret = @Ret + case when @Reset = 1 then UPPER(@c) else LOWER(@c) end,
      @Reset = case when @c like '[a-zA-Z]' then 0 else 1 end,
      @i = @i + 1
  return @Ret
end

Bạn vẫn sẽ phải sử dụng nó để cập nhật dữ liệu của mình.


15
Điều này sẽ nổ tung đối với đầu vào không phải tiếng Anh.
Tomalak 23/10/08

Cảm ơn! hoạt động đầu tiên, ngay cả trên Azure SQL Server :)
Aaron

Tôi có thể chỉ hỏi cơ sở dữ liệu và bảng này đi vào gì không?
v3nt

2
Đã thử điều này với SQL Server 2008 và tất cả các loại dấu, hoạt động như một sự quyến rũ. Nó phụ thuộc vào thực tế trên collation
Baptiste

Cảm ơn! Nó cho kết quả như mong đợi.
Palak Patel

109

Chức năng này:

  • "Trường hợp thích hợp" tất cả các từ "TRƯỜNG HỢP LÊN" được phân cách bằng khoảng trắng
  • để riêng "các từ viết thường"
  • hoạt động bình thường ngay cả đối với các bảng chữ cái không phải tiếng Anh
  • có tính di động ở chỗ nó không sử dụng các tính năng ưa thích của các phiên bản máy chủ SQL gần đây
  • có thể dễ dàng thay đổi để sử dụng NCHAR và NVARCHAR để hỗ trợ unicode, cũng như bất kỳ độ dài thông số nào bạn thấy phù hợp
  • định nghĩa khoảng trắng có thể được cấu hình
CREATE FUNCTION ToProperCase(@string VARCHAR(255)) RETURNS VARCHAR(255)
AS
BEGIN
  DECLARE @i INT           -- index
  DECLARE @l INT           -- input length
  DECLARE @c NCHAR(1)      -- current char
  DECLARE @f INT           -- first letter flag (1/0)
  DECLARE @o VARCHAR(255)  -- output string
  DECLARE @w VARCHAR(10)   -- characters considered as white space

  SET @w = '[' + CHAR(13) + CHAR(10) + CHAR(9) + CHAR(160) + ' ' + ']'
  SET @i = 1
  SET @l = LEN(@string)
  SET @f = 1
  SET @o = ''

  WHILE @i <= @l
  BEGIN
    SET @c = SUBSTRING(@string, @i, 1)
    IF @f = 1 
    BEGIN
     SET @o = @o + @c
     SET @f = 0
    END
    ELSE
    BEGIN
     SET @o = @o + LOWER(@c)
    END

    IF @c LIKE @w SET @f = 1

    SET @i = @i + 1
  END

  RETURN @o
END

Kết quả:

dbo.ToProperCase('ALL UPPER CASE and    SOME lower ÄÄ ÖÖ ÜÜ ÉÉ ØØ ĈĈ ÆÆ')
-----------------------------------------------------------------
All Upper Case and      Some lower Ää Öö Üü Éé Øø Cc Ææ

1
Đây chắc chắn là giải pháp thân thiện với quốc tế nhất. Nó có phiếu bầu của tôi. Giả thiết duy nhất ở đây là một khoảng trắng ngăn cách các từ.
Cervo

3
Nó có thể là chỉ mục nên bắt đầu từ 1? Chuỗi con đầu tiên (, 0,1) trả về <empty>. Tôi đang chạy SQLServer2005
Tháng Một

10
Bạn có thể nên bao gồm một dấu nháy đơn dưới dạng một ký tự khoảng trắng theo mặc định để một cái tên như O'DONNELLsẽ không thay đổi thành O'donnell.
JustinStolle

2
@Tomalak biến @i nên bắt đầu tại một trong, nếu không một không gian được thêm vào phía trước đầu ra
Jakub

5
Chức năng nhỏ tuyệt vời. Không phải OP yêu cầu nó, nhưng nếu ai đó muốn thay đổi nó để nó không bỏ qua các từ đã viết thường và chuyển đổi chúng, ví dụ: "tom bombadil" thành "Tom Bombadil", chỉ cần thay đổi một dòng này - SET @o = @o + @cđến SET @o = @o + UPPER(@c). =)
NateJ

41
UPDATE titles
  SET title =
      UPPER(LEFT(title, 1)) +
        LOWER(RIGHT(title, LEN(title) - 1))

http://sqlmag.com/t-sql/how-title-case-column-value


8
FYI điều này hoạt động cho các giá trị từ đơn lẻ, nhưng không hoạt động cho các giá trị từ nhiều. Vì vậy, "NORTH CAROLINA" trở thành "North carolina" thay vì "North Carolina".
molaro

4
+1 dưới dạng giải pháp từ đơn đơn giản phù hợp với tôi. Điều duy nhất - bạn có thể gặp lỗi nếu titletrống.
Serg

@molaro thực hiện phân chia không gian và thao tác với từng từ riêng lẻ. Giải pháp tốt nhưng có một chút hạn chế về độ dài của các khả năng. Đối với những người xem trong tương lai, có thể muốn tách từ đầu tiên trong câu của bạn và chữ cái đầu tiên trên chữ cái đầu tiên.
GoldBishop

1
Thêm WHERE title IS NOT NULLvào cuối để giải quyết vấn đề của @Serg.
Paul

@Serg Tôi đã chỉnh sửa mã để nó không chạy lỗi trên các chuỗi có độ dài bằng 0 bằng cách sử dụng SUBSTRINGthay thếRIGHT
robotik

18

Nếu bạn có thể kích hoạt CLR trong SQL Server (yêu cầu 2005 trở lên) thì bạn có thể tạo một hàm CLR sử dụng hàm tích hợp TextInfo.ToTitleCase sẽ cho phép bạn tạo ra một cách hiểu biết về văn hóa để thực hiện việc này chỉ trong một số dòng mã.


Tôi cũng phải bỏ phiếu ở đây. CNTT an toàn quốc tế và sử dụng thư viện của người khác, nơi có thể chứa đầy đủ các loại kiểm tra. Bạn không thể sai ở đây :)
Cervo

8

Tôi biết đây là bài đăng muộn trong chủ đề này nhưng, đáng xem. Chức năng này hoạt động cho tôi mọi lúc. Vì vậy, nghĩ đến việc chia sẻ nó.

CREATE FUNCTION [dbo].[fnConvert_TitleCase] (@InputString VARCHAR(4000) )
RETURNS VARCHAR(4000)
AS
BEGIN
DECLARE @Index INT
DECLARE @Char CHAR(1)
DECLARE @OutputString VARCHAR(255)

SET @OutputString = LOWER(@InputString)
SET @Index = 2
SET @OutputString = STUFF(@OutputString, 1, 1,UPPER(SUBSTRING(@InputString,1,1)))

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

RETURN ISNULL(@OutputString,'')
END

Kiểm tra cuộc gọi:

select dbo.fnConvert_TitleCase(Upper('ÄÄ ÖÖ ÜÜ ÉÉ ØØ ĈĈ ÆÆ')) as test
select dbo.fnConvert_TitleCase(upper('Whatever the mind of man can conceive and believe, it can achieve. – Napoleon hill')) as test

Các kết quả:

nhập mô tả hình ảnh ở đây


Bạn có thể mô tả lý do tại sao nó tốt hơn sau đó hàm ToProperCase của Tomalak stackoverflow.com/questions/230138/… ?
Michael Freidgeim

1
Dựa trên các ví dụ được đưa ra với câu trả lời này và của Tomalak cùng với mô tả của Tomalak về những gì nó làm ("chỉ để lại các từ viết thường"), câu trả lời này tốt hơn. Tôi không xác minh câu trả lời của Tomalak, nhưng câu trả lời này phù hợp với trường hợp đầu vào (theo như nhu cầu của tôi có thể xác minh). "Chữ thường là bất kỳ văn bản nào được viết hoa với mỗi chữ cái đầu tiên của mỗi từ được viết hoa." - computerhope.com/jargon/p/proper-case.htm
Morvael

8

Tôi hơi muộn trong trò chơi, nhưng tôi tin rằng điều này có nhiều chức năng hơn và nó hoạt động với bất kỳ ngôn ngữ nào, bao gồm tiếng Nga, tiếng Đức, tiếng Thái, tiếng Việt, v.v. Nó sẽ viết hoa bất kỳ thứ gì sau 'hoặc - hoặc. hoặc (hoặc) hoặc dấu cách (rõ ràng :).

CREATE FUNCTION [dbo].[fnToProperCase]( @name nvarchar(500) )
RETURNS nvarchar(500)
AS
BEGIN
declare @pos    int = 1
      , @pos2   int

if (@name <> '')--or @name = lower(@name) collate SQL_Latin1_General_CP1_CS_AS or @name = upper(@name) collate SQL_Latin1_General_CP1_CS_AS)
begin
    set @name = lower(rtrim(@name))
    while (1 = 1)
    begin
        set @name = stuff(@name, @pos, 1, upper(substring(@name, @pos, 1)))
        set @pos2 = patindex('%[- ''.)(]%', substring(@name, @pos, 500))
        set @pos += @pos2
        if (isnull(@pos2, 0) = 0 or @pos > len(@name))
            break
    end
end

return @name
END
GO

Này hoạt động tốt ngoại trừ việc "nhà jack của" trở thành "Jack CỦA House"
Damien

2
Jack's House không phải là tên của một người. O'Brian, O'Connell là những cái tên :) Nếu bạn không đối phó riêng với tên của mọi người thì cần phải thay đổi.
Alansoft

3

Nếu bạn đang ở trong SSIS nhập dữ liệu có phân biệt hỗn hợp và cần thực hiện tra cứu trên một cột có chữ hoa phù hợp, bạn sẽ nhận thấy rằng việc tra cứu không thành công khi nguồn được kết hợp và nguồn tra cứu phù hợp. Bạn cũng sẽ nhận thấy rằng bạn không thể sử dụng các chức năng phải và trái là SSIS cho SQL Server 2008r2 cho các cột dẫn xuất. Đây là một giải pháp phù hợp với tôi:

UPPER(substring(input_column_name,1,1)) + LOWER(substring(input_column_name, 2, len(input_column_name)-1))

2

Đây là một phiên bản sử dụng bảng chuỗi hoặc số thay vì một vòng lặp. Bạn có thể sửa đổi mệnh đề WHERE để phù hợp với các quy tắc cá nhân của mình về thời điểm chuyển một ký tự thành chữ hoa. Tôi vừa bao gồm một tập hợp đơn giản sẽ viết hoa bất kỳ ký tự nào được tiếp tục bởi một ký tự không phải ký tự, ngoại trừ dấu nháy đơn. Điều này không bao giờ có nghĩa là 123apple sẽ khớp với "a" vì "3" không phải là một chữ cái. Nếu bạn chỉ muốn khoảng trắng (dấu cách, tab, xuống dòng, nguồn cấp dữ liệu dòng), bạn có thể thay thế mẫu '[^a-z]'bằng '[' + Char(32) + Char(9) + Char(13) + Char(10) + ']'.


CREATE FUNCTION String.InitCap( @string nvarchar(4000) ) RETURNS nvarchar(4000) AS
BEGIN

-- 1. Convert all letters to lower case
    DECLARE @InitCap nvarchar(4000); SET @InitCap = Lower(@string);

-- 2. Using a Sequence, replace the letters that should be upper case with their upper case version
    SELECT @InitCap = Stuff( @InitCap, n, 1, Upper( SubString( @InitCap, n, 1 ) ) )
    FROM (
        SELECT (1 + n1.n + n10.n + n100.n + n1000.n) AS n
        FROM       (SELECT 0 AS n UNION SELECT    1 UNION SELECT    2 UNION SELECT    3 UNION SELECT    4 UNION SELECT    5 UNION SELECT    6 UNION SELECT    7 UNION SELECT    8 UNION SELECT    9) AS    n1
        CROSS JOIN (SELECT 0 AS n UNION SELECT   10 UNION SELECT   20 UNION SELECT   30 UNION SELECT   40 UNION SELECT   50 UNION SELECT   60 UNION SELECT   70 UNION SELECT   80 UNION SELECT   90) AS   n10
        CROSS JOIN (SELECT 0 AS n UNION SELECT  100 UNION SELECT  200 UNION SELECT  300 UNION SELECT  400 UNION SELECT  500 UNION SELECT  600 UNION SELECT  700 UNION SELECT  800 UNION SELECT  900) AS  n100
        CROSS JOIN (SELECT 0 AS n UNION SELECT 1000 UNION SELECT 2000 UNION SELECT 3000)                                                                                                             AS n1000
        ) AS Sequence
    WHERE 
        n BETWEEN 1 AND Len( @InitCap )
    AND SubString( @InitCap, n, 1 ) LIKE '[a-z]'                 /* this character is a letter */
    AND (
        n = 1                                                    /* this character is the first `character` */
        OR SubString( @InitCap, n-1, 1 ) LIKE '[^a-z]'           /* the previous character is NOT a letter */
        )
    AND (
        n < 3                                                    /* only test the 3rd or greater characters for this exception */
        OR SubString( @InitCap, n-2, 3 ) NOT LIKE '[a-z]''[a-z]' /* exception: The pattern <letter>'<letter> should not capatolize the letter following the apostrophy */
        )

-- 3. Return the modified version of the input
    RETURN @InitCap

END

1

Liên kết mà tôi đã đăng ở trên là một lựa chọn tuyệt vời giải quyết vấn đề chính: rằng chúng ta không bao giờ có thể tính toán theo chương trình cho tất cả các trường hợp (Smith-Jones, von Haussen, John Smith MD), ít nhất là không theo cách lịch sự. Tony đưa ra khái niệm về một nhân vật ngoại lệ / phá vỡ để đối phó với những trường hợp này. Dù sao, xây dựng dựa trên ý tưởng của Cervo (trên tất cả các ký tự dưới đứng trước khoảng trắng), các câu lệnh thay thế có thể được gói gọn trong một bảng thay thế dựa trên thay thế. Thực sự, mọi tổ hợp ký tự thấp / lên đều có thể được chèn vào @alpha và câu lệnh sẽ không thay đổi:

declare @str    nvarchar(8000)
declare @alpha  table (low nchar(1), up nchar(1))


set @str = 'ALL UPPER CASE and    SOME lower ÄÄ ÖÖ ÜÜ ÉÉ ØØ ĈĈ ÆÆ'

-- stage the alpha (needs number table)
insert into @alpha
    -- A-Z / a-z
    select      nchar(n+32),
                nchar(n)
    from        dbo.Number
    where       n between 65 and 90 or
                n between 192 and 223

-- append space at start of str
set @str = lower(' ' + @str)

-- upper all lower case chars preceded by space
select  @str = replace(@str, ' ' + low, ' ' + up) 
from    @Alpha

select @str

Tuy nhiên, một giải pháp duy nhất của US-ASCII.
Tomalak

Bạn vẫn xem đây là giải pháp lấy Hoa Kỳ làm trung tâm vì nó tham chiếu đến các ký tự unicode. Tôi biết bài đăng ban đầu sử dụng AZ ascii resultset, nhưng điểm của giải pháp là sự ghép nối theo hướng bảng của các ký tự trên: dưới. Câu lệnh Replace chỉ tham chiếu đến bảng.
Nathan Skerl 27/10/08

chỉnh sửa: Tôi đã cập nhật ví dụ để sử dụng đầu vào mẫu của bạn. Thanks cho bất kỳ thông tin phản hồi
Nathan Skerl

Có cách nào "không thanh lịch" để xử lý hầu hết các biến thể được biết đến cho các tên không có dấu gạch nối không? Như 'Mc', O'C, và những gì không?
Merritt

1

Sẽ rất hợp lý nếu bạn duy trì việc tra cứu các trường hợp ngoại lệ để chăm sóc The von Neumann's, McCain's, DeGuzman's, and the Johnson-Smith's.


1

Đã mượn và cải thiện câu trả lời của @Richard Sayakanit. Điều này xử lý nhiều từ. Giống như câu trả lời của anh ấy, điều này không sử dụng bất kỳ UDF nào, chỉ có các chức năng được tích hợp sẵn ( STRING_SPLITSTRING_AGG) và nó khá nhanh. STRING_AGGyêu cầu SQL Server 2017 nhưng bạn luôn có thể sử dụng STUFF/XMLthủ thuật này. Sẽ không xử lý mọi ngoại lệ nhưng có thể hoạt động tốt cho nhiều yêu cầu.

SELECT StateName = 'North Carolina' 
INTO #States
UNION ALL
SELECT 'Texas'


;WITH cteData AS 
(
    SELECT 
        UPPER(LEFT(value, 1)) +
            LOWER(RIGHT(value, LEN(value) - 1)) value, op.StateName
    FROM   #States op
    CROSS APPLY STRING_SPLIT(op.StateName, ' ') AS ss
)
SELECT 
    STRING_AGG(value, ' ')
FROM cteData c 
GROUP BY StateName

1

Một sửa đổi nhỏ cho câu trả lời của @ Gal Na Uy - biến ví dụ St Elizabeth'sthành St Elizabeth'S.

Việc sửa đổi này giữ cho dấu nháy đơn ở dạng chữ thường trong đó s ở cuối chuỗi được cung cấp hoặc s được theo sau bởi một khoảng trắng (và chỉ trong những trường hợp đó).

create function properCase(@text as varchar(8000))
returns varchar(8000)
as
begin
    declare @reset int;
    declare @ret varchar(8000);
    declare @i int;
    declare @c char(1);
    declare @d char(1);

    if @text is null
    return null;

    select @reset = 1, @i = 1, @ret = '';

    while (@i <= len(@text))
    select
        @c = substring(@text, @i, 1),
        @d = substring(@text, @i+1, 1),
        @ret = @ret + case when @reset = 1 or (@reset=-1 and @c!='s') or (@reset=-1 and @c='s' and @d!=' ') then upper(@c) else lower(@c) end,
        @reset = case when @c like '[a-za-z]' then 0 when @c='''' then -1 else 1 end,
        @i = @i + 1
    return @ret
end

Nó rẽ:

  • st elizabeth's thành St Elizabeth's
  • o'keefe thành O'Keefe
  • o'sullivan thành O'Sullivan

Ý kiến ​​của những người khác rằng các giải pháp khác nhau phù hợp hơn cho đầu vào không phải tiếng Anh vẫn còn nguyên.


0

Tôi nghĩ rằng bạn sẽ thấy rằng cách sau là hiệu quả hơn:

IF OBJECT_ID('dbo.ProperCase') IS NOT NULL
    DROP FUNCTION dbo.ProperCase
GO
CREATE FUNCTION dbo.PROPERCASE (
    @str VARCHAR(8000))
RETURNS VARCHAR(8000)
AS
BEGIN
    SET @str = ' ' + @str
    SET @str = 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( @str, ' a', ' A'), ' b', ' B'), ' c', ' C'), ' d', ' D'), ' e', ' E'), ' f', ' F'), ' g', ' G'), ' h', ' H'), ' i', ' I'), ' j', ' J'), ' k', ' K'), ' l', ' L'), ' m', ' M'), ' n', ' N'), ' o', ' O'), ' p', ' P'), ' q', ' Q'), ' r', ' R'), ' s', ' S'), ' t', ' T'), ' u', ' U'), ' v', ' V'), ' w', ' W'), ' x', ' X'), ' y', ' Y'), ' z', ' Z')
    RETURN RIGHT(@str, LEN(@str) - 1)
END
GO

Câu lệnh thay thế có thể được cắt và dán trực tiếp vào một truy vấn SQL. Nó cực kỳ xấu, tuy nhiên bằng cách thay thế @str bằng cột mà bạn quan tâm, bạn sẽ không phải trả giá cho một con trỏ ngầm như bạn sẽ làm với các udfs đã đăng. Tôi thấy rằng ngay cả khi sử dụng UDF của mình, nó vẫn hiệu quả hơn nhiều.

Ồ và thay vì tạo câu lệnh thay thế bằng tay, hãy sử dụng điều này:

-- Code Generator for expression
DECLARE @x  INT,
    @c  CHAR(1),
    @sql    VARCHAR(8000)
SET @x = 0
SET @sql = '@str' -- actual variable/column you want to replace
WHILE @x < 26
BEGIN
    SET @c = CHAR(ASCII('a') + @x)
    SET @sql = 'REPLACE(' + @sql + ', '' ' + @c+  ''', '' ' + UPPER(@c) + ''')'
    SET @x = @x + 1
END
PRINT @sql

Dù sao nó phụ thuộc vào số lượng hàng. Tôi ước bạn chỉ có thể thực hiện s / \ b ([az]) / uc $ 1 /, nhưng chúng tôi làm việc với các công cụ chúng tôi có.

LƯU Ý bạn sẽ phải sử dụng điều này vì bạn sẽ phải sử dụng nó như .... CHỌN dbo.ProperCase (LOWER (cột)) vì cột được viết hoa. Nó thực sự hoạt động khá nhanh trên bảng 5.000 mục nhập (không đến một giây) của tôi ngay cả với mức thấp hơn.

Để đối phó với hàng loạt các bình luận liên quan đến quốc tế hóa, tôi trình bày cách triển khai sau đây xử lý mọi ký tự ascii chỉ dựa vào Thực hiện trên và dưới của SQL Server. Hãy nhớ rằng, các biến chúng ta đang sử dụng ở đây là VARCHAR có nghĩa là chúng chỉ có thể giữ các giá trị ASCII. Để sử dụng các bảng chữ cái quốc tế khác, bạn phải sử dụng NVARCHAR. Logic sẽ tương tự nhưng bạn sẽ cần sử dụng UNICODE và NCHAR thay cho ASCII AND CHAR và câu lệnh thay thế sẽ lớn hơn nhiều ....

-- Code Generator for expression
DECLARE @x  INT,
    @c  CHAR(1),
    @sql    VARCHAR(8000),
    @count  INT
SEt @x = 0
SET @count = 0
SET @sql = '@str' -- actual variable you want to replace
WHILE @x < 256
BEGIN
    SET @c = CHAR(@x)
    -- Only generate replacement expression for characters where upper and lowercase differ
    IF @x = ASCII(LOWER(@c)) AND @x != ASCII(UPPER(@c))
    BEGIN
        SET @sql = 'REPLACE(' + @sql + ', '' ' + @c+  ''', '' ' + UPPER(@c) + ''')'
        SET @count = @count + 1
    END
    SET @x = @x + 1
END
PRINT @sql
PRINT 'Total characters substituted: ' + CONVERT(VARCHAR(255), @count)

Về cơ bản, tiền đề của phương pháp của tôi là giao dịch tiền điện toán để đạt hiệu quả. Việc triển khai ASCII đầy đủ như sau:

IF OBJECT_ID('dbo.ProperCase') IS NOT NULL
    DROP FUNCTION dbo.ProperCase
GO
CREATE FUNCTION dbo.PROPERCASE (
    @str VARCHAR(8000))
RETURNS VARCHAR(8000)
AS
BEGIN
    SET @str = ' ' + @str
SET @str =     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(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(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(@str, ' a', ' A'), ' b', ' B'), ' c', ' C'), ' d', ' D'), ' e', ' E'), ' f', ' F'), ' g', ' G'), ' h', ' H'), ' i', ' I'), ' j', ' J'), ' k', ' K'), ' l', ' L'), ' m', ' M'), ' n', ' N'), ' o', ' O'), ' p', ' P'), ' q', ' Q'), ' r', ' R'), ' s', ' S'), ' t', ' T'), ' u', ' U'), ' v', ' V'), ' w', ' W'), ' x', ' X'), ' y', ' Y'), ' z', ' Z'), ' š', ' Š'), ' œ', ' Œ'), ' ž', ' Ž'), ' à', ' À'), ' á', ' Á'), ' â', ' Â'), ' ã', ' Ã'), ' ä', ' Ä'), ' å', ' Å'), ' æ', ' Æ'), ' ç', ' Ç'), ' è', ' È'), ' é', ' É'), ' ê', ' Ê'), ' ë', ' Ë'), ' ì', ' Ì'), ' í', ' Í'), ' î', ' Î'), ' ï', ' Ï'), ' ð', ' Ð'), ' ñ', ' Ñ'), ' ò', ' Ò'), ' ó', ' Ó'), ' ô', ' Ô'), ' õ', ' Õ'), ' ö', ' Ö'), ' ø', ' Ø'), ' ù', ' Ù'), ' ú', ' Ú'), ' û', ' Û'), ' ü', ' Ü'), ' ý', ' Ý'), ' þ', ' Þ'), ' ÿ', ' Ÿ')
    RETURN RIGHT(@str, LEN(@str) - 1)
END
GO

1
Vâng. Bảng chữ cái của bạn chỉ có 26 ký tự. Của tôi có nhiều hơn nữa. Còn tiếng Hy Lạp thì sao? Hay tiếng Thổ Nhĩ Kỳ?
Tomalak 23/10/08

Tôi cho rằng các giải pháp khác cũng làm như vậy. Nhưng tôi đã bao gồm trình tạo mã. Bạn chỉ có thể thêm các phần bổ sung cho bảng chữ cái của mình. Bạn sẽ phải có mọi thứ dưới dạng NVARCHAR và sử dụng NCHAR và UNICODE để chuyển đổi.
Cervo

Tôi nghĩ rằng bạn càng có nhiều ký tự thì nó sẽ càng kém hiệu quả. Nhưng quái trong một số bộ ký tự mỗi biểu tượng đại diện cho toàn bộ một từ như vậy toàn bộ vấn đề trường hợp thích hợp không áp dụng ....
Cervo

Ngoài ra, tôi nghi ngờ có ai đó sử dụng mọi ký tự unicode cùng một lúc. Vì vậy, có thể chỉ cần tạo mã thay thế cho 2 hoặc 3 bảng chữ cái bạn sử dụng.
Cervo

1
Điều đó không có nghĩa là bạn nên sử dụng các giải pháp chỉ sử dụng tiếng Anh nửa vời chỉ vì bạn mong đợi dữ liệu "có thể nằm trong bảng chữ cái của bạn". Theo hệ thống chữ viết Latinh, có chữ thường / hoa được xác định cho (hầu hết) bất kỳ ký tự nào. Các hàm chuyển đổi thiên về tính đúng đắn hơn là tốc độ.
Tomalak 23/10/08

0

Có quá muộn để quay lại và lấy dữ liệu chưa in hoa không?

Von Neumann's, McCain, DeGuzman's và Johnson-Smith's thuộc cơ sở khách hàng của bạn có thể không thích kết quả xử lý của bạn ...

Ngoài ra, tôi đoán rằng đây là mục đích nâng cấp dữ liệu một lần? Việc xuất, lọc / sửa đổi và nhập lại các tên đã sửa vào db có thể dễ dàng hơn và sau đó bạn có thể sử dụng các phương pháp tiếp cận không phải SQL để sửa tên ...


Toàn bộ vấn đề đặt tên đã đưa ra những nhược điểm có thể xảy ra khi được thảo luận - không có dấu hiệu nào cho thấy tác giả câu hỏi đề cập đến dữ liệu có chứa tên.
Tomalak

0

Đây là một biến thể khác mà tôi tìm thấy trên Diễn đàn SQLTeam.com @ http://www.sqlteam.com/forums/topic.asp?TOPIC_ID=47718

create FUNCTION PROPERCASE
(
--The string to be converted to proper case
@input varchar(8000)
)
--This function returns the proper case string of varchar type
RETURNS varchar(8000)
AS
BEGIN
IF @input IS NULL
BEGIN
--Just return NULL if input string is NULL
RETURN NULL
END

--Character variable declarations
DECLARE @output varchar(8000)
--Integer variable declarations
DECLARE @ctr int, @len int, @found_at int
--Constant declarations
DECLARE @LOWER_CASE_a int, @LOWER_CASE_z int, @Delimiter char(3), @UPPER_CASE_A int, @UPPER_CASE_Z int

--Variable/Constant initializations
SET @ctr = 1
SET @len = LEN(@input)
SET @output = ''
SET @LOWER_CASE_a = 97
SET @LOWER_CASE_z = 122
SET @Delimiter = ' ,-'
SET @UPPER_CASE_A = 65
SET @UPPER_CASE_Z = 90

WHILE @ctr <= @len
BEGIN
--This loop will take care of reccuring white spaces
WHILE CHARINDEX(SUBSTRING(@input,@ctr,1), @Delimiter) > 0
BEGIN
SET @output = @output + SUBSTRING(@input,@ctr,1)
SET @ctr = @ctr + 1
END

IF ASCII(SUBSTRING(@input,@ctr,1)) BETWEEN @LOWER_CASE_a AND @LOWER_CASE_z
BEGIN
--Converting the first character to upper case
SET @output = @output + UPPER(SUBSTRING(@input,@ctr,1))
END
ELSE
BEGIN
SET @output = @output + SUBSTRING(@input,@ctr,1)
END

SET @ctr = @ctr + 1

WHILE CHARINDEX(SUBSTRING(@input,@ctr,1), @Delimiter) = 0 AND (@ctr <= @len)
BEGIN
IF ASCII(SUBSTRING(@input,@ctr,1)) BETWEEN @UPPER_CASE_A AND @UPPER_CASE_Z
BEGIN
SET @output = @output + LOWER(SUBSTRING(@input,@ctr,1))
END
ELSE
BEGIN
SET @output = @output + SUBSTRING(@input,@ctr,1)
END
SET @ctr = @ctr + 1
END

END
RETURN @output
END



GO
SET QUOTED_IDENTIFIER OFF
GO
SET ANSI_NULLS ON
GO

0

Tôi biết ma quỷ ở trong chi tiết (đặc biệt là nơi dữ liệu cá nhân của mọi người có liên quan) và sẽ rất tuyệt nếu có những cái tên được viết hoa đúng cách, nhưng loại rắc rối ở trên là lý do tại sao những người thực dụng, ý thức về thời gian trong chúng ta lại sử dụng những cách sau :

SELECT UPPER('Put YoUR O'So oddLy casED McWeird-nAme von rightHERE here')

Theo kinh nghiệm của tôi, mọi người vẫn ổn khi nhìn thấy TÊN HỌ ... ngay cả khi mới đọc được nửa câu.

Tham khảo thêm: người Nga dùng bút chì!


3
Từ chối câu hỏi là không hữu ích. "Câu trả lời" này là một nhận xét TỐT NHẤT.
Phil

0

Vừa mới học về InitCap() .

Đây là một số mã mẫu:

SELECT ID
      ,InitCap(LastName ||', '|| FirstName ||' '|| Nvl(MiddleName,'')) AS RecipientName
FROM SomeTable

2
OP chỉ định Máy chủ Sql, 'InitCap ()' là một thứ của Oracle.
mxmissile

0

Điều này đã hoạt động trong SSMS:

Select Jobtitle,
concat(Upper(LEFT(jobtitle,1)), SUBSTRING(jobtitle,2,LEN(jobtitle))) as Propercase
From [HumanResources].[Employee]

0

Nếu bạn biết tất cả dữ liệu chỉ là một từ duy nhất thì đây là một giải pháp. Đầu tiên hãy cập nhật cột xuống tất cả thấp hơn và sau đó chạy phần sau

    update tableName set columnName = 
    upper(SUBSTRING(columnName, 1, 1)) + substring(columnName, 2, len(columnName)) from tableName

0

Gần đây đã phải giải quyết điều này và đưa ra những điều sau đây sau khi không có gì hoàn thành tốt mọi thứ tôi muốn. Điều này sẽ thực hiện toàn bộ một câu, các trường hợp xử lý từ đặc biệt. Chúng tôi cũng gặp vấn đề với các 'từ' ký tự đơn mà rất nhiều phương thức đơn giản xử lý được nhưng không phải các phương thức phức tạp hơn. Một biến trả về, không có vòng lặp hoặc con trỏ.

CREATE FUNCTION ProperCase(@Text AS NVARCHAR(MAX))
RETURNS NVARCHAR(MAX)
AS BEGIN

    DECLARE @return NVARCHAR(MAX)

    SELECT @return = COALESCE(@return + ' ', '') + Word FROM (
         SELECT CASE
            WHEN LOWER(value) = 'llc' THEN UPPER(value)
            WHEN LOWER(value) = 'lp' THEN UPPER(value) --Add as many new special cases as needed
            ELSE
               CASE WHEN LEN(value) = 1
               THEN UPPER(value)
               ELSE UPPER(LEFT(value, 1)) + (LOWER(RIGHT(value, LEN(value) - 1)))
              END
            END AS Word
         FROM STRING_SPLIT(@Text, ' ')
     ) tmp

     RETURN @return
END

0

Sao chép và dán dữ liệu của bạn vào MS Word và sử dụng tính năng chuyển đổi văn bản tích hợp thành "Viết hoa Mỗi Từ". So sánh với dữ liệu ban đầu của bạn để giải quyết các trường hợp ngoại lệ. Không thể thấy bất kỳ cách nào xung quanh việc lách các ngoại lệ loại "MacDonald" và "IBM" theo cách thủ công nhưng đây là cách tôi đã thực hiện FWIW.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.