SQL Server: Зробити всі ВЕРХНІ регістри відповідними регістром / заголовком


96

У мене є таблиця, яка була імпортована як ВЕРХНЯ СПРАВА, і я хотів би перетворити її на належну справу. Яким сценарієм хтось із вас скористався цим?


4
Тільки майте на увазі, що для правильного зміни тексту верхнього регістру на правильний регістр можуть знадобитися ручні виправлення в деяких, ну, випадках. Наприклад, з іменами: я не ціную програми, які неправильно пишуть моє ім’я.
Dave DuPlantis

2
На землі не буде жодної функції, яка могла б отримати правильне слово "ДЕЙВ ДУПЛАНТИС". Оновлення даних - це сам по собі WTF, оскільки більшість випадків це просто презентаційне питання.
Томалак

1
Я знаю Макдональда, який розлючений, коли його називають Макдональдом. І я дуже вдячний за належний кожух О'Кіф, будь ласка.
DOK

@Tomalak: цілком правильно, саме тому вам слід приймати змішані регістри та зберігати їх, коли вибір за вами. Повна згода щодо частини WTF ... особливо якщо ви приймаєте "міжнародних" символів.
Дейв ДуПлантіс

Це також культурне питання. З мого досвіду, британці та французи мають звичку прописувати прізвища, де б вони не мали можливості. Я просто не розумію, це не додає ніякої вартості.
Томалак,

Відповіді:


91

Ось СДС, який зробить трюк ...

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

Вам все одно доведеться використовувати його для оновлення даних.


15
Це підірветься для не англійської мови.
Томалак

Дякую! працював в першу чергу, навіть на Azure SQL Server :)
Аарон,

Чи можу я просто запитати, до якої бази даних і таблиці це входить?
v3nt,

2
Спробував це за допомогою SQL Server 2008 і всіляких акцентів, працював як шарм. Фактично це залежить від порівняння
Баптист

Дякую! Це дає результати, як очікувалося.
Palak Patel

109

Ця функція:

  • "Правильні випадки" - усі слова "ВЕРХНІЙ СПРАВИ", позначені пробілами
  • залишає "малі слова" в спокої
  • працює належним чином навіть для неанглійських алфавітів
  • є портативним, оскільки не використовує вигадливих функцій останніх версій сервера SQL
  • можна легко змінити, щоб використовувати NCHAR і NVARCHAR для підтримки Unicode, а також будь-яку довжину параметрів, яку ви вважаєте за потрібне
  • Визначення пробілів можна налаштувати
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

Результат:

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

1
Це, безумовно, найбільш дружнє міжнародне рішення. Це мій голос. Єдиним припущенням є те, що пробіл розділяє слова.
Черво

3
Чи може це бути, що індекс повинен починатися з 1? Перший підрядок (, 0,1) повертає <порожній>. Я запускаю sqlserver2005
січня

10
Ймовірно, ви повинні включити апостроф як пробіл за замовчуванням, щоб ім'я типу O'DONNELLне змінювалося на O'donnell.
JustinStolle

2
@Tomalak змінна @i повинна починатися з одиниці, інакше пробіл додається до виходу
Якуб

5
Відмінна маленька функція. Не те, щоб ОП просило цього, але якщо хтось хоче його змінити, щоб він не ігнорував уже малі слова, а також перетворив їх, наприклад, "tom bombadil" на "Tom Bombadil", просто змініть цей один рядок - SET @o = @o + @cдо 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 це працює для значень одного слова, але не для кількох значень слів. Тож "ПІВНІЧНА КАРОЛІНА" стає "Північною Кароліною" замість вилученої "Північної Кароліни".
molaro

4
+1 як просте рішення з одним словом, яке для мене добре працювало. Єдине - ви можете отримати помилку, якщо titleпусте.
Serg

@molaro розбиває простір і оперує кожним словом окремо. Хороше рішення, але трохи обмежує тривалість можливостей. Для майбутніх глядачів, можливо, захочеться розділити на термінаторі речення і першому випадку перше слово у реченні.
GoldBishop

1
Додайте WHERE title IS NOT NULLдо кінця, щоб вирішити проблему @Serg.
Павло

@Serg Я відредагував код, щоб він не запускав помилку на рядках нульової довжини, використовуючи SUBSTRINGзамістьRIGHT
robotik

18

Якщо ви можете ввімкнути CLR у SQL Server (потрібна версія 2005 або пізнішої версії), ви можете створити функцію CLR, яка використовує вбудовану функцію TextInfo.ToTitleCase, яка дозволить вам створити культурний спосіб зробити це лише за декілька рядки коду.


Я маю тут також голосувати. ІТ безпечні на міжнародному рівні і використовують чужу бібліотеку, яка, мабуть, повна всіляких перевірок. ВИ тут не можете помилитися :)
Черво

8

Я знаю, що це пізній пост у цій темі, але, варто подивитися. Ця функція працює для мене завжди. Тож думав поділитися цим.

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

Тестові дзвінки:

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

Результати:

введіть тут опис зображення


Можете чи ви описати , чому це краще , ніж ToProperCase функція Томалак в stackoverflow.com/questions/230138 / ... ?
Michael Freidgeim

1
На основі прикладів, наведених із цією відповіддю та описом Томалака, а також описом того, що він робить ("залишає лише малі слова"), ця відповідь є кращою. Я не перевіряв Томалака, але ця відповідь надає належний випадок (наскільки можуть підтвердити мої потреби). "Правильний регістр - це будь-який текст, написаний кожною з перших літер кожного слова, що пишеться великими літерами". - computerhope.com/jargon/p/proper-case.htm
Морвель,

8

Я трохи запізнююся в грі, але я вважаю, що це більш функціонально, і вона працює з будь-якою мовою, включаючи російську, німецьку, тайську, в'єтнамську і т.д. або (або) або пробіл (очевидно :).

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

Це добре працює, за винятком того, що "будинок Джека" стає "Дім Джека"
Демієн

2
Будинок Джека - це не ім’я людини. О'Бріан, О'Коннелл - це імена :) Якщо ви не маєте справу лише з іменем людей, потрібно змінити.
Alansoft

3

Якщо ви перебуваєте в імпорті даних SSIS, у яких змішані обстановки, і вам потрібно здійснити пошук у стовпці з належним регістром, ви помітите, що пошук не працює там, де джерело змішується та джерело пошуку є належним. Ви також помітите, що не можна використовувати праву та ліву функції - це SSIS для SQL Server 2008r2 для похідних стовпців. Ось рішення, яке мені підходить:

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

2

Ось версія, яка використовує таблицю послідовностей або чисел, а не цикл. Ви можете змінити речення WHERE, щоб відповідати вашим особистим правилам щодо перетворення символу у верхній регістр. Я щойно включив простий набір, який буде писати великі літери на будь-які літери, що переходять небуквеними, за винятком апострофів. Це означає, що коли-небудь означає, що 123apple матиме збіг на "а", оскільки "3" - це не буква. Якщо вам потрібні лише пробіли (пробіл, вкладка, повернення каретки, подача рядка), ви можете замінити шаблон '[^a-z]'на '[' + 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

Посилання, яке я розмістив вище, є чудовим варіантом, який вирішує головну проблему: ми ніколи не можемо програмно враховувати всі випадки (Сміт-Джонс, фон Хауссен, Джон Сміт, доктор медичних наук), принаймні не елегантно. Тоні вводить поняття винятку / зламаного персонажа для вирішення цих випадків. У будь-якому випадку, спираючись на ідею Черво (верхні всі нижні символи, перед якими стоїть пробіл), замість цього оператори replace можуть бути заміщені в одну таблицю на основі заміни. Дійсно, будь-яка комбінація символів з низьким та вгору значенням може бути вставлена ​​в @alpha, і вираз не зміниться:

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

Ще одне рішення, призначене лише для США та ASCII.
Томалак,

Ви все ще розглядаєте це як орієнтоване на США рішення, оскільки воно посилається на символи Unicode. Я знаю, що в оригінальному розміщенні використовувався AZ ascii набір результатів, але сенс рішення полягає в тому, що його табличне керування поєднанням верхнього: нижнього символів. Заява заміни просто посилається на таблицю.
Натан Скерл,

редагувати: я оновив приклад, щоб використати ваш зразок введення. Дякуємо за будь-який відгук
Натан Скерл

Чи існує "неелегантний" спосіб обробки найвідоміших варіантів імен, які не переносяться? Як "Mc", O'C, а що ні?
Мерріт

1

Мало б сенс вести пошук винятків, щоб піклуватися про фон Неймана, Маккейна, ДеГузмана та Джонсона-Сміта.


1

Відповідь @Richard Sayakanit запозичив та вдосконалив. Це обробляє кілька слів. Як і його відповідь, тут не використовуються UDF, лише вбудовані функції ( STRING_SPLITі STRING_AGG), і це досить швидко. STRING_AGGпотрібен SQL Server 2017, але ви завжди можете скористатися STUFF/XMLфокусом. Не впорається з кожним винятком, але може чудово працювати для багатьох вимог.

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

Невелика модифікація відповіді @ Галвезької - яка перетворюється, наприклад, St Elizabeth'sу St Elizabeth'S.

Ця модифікація зберігає апострофи як малі регістри, де s в кінці рядка, що надається, або s після пробілу (і лише за таких обставин).

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

Виходить:

  • st elizabeth's в St Elizabeth's
  • o'keefe в O'Keefe
  • o'sullivan в O'Sullivan

Зауваження інших, що різні варіанти є кращими для введення не англійською мовою, залишаються такими.


0

Я думаю, ви виявите, що наступне є більш ефективним:

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

Оператор replace можна вирізати та вставити безпосередньо в запит SQL. Це дуже некрасиво, проте, замінивши @str на потрібний вам стовпець, ви не заплатите ціну за неявний курсор, як ви будете за розміщений таким чином udfs. Я вважаю, що навіть використання мого UDF набагато ефективніше.

О, і замість того, щоб генерувати оператор replace вручну, використовуйте це:

-- 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

У будь-якому випадку це залежить від кількості рядків. Я хотів би, щоб ти міг просто зробити s / \ b ([az]) / uc $ 1 /, але ну ми добре працюємо з наявними у нас інструментами.

ПРИМІТКА - вам потрібно було б використовувати це, як це було б потрібно використовувати як .... SELECT dbo.ProperCase (LOWER (стовпець)), оскільки стовпець у верхньому регістрі. Це фактично працює досить швидко на моєму столі з 5000 записів (навіть не на одну секунду) навіть з нижньою.

У відповідь на безліч коментарів щодо інтернаціоналізації я представляю наступну реалізацію, яка обробляє кожен символ ascii, покладаючись лише на реалізацію SQL Server верхнього та нижнього рівня. Пам’ятайте, ми використовуємо тут змінні VARCHAR, що означає, що вони можуть містити лише значення ASCII. Для того, щоб використовувати подальші міжнародні алфавіти, вам слід використовувати NVARCHAR. Логіка була б схожою, але вам потрібно було б використовувати UNICODE та NCHAR замість ASCII І CHAR, а оператор replace був би набагато величезнішим ....

-- 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)

В основному передумовою мого методу є торгівля попередніми обчисленнями для підвищення ефективності. Повна реалізація ASCII така:

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
Так. Ваш алфавіт містить лише 26 символів. У мого більше. Як щодо грецької? Чи турецький?
Томалак

Я стверджую, що інші рішення роблять те саме. Але я включив генератор коду. Ви можете просто додати додаткові розділи для вашого алфавіту. Вам потрібно було мати все як NVARCHAR і використовувати NCHAR та UNICODE для конвертації.
Черво

Я думаю, що чим більше у вас персонажів, тим менше він отримає. Але, будь ласка, у деяких наборах символів кожен символ представляє ціле слово, тому вся проблема з правильним регістром не застосовується ....
Черво

Також я сумніваюся, що хтось використовує кожен символ Unicode одночасно. Тож, мабуть, просто генеруйте заміну для 2 або 3 алфавітів, якими ви користуєтесь.
Черво

1
Це не означає, що ви повинні використовувати напівпечені рішення лише для англійської мови, лише тому, що ви очікуєте, що дані "будуть у вашому алфавіті, ймовірно". Що стосується латинської системи письма, для нижчого / верхнього регістру визначено (майже) будь-який символ. Функції перетворення більше стосуються правильності, ніж швидкості.
Томалак

0

Чи не пізно повертатися назад і отримувати великі дані?

Результати вашої обробки можуть не сподобатися фондам Неймана, Маккейна, ДеГузмана та Джонсона-Сміта вашої клієнтської бази ...

Також я здогадуюсь, що це призначене для одноразового оновлення даних? Можливо, буде простіше експортувати, фільтрувати / модифікувати та повторно імпортувати виправлені імена в базу даних, і тоді ви можете використовувати підходи, що не пов'язані з SQL, для виправлення імен ...


Всю проблему з іменуванням з'явилися як можливі недоліки, де обговорювалося - немає жодних ознак того, що автор питання посилається на дані, що містять імена.
Томалак

0

Ось ще один варіант, який я знайшов на форумах 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

Я знаю, що диявол у деталях (особливо там, де це стосується персональних даних людей), і що було б дуже приємно мати правильно написані великі імена, але вищезазначений тип клопоту - це те, чому прагматичні, уважні серед нас люди використовують наступне :

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

З мого досвіду, люди прекрасно бачать ЇХНЕ ІМ'Я ... навіть тоді, коли це вже половина речення.

Посилання: росіяни використовували олівець!


3
Заперечення питання не корисно. Ця "відповідь" є коментарем НАЙКРАЩЕ.
Філ

0

Щойно дізнався про InitCap().

Ось приклад коду:

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

2
OP вказаний сервер SQL, 'InitCap ()' - це річ Oracle.
mxmissle

0

Це працювало в SSMS:

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

0

Якщо ви знаєте, що всі дані - це лише одне слово, ось рішення. Спочатку оновіть стовпець до нижчого рівня, а потім виконайте наступне

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

0

Нещодавно довелося боротися з цим, і придумав наступне після того, як нічого не вдарило все, що я хотів. Це дозволить скласти ціле речення, випадки для спеціального оброблення слів. У нас також виникли проблеми зі словами "одного слова", з якими справляється багато простих методів, але не більш складні методи. Змінна одного повернення, без циклів або курсорів.

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

Скопіюйте та вставте свої дані у MS Word і використовуйте вбудований текст-перетворення для "Використання великих літер у кожному слові". Порівняйте з вихідними даними, щоб вирішити винятки. Я не бачу жодного способу обходу винятків типу "MacDonald" та "IBM" вручну, але так я це зробив FWIW.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.