SQL Server: переведите все ВЕРХНИЕ дела в надлежащие дела / заглавные дела - PullRequest
80 голосов
/ 23 октября 2008

У меня есть таблица, которая была импортирована как верхний регистр, и я хотел бы превратить ее в правильный регистр. Какой сценарий кто-нибудь из вас использовал для этого?

Ответы [ 19 ]

0 голосов
/ 11 апреля 2019

Небольшая модификация ответа @ Galwegian - например, St Elizabeth's в St Elizabeth'S.

Эта модификация сохраняет апострофы-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 голосов
/ 28 февраля 2019

Если вы знаете, что все данные - это всего лишь одно слово, вот решение. Сначала обновите столбец до всех нижних, а затем выполните следующую команду

    update tableName set columnName = 
    upper(SUBSTRING(columnName, 1, 1)) + substring(columnName, 2, len(columnName)) from tableName
0 голосов
/ 09 ноября 2018

Занят и улучшен ответ @Richard Sayakanit. Это обрабатывает несколько слов. Как и его ответ, здесь не используются пользовательские функции, только встроенные функции (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
0 голосов
/ 24 июля 2018

Это работало в SSMS:

Select Jobtitle,
concat(Upper(LEFT(jobtitle,1)), SUBSTRING(jobtitle,2,LEN(jobtitle))) as Propercase
From [HumanResources].[Employee]
0 голосов
/ 18 июля 2018

только что узнал о InitCap().

Вот пример кода:

SELECT ID
      ,InitCap(LastName ||', '|| FirstName ||' '|| Nvl(MiddleName,'')) AS RecipientName
FROM SomeTable
0 голосов
/ 08 сентября 2016

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

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

По моему опыту, люди прекрасно видят ИМЯ ... даже когда оно на полпути к предложению.

См .: русские использовали карандаш!

0 голосов
/ 23 октября 2008

Я думаю, вы найдете, что следующее более эффективно:

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

Оператор замены может быть вырезан и вставлен непосредственно в запрос SQL. Это крайне уродливо, однако, заменив @str на интересующий вас столбец, вы не будете платить цену за неявный курсор, как вы платите за опубликованные таким образом файлы udf. Я считаю, что даже используя мой UDF, он гораздо эффективнее.

Да, и вместо генерации оператора замены используйте это:

-- 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 ([a-z]) / uc $ 1 /, ну да ладно, мы работаем с инструментами, которые у нас есть.

ПРИМЕЧАНИЕ: вам придется использовать это, как если бы вы использовали его как ... SELECT dbo.ProperCase (LOWER (column)), так как столбец в верхнем регистре. На самом деле он работает довольно быстро на моей таблице, состоящей из 5000 записей (даже не одной секунды), даже при меньшем.

В ответ на поток комментариев, касающихся интернационализации, я представляю следующую реализацию, которая обрабатывает каждый символ ascii, полагаясь только на реализацию SQL Server верхнего и нижнего уровней. Помните, что переменные, которые мы используем здесь, являются VARCHAR, что означает, что они могут содержать только значения ASCII. Чтобы использовать другие международные алфавиты, вы должны использовать NVARCHAR. Логика была бы аналогичной, но вам нужно было бы использовать UNICODE и NCHAR вместо ASCII и CHAR, а оператор замены был бы гораздо более громоздким ....

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

По сути, предпосылка метода my заключается в обмене предварительными вычислениями на эффективность. Полная реализация 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
0 голосов
/ 17 июня 2009

Вот еще один вариант, который я нашел на форумах 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 голосов
/ 23 октября 2008

Не слишком ли поздно вернуться и получить данные без заглавных букв?

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

Кроме того, я предполагаю, что это должно быть разовое обновление данных? Может быть проще экспортировать, фильтровать / изменять и повторно импортировать исправленные имена в БД, а затем вы можете использовать не-SQL подходы для фиксации имен ...

...