7

是否可以仅使用正确的 SQL 代码将 SQL Server 中的表列中的文本转换为 PascalCase?

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

包含要转换的文本的字段是CITTA。它包含所有大写值,例如“ABANO TERME”、“ROMA”等。单词由空格分隔。

编辑

我忘了说有些词里面有重音符号'。这个字符可以在单词的末尾或中间找到。

编辑2:

在结果中发现了一些怪癖:

  • 如果我有一个像“ISOLA BALBA”这样的名字,这个名字会被翻译成“IsolaBalba”(正确的大小写,但缺少空格)
  • 如果我有一个像“ISOLA D'ASTI”这样的名字,它会被转换为“IsolaD'asti”(像以前一样缺少空格并且大小写不正确。在这种情况下,正确的结果是“Isola D'Asti”

你能给我一些关于这个小问题的建议吗?

4

4 回答 4

4
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]
于 2010-12-08T00:43:21.197 回答
4

我鼓励您尝试我不久前在博客中发布的代码。我怀疑它会很好地满足您的要求,并且比许多其他方法执行得更好。

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

这个函数比大多数函数要快一点,因为它只为每个需要大写字母的单词循环一次。

于 2010-12-08T14:01:39.143 回答
3

尝试以下功能(根据需要调整字符串类型)。只是不要在 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
于 2010-12-08T00:46:36.677 回答
1

从 SQL 2017 开始,您可以非常优雅地做到这一点。与其他一些答案不同,这会根据要求给出 PascalCase,而不是 Proper Case。它也适用于下划线或空格(以及连续的多个)。

CREATE OR ALTER FUNCTION dbo.fnPascalCase(@word NVARCHAR(MAX)) RETURNS NVARCHAR(MAX)
BEGIN
    DECLARE @t1 TABLE (Val NVARCHAR(MAX));
    INSERT INTO @t1 (Val)
    SELECT Val = UPPER(SUBSTRING(LTRIM(RTRIM(value)), 1, 1)) + LOWER(SUBSTRING(LTRIM(RTRIM(value)), 2, 2000000000)) FROM STRING_SPLIT(REPLACE(@word, ' ', '_'), '_')

    DECLARE @result NVARCHAR(MAX);

    SELECT @result = STRING_AGG(Val, '') FROM @t1
    RETURN @result
END

用法:

SELECT dbo.fnPascalCase('taco___tuesday is   today') --Returns 'TacoTuesdayIsToday`
SELECT dbo.fnPascalCase('HELLO MY fRiEnD') --Returns 'HelloMyFriend`
于 2020-03-19T20:57:15.173 回答