7
votes

Convertir du texte dans Pascalcase

est-il possible de convertir le texte d'une colonne de table dans SQL Server en Pascalcase uniquement à l'aide d'un code SQL approprié?

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


11 commentaires

Probablement. Pas sûr que SQL est le meilleur environnement pour le faire, mais si vous donnez des exemples d'entrée et de sortie, je vais passer! Les mots sont-ils actuellement délimités avec un espace? C'est-à-dire que cela a besoin de convertir un cas Pascal vers Pascalcase ?


@Martin: Merci pour votre réponse rapide. Regardez ma question Modifier s'il vous plaît


@Lorenzo - Les UDFC comptent-ils comme code SQL approprié pour vos besoins?


Re: Votre commentaire sur les accents Quelle est la sortie attendue -> Sortie pour ceux-ci alors?


@Martin: le caractère doit rester inchangé dans la même position


Cela ne change rien alors le fait-il? Je pense que les règles d'origine fonctionneraient toujours?


@Martin: J'essaie juste maintenant. Je vous ferai savoir


@Lorenzo - typiquement Pascal Case est utilisé pour des identifiants dans le code - c'est pourquoi les deux réponses ont des espaces supprimés (les espaces ne sont généralement pas légaux dans les identificateurs). N'avait pas apprécié que des espaces devaient être conservés.


@Lorenzo - voir modifier. J'ai également remplacé la CTE avec une table indexée #TEpp dans l'espoir que cela sera plus rapide.


@WILL A: Tu as raison. Ce ne sont pas des identifiants de toute façon. C'est une liste de la ville :)


@Martin: Merci pour la mise à jour. Tu veux dire plus vite? Il faut maintenant seulement 5 secondes !!!! : O


4 Réponses :


4
votes
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]

5 commentaires

Stuff soie - Faites attention aux problèmes avec des personnages qui nécessitent une échappée XML, Tho ', «jambon et œufs» ne sont pas bien traités par ce qui précède.


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 pour convertir :) Aucune donnée n'a aucun caractère qui doit être échappé. Merci beaucoup!!! :)


C'est vraiment assez lent. Quelqu'un est-il assez long? Je suppose que c'est juste une tâche unique de toute façon?


Oui c'est le cas. Je ne me dérange pas que le temps nécessaire. Le texte le plus long est de 34 caractères.


J'ai trouvé des petites bizarreries après une analyse approfondie des résultats. Pourriez-vous s'il vous plaît jeter un coup d'œil à ma dernière modification sur la question? BTW La requête a pris 88 minutes pour exécuter complètement. Merci!



3
votes

Essayez la fonction ci-dessous (ajustez le type de chaîne selon que nécessaire). Il suffit de ne pas l'utiliser dans une clause où - et envisagez les ramifications de la performance ailleurs. Le 12345678 est juste une valeur arbitraire importante que vous voudrez peut-être remplacer avec 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


5 commentaires

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


@Lorenzo - Mon plaisir. C'est la simple approche (et ne pas faire face à '' comme entrée - Oups!). Ce n'est probablement pas brillant en termes de temps d'exécution. L'approche de Martin peut bien fonctionner mieux - faites attention à des problèmes potentiels avec des personnages nécessitant une échappée XML.


@LOERNZO - ne s'attendrait pas à ce que les accents posent un problème - cela ne fait que fractionnement sur les espaces et en rechange le premier caractère après chaque espace - devrait fonctionner correctement avec des accents.


Merci beaucoup pour votre contribution. Comme vous l'attendiez, pose problème avec les accents. Heureusement, l'autre réponse fonctionne bien même si c'est un peu lent ... S'il vous plaît voir mon dernier commentaire sur Martin Réponse


Cela ne fonctionne pas pour les traits de soulignement ou pour plusieurs espaces d'affilée.



4
votes

Je vous encourage à essayer le code que j'ai posté dans un blog il y a un moment. Je soupçonne que cela conviendra très bien à vos besoins, et mieux mieux que nombre des autres méthodes.

fonction de cas appropriée SQL Server xxx

Cette fonction est un peu plus rapide que la plupart des choses parce que cela ne boucle qu'une fois pour chaque mot qui nécessite une lettre majuscule.


3 commentaires

@G Maastros: Merci pour votre aide! J'ai essayé la fonction et cela fonctionne très bien même si je ne suis pas sûr de manipuler correctement le caractère d'accent '. Quoi qu'il en soit, cette tâche était une tâche unique et la dernière modification de @martin fonctionne très rapidement (seulement 5 secondes pour faire le travail). Salutations


La question demande à Pascalcase, pas de cas approprié. Ce n'est pas la même chose.


@Mgsam Veuillez noter que cela indique Pascalcase dans le titre, mais plus bas, dans le corps de la question, il est indiqué "Les mots sont délimités par un espace".



1
votes

A partir de SQL 2017, vous pouvez le faire assez élégamment. Contrairement à certaines des autres réponses, cela donne à Pascalcase, comme demandé, plutôt que des cas appropriés. Cela fonctionne également pour les traits de soulignement ou des espaces (et multiples d'une rangée).

SELECT dbo.fnPascalCase('taco___tuesday is   today') --Returns 'TacoTuesdayIsToday`
SELECT dbo.fnPascalCase('HELLO MY fRiEnD') --Returns 'HelloMyFriend`


0 commentaires