Конвертировать текст в PascalCase - PullRequest
7 голосов
/ 08 декабря 2010

Возможно ли преобразовать текст из столбца таблицы в SQL Server в PascalCase только с использованием правильного кода SQL?

TABLE DEFINITION
----------------------
ID  int
CITTA   varchar(50)
PROV    varchar(50)
CAP varchar(50)
COD varchar(50)

Поле, содержащее текст для преобразования: CITTA. Он содержит все значения в верхнем регистре, такие как «ABANO TERME», «ROMA» и так далее. Слова отделяются пробелом.

EDIT

Я забыл упомянуть, что в некоторых словах есть акцент '. Этот символ может быть найден в конце слова или в середине.

РЕДАКТИРОВАТЬ 2:

Найдены некоторые причуды по результатам:

  • Если у меня есть имя, подобное «ISOLA BALBA», это имя переводят в «IsolaBalba» (правильный регистр, но пропущено место)
  • Если у меня есть имя, подобное «ISOLA D'ASTI», оно преобразуется в «IsolaD'asti» (пропущенный пробел, как и раньше, и неправильный регистр. В этом случае правильный результат - «Isola D'Asti»

Не могли бы вы дать мне несколько советов по этой маленькой проблеме?

Ответы [ 3 ]

4 голосов
/ 08 декабря 2010
DECLARE @T TABLE
(
ID  INT PRIMARY KEY,
CITTA   VARCHAR(50)
)
INSERT INTO @T
SELECT 1, 'ABANO TERME' UNION ALL SELECT 2, 'ROMA' UNION ALL SELECT 3, 'ISOLA D''ASTI';

IF OBJECT_ID('tempdb..#HolderTable') IS NOT NULL
    DROP TABLE #HolderTable

CREATE TABLE #HolderTable
(
Idx INT IDENTITY(1,1) PRIMARY KEY,
ID INT,
Word  VARCHAR(50)
)

CREATE NONCLUSTERED INDEX ix ON #HolderTable(ID)
;

WITH T1 AS
(
SELECT ID, CAST(N'<root><r>' + REPLACE(REPLACE(CITTA, '''', '''</r><r>'), ' ', ' </r><r>') + '</r></root>' AS XML) AS xl
FROM @T
)
INSERT INTO #HolderTable
SELECT ID, 
       r.value('.','NVARCHAR(MAX)') AS Item
 FROM T1
 CROSS APPLY
xl.nodes('//root/r') AS RECORDS(r)

SELECT 
      ID, 
      (SELECT STUFF(LOWER(Word),1,1,UPPER(LEFT(Word,1))) FROM #HolderTable WHERE [@T].ID =  #HolderTable.ID ORDER BY Idx FOR XML PATH('') )
FROM @T [@T]
3 голосов
/ 08 декабря 2010

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

Правильный регистр SQL Server Функция

CREATE FUNCTION dbo.Proper(@DATA VARCHAR(8000))
RETURNS VARCHAR(8000)
AS
BEGIN
  DECLARE @Position INT

  SELECT @DATA = STUFF(LOWER(@DATA), 1, 1, UPPER(LEFT(@DATA, 1))),
         @Position = PATINDEX('%[^a-zA-Z][a-z]%', @DATA COLLATE Latin1_General_Bin)

  WHILE @Position > 0
    SELECT @DATA = STUFF(@DATA, @Position, 2, UPPER(SUBSTRING(@DATA, @Position, 2))),
           @Position = PATINDEX('%[^a-zA-Z][a-z]%', @DATA COLLATE Latin1_General_Bin)

  RETURN @DATA
END

Эта функция немного быстрее, чем большинство, потому что она повторяется только один раз для каждого слова, которое требует заглавной буквы.

2 голосов
/ 08 декабря 2010

Попробуйте следующую функцию (отрегулируйте тип строки соответствующим образом). Только не используйте это в предложении WHERE - и рассмотрите последствия для производительности в другом месте. 12345678 - это просто какое-то произвольно большое значение, которое вы можете заменить на более подходящее!

CREATE FUNCTION dbo.ufn_PascalCase(@str AS VARCHAR(MAX)) RETURNS VARCHAR(MAX)
BEGIN
    SET @str = LOWER(@str)

    DECLARE @result VARCHAR(MAX) = ''

    DECLARE @spaceIndex INTEGER = CHARINDEX(' ', @str)
    WHILE @spaceIndex > 0
    BEGIN
        SET @result += UPPER(SUBSTRING(@str, 1, 1)) + SUBSTRING(@str, 2, @spaceIndex - 2)
        SET @str = SUBSTRING(@str, @spaceIndex + 1, 12345678)
        SET @spaceIndex = CHARINDEX(' ', @str)
    END

    SET @result += UPPER(SUBSTRING(@str, 1, 1)) + SUBSTRING(@str, 2, 12345678)

    RETURN @result
END
...