Conversión de cadena de caso Pascal a "Nombre descriptivo" en SQL
-
10-07-2019 - |
Pregunta
Tengo una tabla con una columna cuyos valores provienen de una enumeración. Necesito crear una función TSQL para convertir estos valores a '' Nombres amigables '' al recuperarlo.
Ejemplos:
'DateOfBirth' --> 'Date Of Birth'
'PrincipalStreetAddress' --> 'Principal Street Address'
Necesito una solución directa de TSQL UDF. No tengo la opción de instalar procedimientos de almacenamiento extendido o código CLR.
Solución
/*
Try this. It's a first hack - still has problem of adding extra space
at start if first char is in upper case.
*/
create function udf_FriendlyName(@PascalName varchar(max))
returns varchar(max)
as
begin
declare @char char(1)
set @char = 'A'
-- Loop through the letters A - Z, replace them with a space and the letter
while ascii(@char) <= ascii('Z')
begin
set @PascalName = replace(@PascalName, @char collate Latin1_General_CS_AS, ' ' + @char)
set @char = char(ascii(@char) + 1)
end
return LTRIM(@PascalName) --remove extra space at the beginning
end
Otros consejos
Si está utilizando SQL Server 2005, puede escribir un procedimiento CLR nativo:
static string ToFriendlyCase(this string PascalString)
{
return Regex.Replace(PascalString, "(?!^)([A-Z])", " $1");
}
Salidas:
Convierta mi oración de caso Crazy Pascal en un caso amistoso
Si no usa 2005, debe analizarlo manualmente o hacer referencia al objeto regex mediante procedimientos extendidos. Puede encontrar un buen artículo aquí:
http://www.codeproject.com/KB/mcpp/xpregex.aspx
Editar: un UDF no puede afectar la base de datos, por lo que no puede registrar el objeto regex com, por lo que arroja esa idea. Sin embargo, un procedimiento almacenado puede, por lo que podría ser una ruta.
Para hacer una comparación entre mayúsculas y minúsculas, tendrá que establecer la intercalación para que la consulta sea sensible a mayúsculas y minúsculas, creo que ... aquí hay un artículo que podría ser útil para señalarle fuera en la dirección correcta:
No es la solución más elegante, pero funciona:
declare @pascalCasedString nvarchar(max) = 'PascalCasedString'
declare @friendlyName nvarchar(max) = ''
declare @currentCode int;
declare @currentChar nvarchar;
while (LEN(@pascalCasedString) > 0)
begin
set @currentCode = UNICODE(@pascalCasedString)
set @currentChar = NCHAR(@currentCode)
if ((@currentCode >= 65) AND (@currentCode <= 90))
begin
set @friendlyName += SPACE(1)
end
set @friendlyName += @currentChar
set @pascalCasedString = RIGHT(@pascalCasedString,LEN(@pascalCasedString) - 1)
end
select @friendlyName
declare @arg varchar(20)
set @arg = 'DateOfBirthOnMonday'
declare @argLen int
set @argLen = len(@arg)
declare @output varchar(40)
set @output = ''
declare @i int
set @i = 1
declare @currentChar varchar(1)
declare @currentCharASCII int
while (1 = 1)
begin
set @currentChar = substring(@arg, @i, 1)
set @currentCharASCII = ascii(@currentChar)
if (@currentCharASCII >= 65 and @currentCharASCII <= 90)
set @output = @output + ' '
set @output = @output + @currentChar
set @i = @i+ 1
if (@i > @argLen) break
end
set @output = ltrim(rtrim(@output))
print @output
Cambia el valor de @arg a algo con lo que quieras probar.
Además, es posible que deba cambiar la declaración @output para acomodar una cadena que tenga la misma longitud que el número de espacios @arg + que pueda necesitar. Lo he duplicado en mi ejemplo.
Encontré que esto funciona exactamente como se requiere. Cortesía de SqlAuthority.com :
CREATE FUNCTION dbo.udf_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
Uso:
SELECT dbo.udf_TitleCase('This function will convert this string to title case!')
Salida:
This Function Will Convert This String To Title Case!