SQL Server: haga todas las mayúsculas en mayúsculas y minúsculas en el caso / título apropiado

95

Tengo una tabla que se importó en MAYÚSCULAS y me gustaría convertirla en una caja adecuada. ¿Qué guión ha usado alguno de ustedes para completar esto?

RyanKeeter
fuente
4
Solo tenga en cuenta que cambiar correctamente el texto en mayúsculas a texto en mayúsculas puede requerir correcciones manuales en algunos, bueno, casos. Con nombres, por ejemplo: no aprecio las aplicaciones que escriben mal mi nombre.
Dave DuPlantis
2
No habrá ninguna función en la tierra que haga bien a 'DAVE DUPLANTIS'. Los datos en mayúsculas son una gran WTF en sí misma, porque la mayoría de las veces es simplemente un problema de presentación.
Tomalak
1
Conozco a un Macdonald que se pone furioso cuando se le llama MacDonald. Y agradecería también la carcasa adecuada de O'Keefe, por favor.
DOK
@Tomalak: correcto, por eso debe aceptar datos de mayúsculas y minúsculas y conservarlos cuando la elección sea suya. Totalmente de acuerdo sobre la parte WTF ... particularmente si acepta caracteres "internacionales".
Dave DuPlantis
También es un problema cultural. En mi experiencia, los británicos y los franceses tienen la costumbre de poner los apellidos en mayúsculas donde sea que tengan la oportunidad. Simplemente no lo entiendo, no agrega valor.
Tomalak

Respuestas:

89

Aquí hay un UDF que hará el truco ...

create function ProperCase(@Text as varchar(8000))
returns varchar(8000)
as
begin
  declare @Reset bit;
  declare @Ret varchar(8000);
  declare @i int;
  declare @c char(1);

  if @Text is null
    return null;

  select @Reset = 1, @i = 1, @Ret = '';

  while (@i <= len(@Text))
    select @c = substring(@Text, @i, 1),
      @Ret = @Ret + case when @Reset = 1 then UPPER(@c) else LOWER(@c) end,
      @Reset = case when @c like '[a-zA-Z]' then 0 else 1 end,
      @i = @i + 1
  return @Ret
end

Sin embargo, aún tendrá que usarlo para actualizar sus datos.

Galwegian
fuente
15
Esto explotará para entradas que no estén en inglés.
Tomalak
¡Gracias! funcionó primero, incluso en Azure SQL Server :)
Aaron
¿Puedo preguntar en qué base de datos y tabla se incluye?
v3nt
2
Probé esto con SQL Server 2008 y todo tipo de acentos, funcionó como un encanto. De hecho, depende de la colación
Baptiste
¡Gracias! Está dando los resultados esperados.
Palak Patel
109

Esta función:

  • "Casos propios" todas las palabras "MAYÚSCULAS" que están delimitadas por espacios en blanco
  • deja "palabras en minúscula" solas
  • funciona correctamente incluso para alfabetos distintos del inglés
  • es portátil en el sentido de que no utiliza características sofisticadas de las versiones recientes del servidor SQL
  • se puede cambiar fácilmente para usar NCHAR y NVARCHAR para compatibilidad con Unicode, así como cualquier longitud de parámetro que crea conveniente
  • la definición de espacio en blanco se puede configurar
CREATE FUNCTION ToProperCase(@string VARCHAR(255)) RETURNS VARCHAR(255)
AS
BEGIN
  DECLARE @i INT           -- index
  DECLARE @l INT           -- input length
  DECLARE @c NCHAR(1)      -- current char
  DECLARE @f INT           -- first letter flag (1/0)
  DECLARE @o VARCHAR(255)  -- output string
  DECLARE @w VARCHAR(10)   -- characters considered as white space

  SET @w = '[' + CHAR(13) + CHAR(10) + CHAR(9) + CHAR(160) + ' ' + ']'
  SET @i = 1
  SET @l = LEN(@string)
  SET @f = 1
  SET @o = ''

  WHILE @i <= @l
  BEGIN
    SET @c = SUBSTRING(@string, @i, 1)
    IF @f = 1 
    BEGIN
     SET @o = @o + @c
     SET @f = 0
    END
    ELSE
    BEGIN
     SET @o = @o + LOWER(@c)
    END

    IF @c LIKE @w SET @f = 1

    SET @i = @i + 1
  END

  RETURN @o
END

Resultado:

dbo.ToProperCase('ALL UPPER CASE and    SOME lower ÄÄ ÖÖ ÜÜ ÉÉ ØØ ĈĈ ÆÆ')
-----------------------------------------------------------------
All Upper Case and      Some lower Ää Öö Üü Éé Øø Cc Ææ
Tomalak
fuente
1
Esta es definitivamente la solución más amigable internacionalmente. Tiene mi voto. El único supuesto aquí es que un espacio separa las palabras.
Cervo
3
¿Podría ser que el índice debería comenzar en 1? La primera subcadena (, 0,1) devuelve <vacío>. Estoy corriendo SQLServer2005
enero
10
Probablemente debería incluir un apóstrofo como carácter de espacio en blanco de forma predeterminada para que un nombre como O'DONNELLno cambie a O'donnell.
JustinStolle
2
@Tomalak, la variable @i debe comenzar en uno, de lo contrario, se antepone un espacio a la salida
Jakub
5
Excelente pequeña función. No es que el OP lo solicite, pero si alguien quiere cambiarlo para que no ignore las palabras que ya están en minúscula y las convierta también, por ejemplo, "tom bombadil" a "Tom Bombadil", simplemente cambie esta línea. - SET @o = @o + @ca SET @o = @o + UPPER(@c). =)
NateJ
41
UPDATE titles
  SET title =
      UPPER(LEFT(title, 1)) +
        LOWER(RIGHT(title, LEN(title) - 1))

http://sqlmag.com/t-sql/how-title-case-column-value

Richard Sayakanit
fuente
8
Para su información, esto funciona para valores de una sola palabra, pero no para valores de varias palabras. Así que "CAROLINA DEL NORTE" se convierte en "Carolina del Norte" en lugar de la "Carolina del Norte" ejecutada.
molaro
4
+1 como solución simple de una sola palabra que funcionó bien para mí. El único: puede obtener un error si titleestá vacío.
Serg
@molaro divide el espacio y opera con cada palabra individualmente. Buena solución pero un poco restrictiva en cuanto a las posibilidades. Para los futuros espectadores, es posible que desee dividir el terminador de la oración y el primer caso la primera palabra de la oración.
GoldBishop
1
Agregue WHERE title IS NOT NULLal final para resolver el problema de @Serg.
Paul
@Serg Edité el código para que no se ejecute por error en cadenas de longitud cero usando en SUBSTRINGlugar deRIGHT
robotik
18

Si puede habilitar CLR en SQL Server (requiere 2005 o posterior), entonces podría crear una función CLR que use la función incorporada TextInfo.ToTitleCase que le permitiría crear una forma consciente de la cultura de hacer esto en solo unos pocos líneas de código.

Greg Beech
fuente
Yo también tengo que votar aquí. TI es seguro a nivel internacional y utiliza la biblioteca de otra persona que probablemente esté llena de todo tipo de comprobaciones. No puedes equivocarte aquí :)
Cervo
8

Sé que esta es una publicación tardía en este hilo, pero vale la pena mirar. Esta función funciona para mí siempre. Así que pensé en compartirlo.

CREATE FUNCTION [dbo].[fnConvert_TitleCase] (@InputString VARCHAR(4000) )
RETURNS VARCHAR(4000)
AS
BEGIN
DECLARE @Index INT
DECLARE @Char CHAR(1)
DECLARE @OutputString VARCHAR(255)

SET @OutputString = LOWER(@InputString)
SET @Index = 2
SET @OutputString = STUFF(@OutputString, 1, 1,UPPER(SUBSTRING(@InputString,1,1)))

WHILE @Index <= LEN(@InputString)
BEGIN
    SET @Char = SUBSTRING(@InputString, @Index, 1)
    IF @Char IN (' ', ';', ':', '!', '?', ',', '.', '_', '-', '/', '&','''','(')
    IF @Index + 1 <= LEN(@InputString)
BEGIN
    IF @Char != ''''
    OR
    UPPER(SUBSTRING(@InputString, @Index + 1, 1)) != 'S'
    SET @OutputString =
    STUFF(@OutputString, @Index + 1, 1,UPPER(SUBSTRING(@InputString, @Index + 1, 1)))
END
    SET @Index = @Index + 1
END

RETURN ISNULL(@OutputString,'')
END

Llamadas de prueba:

select dbo.fnConvert_TitleCase(Upper('ÄÄ ÖÖ ÜÜ ÉÉ ØØ ĈĈ ÆÆ')) as test
select dbo.fnConvert_TitleCase(upper('Whatever the mind of man can conceive and believe, it can achieve. – Napoleon hill')) as test

Resultados:

ingrese la descripción de la imagen aquí

Harmeet Singh Bhamra
fuente
¿Puede describir por qué es mejor que la función ToProperCase de Tomalak stackoverflow.com/questions/230138/… ?
Michael Freidgeim
1
Basado en los ejemplos dados con esta respuesta y Tomalak junto con la descripción de Tomalak de lo que hace ("deja las palabras en minúsculas en paz") ​​esta respuesta es mejor. No verifiqué la de Tomalak, pero esta respuesta hace el caso apropiado como entrada (hasta donde mis necesidades pueden verificar). "El caso apropiado es cualquier texto que se escribe con cada una de las primeras letras de cada palabra en mayúscula". - computerhope.com/jargon/p/proper-case.htm
Morvael
8

Llegué un poco tarde en el juego, pero creo que esto es más funcional y funciona con cualquier idioma, incluyendo ruso, alemán, tailandés, vietnamita, etc. Hará mayúsculas cualquier cosa después de 'o - o. o (o) o espacio (obviamente :).

CREATE FUNCTION [dbo].[fnToProperCase]( @name nvarchar(500) )
RETURNS nvarchar(500)
AS
BEGIN
declare @pos    int = 1
      , @pos2   int

if (@name <> '')--or @name = lower(@name) collate SQL_Latin1_General_CP1_CS_AS or @name = upper(@name) collate SQL_Latin1_General_CP1_CS_AS)
begin
    set @name = lower(rtrim(@name))
    while (1 = 1)
    begin
        set @name = stuff(@name, @pos, 1, upper(substring(@name, @pos, 1)))
        set @pos2 = patindex('%[- ''.)(]%', substring(@name, @pos, 500))
        set @pos += @pos2
        if (isnull(@pos2, 0) = 0 or @pos > len(@name))
            break
    end
end

return @name
END
GO
Alansoft
fuente
Esto funciona bien, excepto que "la casa de Jack" se convierte en "Casa de Jack"
Damien
2
Jack's House no es el nombre de una persona. O'Brian, O'Connell son nombres :) Si no se trata exclusivamente del nombre de las personas, es necesario un cambio.
Alansoft
3

Si está en SSIS importando datos que tienen mayúsculas y minúsculas mixtas y necesita realizar una búsqueda en una columna con el caso adecuado, notará que la búsqueda falla cuando la fuente está mezclada y la fuente de búsqueda es la adecuada. También notará que no puede usar las funciones derecha e izquierda es SSIS para SQL Server 2008r2 para columnas derivadas. Aquí hay una solución que funciona para mí:

UPPER(substring(input_column_name,1,1)) + LOWER(substring(input_column_name, 2, len(input_column_name)-1))
Kenjamarticus
fuente
2

Aquí hay una versión que usa una secuencia o una tabla de números en lugar de un bucle. Puede modificar la cláusula WHERE para que se adapte a sus reglas personales sobre cuándo convertir un carácter a mayúsculas. Acabo de incluir un conjunto simple que pondrá en mayúsculas cualquier letra que vaya precedida de una no letra, con la excepción de los apóstrofos. Sin embargo, esto significa que 123apple tendría una coincidencia en la "a" porque "3" no es una letra. Si solo desea espacios en blanco (espacio, tabulación, retorno de carro, avance de línea), puede reemplazar el patrón '[^a-z]'con '[' + Char(32) + Char(9) + Char(13) + Char(10) + ']'.


CREATE FUNCTION String.InitCap( @string nvarchar(4000) ) RETURNS nvarchar(4000) AS
BEGIN

-- 1. Convert all letters to lower case
    DECLARE @InitCap nvarchar(4000); SET @InitCap = Lower(@string);

-- 2. Using a Sequence, replace the letters that should be upper case with their upper case version
    SELECT @InitCap = Stuff( @InitCap, n, 1, Upper( SubString( @InitCap, n, 1 ) ) )
    FROM (
        SELECT (1 + n1.n + n10.n + n100.n + n1000.n) AS n
        FROM       (SELECT 0 AS n UNION SELECT    1 UNION SELECT    2 UNION SELECT    3 UNION SELECT    4 UNION SELECT    5 UNION SELECT    6 UNION SELECT    7 UNION SELECT    8 UNION SELECT    9) AS    n1
        CROSS JOIN (SELECT 0 AS n UNION SELECT   10 UNION SELECT   20 UNION SELECT   30 UNION SELECT   40 UNION SELECT   50 UNION SELECT   60 UNION SELECT   70 UNION SELECT   80 UNION SELECT   90) AS   n10
        CROSS JOIN (SELECT 0 AS n UNION SELECT  100 UNION SELECT  200 UNION SELECT  300 UNION SELECT  400 UNION SELECT  500 UNION SELECT  600 UNION SELECT  700 UNION SELECT  800 UNION SELECT  900) AS  n100
        CROSS JOIN (SELECT 0 AS n UNION SELECT 1000 UNION SELECT 2000 UNION SELECT 3000)                                                                                                             AS n1000
        ) AS Sequence
    WHERE 
        n BETWEEN 1 AND Len( @InitCap )
    AND SubString( @InitCap, n, 1 ) LIKE '[a-z]'                 /* this character is a letter */
    AND (
        n = 1                                                    /* this character is the first `character` */
        OR SubString( @InitCap, n-1, 1 ) LIKE '[^a-z]'           /* the previous character is NOT a letter */
        )
    AND (
        n < 3                                                    /* only test the 3rd or greater characters for this exception */
        OR SubString( @InitCap, n-2, 3 ) NOT LIKE '[a-z]''[a-z]' /* exception: The pattern <letter>'<letter> should not capatolize the letter following the apostrophy */
        )

-- 3. Return the modified version of the input
    RETURN @InitCap

END
Dennis Allen
fuente
1

El enlace que publiqué anteriormente es una excelente opción que aborda el problema principal: que nunca podremos dar cuenta programáticamente de todos los casos (Smith-Jones, von Haussen, John Smith MD), al menos no de una manera elegante. Tony introduce el concepto de carácter de excepción / ruptura para tratar estos casos. De todos modos, sobre la base de la idea de Cervo (en la parte superior todos los caracteres inferiores precedidos por un espacio), las declaraciones de reemplazo podrían envolverse en una sola tabla de reemplazo basada en su lugar. Realmente, cualquier combinación de caracteres de abajo / arriba podría insertarse en @alpha y la declaración no cambiaría:

declare @str    nvarchar(8000)
declare @alpha  table (low nchar(1), up nchar(1))


set @str = 'ALL UPPER CASE and    SOME lower ÄÄ ÖÖ ÜÜ ÉÉ ØØ ĈĈ ÆÆ'

-- stage the alpha (needs number table)
insert into @alpha
    -- A-Z / a-z
    select      nchar(n+32),
                nchar(n)
    from        dbo.Number
    where       n between 65 and 90 or
                n between 192 and 223

-- append space at start of str
set @str = lower(' ' + @str)

-- upper all lower case chars preceded by space
select  @str = replace(@str, ' ' + low, ' ' + up) 
from    @Alpha

select @str
Nathan Skerl
fuente
Otra única solución de US-ASCII.
Tomalak
¿Sigue viendo esto como una solución centrada en los EE. UU. Ya que hace referencia a caracteres Unicode? Sé que la publicación original usaba el conjunto de resultados AZ ascii, pero el punto de la solución es que se trata de un emparejamiento impulsado por tablas de caracteres superiores: inferiores. La declaración de reemplazo solo se refiere a la tabla.
Nathan Skerl
editar: Actualicé el ejemplo para usar su entrada de muestra. Gracias por cualquier comentario
Nathan Skerl
¿Existe una forma "poco elegante" de manejar la mayoría de las variaciones conocidas para los nombres que no están separados por guiones? Como 'Mc', O'C, ¿y qué no?
Merritt
1

Tendría sentido mantener una búsqueda de excepciones para ocuparse de los de von Neumann, McCain, DeGuzman y Johnson-Smith.

Sotavento
fuente
1

Tomó prestado y mejoró la respuesta de @Richard Sayakanit. Esto maneja varias palabras. Como su respuesta, esto no usa ninguna UDF, solo funciones integradas ( STRING_SPLITy STRING_AGG) y es bastante rápido. STRING_AGGrequiere SQL Server 2017 pero siempre puedes usar el STUFF/XMLtruco. No manejará todas las excepciones, pero puede funcionar muy bien para muchos requisitos.

SELECT StateName = 'North Carolina' 
INTO #States
UNION ALL
SELECT 'Texas'


;WITH cteData AS 
(
    SELECT 
        UPPER(LEFT(value, 1)) +
            LOWER(RIGHT(value, LEN(value) - 1)) value, op.StateName
    FROM   #States op
    CROSS APPLY STRING_SPLIT(op.StateName, ' ') AS ss
)
SELECT 
    STRING_AGG(value, ' ')
FROM cteData c 
GROUP BY StateName
Gabe
fuente
1

Una ligera modificación a la respuesta de @ Galwegian, que se convierte, por ejemplo, St Elizabeth'sen St Elizabeth'S.

Esta modificación mantiene los apóstrofos en minúsculas donde la s viene al final de la cadena proporcionada o la s va seguida de un espacio (y solo en esas circunstancias).

create function properCase(@text as varchar(8000))
returns varchar(8000)
as
begin
    declare @reset int;
    declare @ret varchar(8000);
    declare @i int;
    declare @c char(1);
    declare @d char(1);

    if @text is null
    return null;

    select @reset = 1, @i = 1, @ret = '';

    while (@i <= len(@text))
    select
        @c = substring(@text, @i, 1),
        @d = substring(@text, @i+1, 1),
        @ret = @ret + case when @reset = 1 or (@reset=-1 and @c!='s') or (@reset=-1 and @c='s' and @d!=' ') then upper(@c) else lower(@c) end,
        @reset = case when @c like '[a-za-z]' then 0 when @c='''' then -1 else 1 end,
        @i = @i + 1
    return @ret
end

Da vueltas:

  • st elizabeth's dentro St Elizabeth's
  • o'keefe dentro O'Keefe
  • o'sullivan dentro O'Sullivan

Los comentarios de otros de que son preferibles diferentes soluciones para la entrada que no es en inglés siguen siendo el caso.

philipnye
fuente
0

Creo que encontrará que lo siguiente es más eficiente:

IF OBJECT_ID('dbo.ProperCase') IS NOT NULL
    DROP FUNCTION dbo.ProperCase
GO
CREATE FUNCTION dbo.PROPERCASE (
    @str VARCHAR(8000))
RETURNS VARCHAR(8000)
AS
BEGIN
    SET @str = ' ' + @str
    SET @str = REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE( @str, ' a', ' A'), ' b', ' B'), ' c', ' C'), ' d', ' D'), ' e', ' E'), ' f', ' F'), ' g', ' G'), ' h', ' H'), ' i', ' I'), ' j', ' J'), ' k', ' K'), ' l', ' L'), ' m', ' M'), ' n', ' N'), ' o', ' O'), ' p', ' P'), ' q', ' Q'), ' r', ' R'), ' s', ' S'), ' t', ' T'), ' u', ' U'), ' v', ' V'), ' w', ' W'), ' x', ' X'), ' y', ' Y'), ' z', ' Z')
    RETURN RIGHT(@str, LEN(@str) - 1)
END
GO

La declaración de reemplazo se puede cortar y pegar directamente en una consulta SQL. Es muy feo, sin embargo, al reemplazar @str con la columna que le interesa, no pagará un precio por un cursor implícito como lo haría con las udfs así publicadas. Encuentro que incluso usando mi UDF es mucho más eficiente.

Ah, y en lugar de generar la declaración de reemplazo a mano, use esto:

-- Code Generator for expression
DECLARE @x  INT,
    @c  CHAR(1),
    @sql    VARCHAR(8000)
SET @x = 0
SET @sql = '@str' -- actual variable/column you want to replace
WHILE @x < 26
BEGIN
    SET @c = CHAR(ASCII('a') + @x)
    SET @sql = 'REPLACE(' + @sql + ', '' ' + @c+  ''', '' ' + UPPER(@c) + ''')'
    SET @x = @x + 1
END
PRINT @sql

De todos modos depende del número de filas. Ojalá pudieras hacer s / \ b ([az]) / uc $ 1 /, pero bueno, trabajamos con las herramientas que tenemos.

NOTA: tendría que usar esto ya que tendría que usarlo como .... SELECT dbo.ProperCase (LOWER (column)) ya que la columna está en mayúsculas. En realidad, funciona bastante rápido en mi tabla de 5,000 entradas (ni siquiera un segundo) incluso con la más baja.

En respuesta a la avalancha de comentarios sobre la internacionalización, presento la siguiente implementación que maneja cada carácter ascii confiando solo en la implementación de SQL Server de superior e inferior. Recuerde, las variables que estamos usando aquí son VARCHAR, lo que significa que solo pueden contener valores ASCII. Para utilizar más alfabetos internacionales, debe utilizar NVARCHAR. La lógica sería similar, pero necesitaría usar UNICODE y NCHAR en lugar de ASCII Y CHAR y la declaración de reemplazo sería mucho más grande ...

-- Code Generator for expression
DECLARE @x  INT,
    @c  CHAR(1),
    @sql    VARCHAR(8000),
    @count  INT
SEt @x = 0
SET @count = 0
SET @sql = '@str' -- actual variable you want to replace
WHILE @x < 256
BEGIN
    SET @c = CHAR(@x)
    -- Only generate replacement expression for characters where upper and lowercase differ
    IF @x = ASCII(LOWER(@c)) AND @x != ASCII(UPPER(@c))
    BEGIN
        SET @sql = 'REPLACE(' + @sql + ', '' ' + @c+  ''', '' ' + UPPER(@c) + ''')'
        SET @count = @count + 1
    END
    SET @x = @x + 1
END
PRINT @sql
PRINT 'Total characters substituted: ' + CONVERT(VARCHAR(255), @count)

Básicamente, la premisa del método my es cambiar la pre-computación por eficiencia. La implementación completa de ASCII es la siguiente:

IF OBJECT_ID('dbo.ProperCase') IS NOT NULL
    DROP FUNCTION dbo.ProperCase
GO
CREATE FUNCTION dbo.PROPERCASE (
    @str VARCHAR(8000))
RETURNS VARCHAR(8000)
AS
BEGIN
    SET @str = ' ' + @str
SET @str =     REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(@str, ' a', ' A'), ' b', ' B'), ' c', ' C'), ' d', ' D'), ' e', ' E'), ' f', ' F'), ' g', ' G'), ' h', ' H'), ' i', ' I'), ' j', ' J'), ' k', ' K'), ' l', ' L'), ' m', ' M'), ' n', ' N'), ' o', ' O'), ' p', ' P'), ' q', ' Q'), ' r', ' R'), ' s', ' S'), ' t', ' T'), ' u', ' U'), ' v', ' V'), ' w', ' W'), ' x', ' X'), ' y', ' Y'), ' z', ' Z'), ' š', ' Š'), ' œ', ' Œ'), ' ž', ' Ž'), ' à', ' À'), ' á', ' Á'), ' â', ' Â'), ' ã', ' Ã'), ' ä', ' Ä'), ' å', ' Å'), ' æ', ' Æ'), ' ç', ' Ç'), ' è', ' È'), ' é', ' É'), ' ê', ' Ê'), ' ë', ' Ë'), ' ì', ' Ì'), ' í', ' Í'), ' î', ' Î'), ' ï', ' Ï'), ' ð', ' Ð'), ' ñ', ' Ñ'), ' ò', ' Ò'), ' ó', ' Ó'), ' ô', ' Ô'), ' õ', ' Õ'), ' ö', ' Ö'), ' ø', ' Ø'), ' ù', ' Ù'), ' ú', ' Ú'), ' û', ' Û'), ' ü', ' Ü'), ' ý', ' Ý'), ' þ', ' Þ'), ' ÿ', ' Ÿ')
    RETURN RIGHT(@str, LEN(@str) - 1)
END
GO
Cervo
fuente
1
Si. Su alfabeto tiene solo 26 caracteres. El mío tiene más. ¿Qué hay del griego? ¿O turco?
Tomalak
Yo diría que las otras soluciones hacen lo mismo. Pero he incluido el generador de código. Puede agregar secciones adicionales para su alfabeto. Debería tener todo como NVARCHAR y usar NCHAR y UNICODE para convertir.
Cervo
Creo que cuantos más personajes tengas, menos eficiente será. Pero diablos, en algunos conjuntos de caracteres, cada símbolo representa una palabra completa, por lo que no se aplica todo el problema de mayúsculas y minúsculas ...
Cervo
También dudo que alguien use todos los caracteres Unicode a la vez. Entonces, probablemente solo el código genere el reemplazo para los 2 o 3 alfabetos que usa.
Cervo
1
Eso no significa que deba usar soluciones a medias en inglés solo porque espera que los datos "estén en su alfabeto, probablemente". En lo que respecta al sistema de escritura latina, hay mayúsculas / minúsculas definidas para (casi) cualquier carácter. Las funciones de conversión tienen más que ver con la corrección que con la velocidad.
Tomalak
0

¿Es demasiado tarde para volver atrás y obtener los datos sin mayúsculas?

Es posible que a los von Neumann, McCain, DeGuzman y Johnson-Smith de su base de clientes no les guste el resultado de su procesamiento ...

Además, supongo que se pretende que sea una actualización única de los datos. Podría ser más fácil exportar, filtrar / modificar y volver a importar los nombres corregidos a la base de datos, y luego puede usar enfoques que no sean SQL para corregir nombres ...

Constructor de juguetes
fuente
Todo el problema de los nombres surgió como posibles inconvenientes cuando se discutió: no hay indicios de que el autor de la pregunta se refiera a datos que contienen nombres.
Tomalak
0

Aquí hay otra variación que encontré en los foros de SQLTeam.com @ http://www.sqlteam.com/forums/topic.asp?TOPIC_ID=47718

create FUNCTION PROPERCASE
(
--The string to be converted to proper case
@input varchar(8000)
)
--This function returns the proper case string of varchar type
RETURNS varchar(8000)
AS
BEGIN
IF @input IS NULL
BEGIN
--Just return NULL if input string is NULL
RETURN NULL
END

--Character variable declarations
DECLARE @output varchar(8000)
--Integer variable declarations
DECLARE @ctr int, @len int, @found_at int
--Constant declarations
DECLARE @LOWER_CASE_a int, @LOWER_CASE_z int, @Delimiter char(3), @UPPER_CASE_A int, @UPPER_CASE_Z int

--Variable/Constant initializations
SET @ctr = 1
SET @len = LEN(@input)
SET @output = ''
SET @LOWER_CASE_a = 97
SET @LOWER_CASE_z = 122
SET @Delimiter = ' ,-'
SET @UPPER_CASE_A = 65
SET @UPPER_CASE_Z = 90

WHILE @ctr <= @len
BEGIN
--This loop will take care of reccuring white spaces
WHILE CHARINDEX(SUBSTRING(@input,@ctr,1), @Delimiter) > 0
BEGIN
SET @output = @output + SUBSTRING(@input,@ctr,1)
SET @ctr = @ctr + 1
END

IF ASCII(SUBSTRING(@input,@ctr,1)) BETWEEN @LOWER_CASE_a AND @LOWER_CASE_z
BEGIN
--Converting the first character to upper case
SET @output = @output + UPPER(SUBSTRING(@input,@ctr,1))
END
ELSE
BEGIN
SET @output = @output + SUBSTRING(@input,@ctr,1)
END

SET @ctr = @ctr + 1

WHILE CHARINDEX(SUBSTRING(@input,@ctr,1), @Delimiter) = 0 AND (@ctr <= @len)
BEGIN
IF ASCII(SUBSTRING(@input,@ctr,1)) BETWEEN @UPPER_CASE_A AND @UPPER_CASE_Z
BEGIN
SET @output = @output + LOWER(SUBSTRING(@input,@ctr,1))
END
ELSE
BEGIN
SET @output = @output + SUBSTRING(@input,@ctr,1)
END
SET @ctr = @ctr + 1
END

END
RETURN @output
END



GO
SET QUOTED_IDENTIFIER OFF
GO
SET ANSI_NULLS ON
GO
Merritt
fuente
0

Sé que el diablo está en los detalles (especialmente en lo que respecta a los datos personales de las personas), y que sería muy bueno tener los nombres en mayúscula correctamente, pero el tipo de molestia anterior es la razón por la que los pragmáticos y conscientes del tiempo entre nosotros usan lo siguiente :

SELECT UPPER('Put YoUR O'So oddLy casED McWeird-nAme von rightHERE here')

En mi experiencia, la gente está bien viendo SU NOMBRE ... incluso cuando está a la mitad de una oración.

Refiérase a: ¡los rusos usaron un lápiz!

Vorlic
fuente
3
Negar la pregunta no es útil. Esta "respuesta" es un comentario EN EL MEJOR.
Phil
0

Acabo de enterarme InitCap().

Aquí hay un código de muestra:

SELECT ID
      ,InitCap(LastName ||', '|| FirstName ||' '|| Nvl(MiddleName,'')) AS RecipientName
FROM SomeTable
EdD
fuente
2
OP especificado Sql Server, 'InitCap ()' es una cosa de Oracle.
mxmissile
0

Esto funcionó en SSMS:

Select Jobtitle,
concat(Upper(LEFT(jobtitle,1)), SUBSTRING(jobtitle,2,LEN(jobtitle))) as Propercase
From [HumanResources].[Employee]
Sathish Babu
fuente
0

Si sabe que todos los datos son solo una palabra, aquí tiene una solución. Primero actualice la columna a todos los más bajos y luego ejecute lo siguiente

    update tableName set columnName = 
    upper(SUBSTRING(columnName, 1, 1)) + substring(columnName, 2, len(columnName)) from tableName
reggaeguitarra
fuente
0

Recientemente tuve que abordar esto y se me ocurrió lo siguiente después de que nada alcanzara todo lo que quería. Esto hará una oración completa, casos para manejo especial de palabras. También tuvimos problemas con las 'palabras' de un solo carácter que manejan muchos de los métodos más simples pero no los más complicados. Variable de retorno única, sin bucles ni cursores.

CREATE FUNCTION ProperCase(@Text AS NVARCHAR(MAX))
RETURNS NVARCHAR(MAX)
AS BEGIN

    DECLARE @return NVARCHAR(MAX)

    SELECT @return = COALESCE(@return + ' ', '') + Word FROM (
         SELECT CASE
            WHEN LOWER(value) = 'llc' THEN UPPER(value)
            WHEN LOWER(value) = 'lp' THEN UPPER(value) --Add as many new special cases as needed
            ELSE
               CASE WHEN LEN(value) = 1
               THEN UPPER(value)
               ELSE UPPER(LEFT(value, 1)) + (LOWER(RIGHT(value, LEN(value) - 1)))
              END
            END AS Word
         FROM STRING_SPLIT(@Text, ' ')
     ) tmp

     RETURN @return
END
Marquesa de Zexks
fuente
0

Copie y pegue sus datos en MS Word y utilice la conversión de texto incorporada a "Capitalizar cada palabra". Compare con sus datos originales para abordar las excepciones. No veo ninguna forma de evitar manualmente las excepciones de tipo "MacDonald" e "IBM", pero así fue como lo hice FWIW.

tobydodds
fuente