2010-12-08 35 views
6

Est-il possible de convertir du texte d'une colonne de table dans SQL Server en PascalCase uniquement en utilisant un code SQL approprié?Convertir du texte dans PascalCase

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

Le champ qui contient du texte à convertir est CITTA. Il contient toutes les majuscules comme "ABANO TERME", "ROMA", et ainsi de suite. Les mots sont délimités par un espace.

EDIT

j'oublié de mentionner que certains mots ont un caractère d'accent dans ce '. Ce personnage peut être trouvé soit à la fin du mot ou au milieu.

EDIT 2:

Quelques bizarreries trouvées sur les résultats:

  • Si j'ai un nom comme "ISOLA Bâlbă" ce nom se traduit à "IsolaBalba" (cas correct, mais l'espace manqué)
  • Si j'ai un nom comme « ISOLA d'ASTI » ce sont convertis à « IsolaD'asti » (espace manqué comme avant et cas incorrect. Dans ce cas, le résultat correct est « Isola d'Asti »

pourriez-vous s'il vous plaît me donner quelques conseils sur ce petit problème?

+2

Probablement. Je ne suis pas sûr que SQL soit le meilleur environnement pour cela, mais si vous donnez des exemples d'entrée et de sortie, je vais essayer! Les mots sont-ils actuellement délimités avec un espace? c'est-à-dire a-t-il besoin de convertir 'pascal case' en' PascalCase'? –

+0

@Martin: merci pour votre réponse rapide. jetez un oeil à ma question éditez svp – Lorenzo

+0

@Lorenzo - les UDFs comptent-ils comme code SQL approprié pour vos buts? –

Répondre

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] 
+0

Neat stuff - attention aux problèmes avec les caractères qui nécessitent l'échappement XML, tho ',' HAM & OEUFS 'n'est pas bien traité par ce qui précède. –

+0

La requête fonctionne très bien même si elle est un peu lente: 3 minutes pour 400 enregistrements. Et j'ai environ 10k à convertir :) Non, les données n'ont pas de caractères qui doivent être échappés. Merci beaucoup!!! :) – Lorenzo

+0

C'est en effet assez lent. Certains textes sont-ils assez longs? Je suppose que c'est juste une tâche unique de toute façon? –

2

Essayez la fonction ci-dessous (ajustez le type de chaîne le cas échéant). N'utilisez pas ceci dans une clause WHERE - et considérez les ramifications de performance ailleurs. Le 12345678 est juste une valeur arbitrairement grande que vous pourriez vouloir remplacer par quelque chose de plus approprié!

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

@Merci, je vais l'essayer! Avez-vous vu ma dernière modification sur la question? – Lorenzo

+0

@Lorenzo - mon plaisir. C'est l'approche simple (et ne gère pas avec '' comme entrée - oups!). Ce n'est probablement pas génial en termes de temps d'exécution. L'approche de Martin pourrait bien mieux fonctionner - faites attention aux éventuels problèmes avec les caractères qui ont besoin de s'échapper du XML. –

+0

@Loernzo - ne s'attend pas à ce que les accents posent un problème - c'est juste une division sur les espaces et une MAJEURE du premier caractère après chaque espace - devrait fonctionner correctement avec des accents. –

3

Je vous encourage à essayer le code que j'ai posté dans un blog il y a un certain temps. Je soupçonne que cela répondra très bien à vos besoins et sera aussi plus efficace que de nombreuses autres méthodes.

SQL Server Proper Case Function

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 

Cette fonction est un peu plus rapide que la plupart parce que les boucles qu'une seule fois pour chaque mot qui exige une lettre majuscule.

+0

@G Maastros: merci pour votre aide! J'ai essayé la fonction et il fonctionne très bien même si je ne suis pas sûr de pouvoir gérer correctement le caractère accent "' ''. Quoi qu'il en soit, cette tâche était une tâche unique et la dernière édition par @Martin fonctionne très rapidement (seulement 5 secondes pour faire le travail). Cordialement – Lorenzo