2010-12-08 23 views
6

¿Es posible convertir texto de una columna de tabla en SQL Server a PascalCase utilizando solo un código SQL adecuado?Convertir texto en PascalCase

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

El campo que contiene texto para convertir es CITTA. Contiene todos los valores en mayúscula como "ABANO TERME", "ROMA", y así sucesivamente. Las palabras están delimitadas por un espacio.

EDITAR

me olvidó mencionar que algunas palabras tienen un carácter con acento en ella '. Este personaje se puede encontrar al final de la palabra o en el medio.

EDIT 2:

algunas peculiaridades que se encuentran en los resultados:

  • Si tengo un nombre como "ISOLA BALBA" este nombre traduce a "IsolaBalba" (mayúsculas o minúsculas pero el espacio perdido)
  • Si tengo un nombre como "Isola d'Asti" esto se convierten a "IsolaD'asti" (espacio perdido como antes y la caja incorrecta. En este caso el resultado correcto es "Isola D'Asti"

¿podría darme algún consejo sobre este pequeño problema?

+2

Probablemente. No estoy seguro de que SQL sea el mejor entorno para hacerlo, pero si das ejemplos de entrada y salida, ¡voy a probarlo! ¿Las palabras están actualmente delimitadas con un espacio? es decir, ¿Necesita convertir 'pascal case' a' PascalCase'? –

+0

@Martin: gracias por su respuesta rápida. eche un vistazo a mi edición de preguntas, por favor – Lorenzo

+0

@Lorenzo - ¿Las UDF cuentan como código SQL adecuado para sus propósitos? –

Respuesta

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

Lo mejor: ten cuidado con los problemas con los caracteres que requieren escapes de XML, aunque ',' HAM & EGGS 'no se trata bien con lo anterior. –

+0

La consulta está funcionando muy bien, incluso si es un poco lento: 3 minutos para 400 registros. Y tengo aproximadamente 10k para convertir :) No, los datos no tienen caracteres que deban escaparse. ¡¡¡Muchas gracias!!! :) – Lorenzo

+0

Eso es bastante lento. ¿Alguno de los textos es bastante largo? Supongo que esto es solo una tarea única de todos modos? –

2

Pruebe la función siguiente (ajuste el tipo de cadena según corresponda). Simplemente no use esto en una cláusula WHERE, y considere las ramificaciones de desempeño en otros lugares. ¡El 12345678 es solo un valor arbitrariamente grande que puede reemplazar con algo más apropiado!

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

@Gracias, voy a intentarlo! ¿Has visto mi última edición en la pregunta? – Lorenzo

+0

@Lorenzo - mi placer. Este es el enfoque simple (y no hace frente a '' como entrada, ¡vaya!). Probablemente no sea brillante en términos de tiempo de ejecución. El enfoque de Martin podría funcionar mejor, solo ten cuidado con los posibles problemas con los personajes que necesitan escaparse de XML. –

+0

@Loernzo - no esperaría que los acentos planteen un problema - esto es simplemente dividir en espacios y SUPERAR el primer carácter después de cada espacio - debería funcionar bien con acentos. –

3

Te animo a que pruebes el código que publiqué en un blog hace un tiempo. Sospecho que se ajustará muy bien a sus necesidades y también tendrá un mejor rendimiento que muchos de los otros métodos.

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 

Esta función es un poco más rápido que la mayoría, ya que sólo los bucles de una vez por cada palabra que requiere una letra mayúscula.

+0

@G Maastros: ¡gracias por su ayuda! He probado la función y funciona muy bien incluso si no estoy seguro de que maneje correctamente el carácter de acento '''. De todos modos, esta tarea fue una tarea única y la última edición de @Martin funciona muy rápido (solo 5 segundos para hacer el trabajo). Saludos – Lorenzo

Cuestiones relacionadas