Estoy buscando una función incorporada / función extendida en T-SQL para la manipulación de cadenas similar al String.Formatmétodo en .NET.
Respuestas:
Si está utilizando SQL Server 2012 y superior, puede utilizar FORMATMESSAGE. p.ej.
DECLARE @s NVARCHAR(50) = 'World';
DECLARE @d INT = 123;
SELECT FORMATMESSAGE('Hello %s, %d', @s, @d)
-- RETURNS 'Hello World, 123'
Más ejemplos de MSDN: FORMATMESSAGE
SELECT FORMATMESSAGE('Signed int %i, %d %i, %d, %+i, %+d, %+i, %+d', 5, -5, 50, -50, -11, -11, 11, 11);
SELECT FORMATMESSAGE('Signed int with leading zero %020i', 5);
SELECT FORMATMESSAGE('Signed int with leading zero 0 %020i', -55);
SELECT FORMATMESSAGE('Unsigned int %u, %u', 50, -50);
SELECT FORMATMESSAGE('Unsigned octal %o, %o', 50, -50);
SELECT FORMATMESSAGE('Unsigned hexadecimal %x, %X, %X, %X, %x', 11, 11, -11, 50, -50);
SELECT FORMATMESSAGE('Unsigned octal with prefix: %#o, %#o', 50, -50);
SELECT FORMATMESSAGE('Unsigned hexadecimal with prefix: %#x, %#X, %#X, %X, %x', 11, 11, -11, 50, -50);
SELECT FORMATMESSAGE('Hello %s!', 'TEST');
SELECT FORMATMESSAGE('Hello %20s!', 'TEST');
SELECT FORMATMESSAGE('Hello %-20s!', 'TEST');
SELECT FORMATMESSAGE('Hello %20s!', 'TEST');
NOTAS:
FORMATMESSAGEaparece como un error (inofensivo)msg_number.
string.Formatfuncionalidad de estilo en T-SQL, esto es lo más cercano que obtendrá.
eche un vistazo a xp_sprintf . ejemplo a continuación.
DECLARE @ret_string varchar (255)
EXEC xp_sprintf @ret_string OUTPUT,
'INSERT INTO %s VALUES (%s, %s)', 'table1', '1', '2'
PRINT @ret_string
El resultado se ve así:
INSERT INTO table1 VALUES (1, 2)
Acabo de encontrar un problema con el tamaño máximo (límite de 255 caracteres) de la cadena con esto, por lo que hay una función alternativa que puede usar:
create function dbo.fnSprintf (@s varchar(MAX),
@params varchar(MAX), @separator char(1) = ',')
returns varchar(MAX)
as
begin
declare @p varchar(MAX)
declare @paramlen int
set @params = @params + @separator
set @paramlen = len(@params)
while not @params = ''
begin
set @p = left(@params+@separator, charindex(@separator, @params)-1)
set @s = STUFF(@s, charindex('%s', @s), 2, @p)
set @params = substring(@params, len(@p)+2, @paramlen)
end
return @s
end
Para obtener el mismo resultado que el anterior, llame a la función de la siguiente manera:
print dbo.fnSprintf('INSERT INTO %s VALUES (%s, %s)', 'table1,1,2', default)
He creado una función definida por el usuario para imitar la funcionalidad string.format. Puedes usarlo.
Hay una forma, pero tiene sus limitaciones. Puede utilizar la FORMATMESSAGE()función. Le permite formatear una cadena usando un formato similar a la printf()función en C.
Sin embargo, la mayor limitación es que solo funcionará con mensajes en la tabla sys.messages. Aquí hay un artículo al respecto: microsoft_library_ms186788
Es una pena que no haya una manera más fácil de hacer esto, porque hay ocasiones en las que desea formatear una cadena / varchar en la base de datos. Con suerte, solo está buscando formatear una cadena de una manera estándar y puede usar la sys.messagestabla.
Casualmente, también podría usar la RAISERROR()función con una gravedad muy baja, la documentación de raiseerror incluso menciona hacer esto, pero los resultados solo se imprimen. Por lo tanto, no podría hacer nada con el valor resultante (por lo que entiendo).
¡Buena suerte!
FORMATMESSAGE()es incorrecta, sin embargo es comprensible porque no está documentada pero aceptará cualquier cadena como primer parámetro, vea esta respuesta de @ g2server .
El t-sql sin formato está limitado a CHARINDEX (), PATINDEX (), REPLACE () y SUBSTRING () para la manipulación de cadenas. Pero con sql server 2005 y versiones posteriores, puede configurar funciones definidas por el usuario que se ejecutan en .Net, lo que significa que configurar una UDF string.format () no debería ser demasiado difícil.
Una idea más.
Aunque esta no es una solución universal, es simple y funciona, al menos para mí :)
Para un marcador de posición {0}:
create function dbo.Format1
(
@String nvarchar(4000),
@Param0 sql_variant
)
returns nvarchar(4000)
as
begin
declare @Null nvarchar(4) = N'NULL';
return replace(@String, N'{0}', cast(isnull(@Param0, @Null) as nvarchar(4000)));
end
Para dos marcadores de posición {0} y {1}:
create function dbo.Format2
(
@String nvarchar(4000),
@Param0 sql_variant,
@Param1 sql_variant
)
returns nvarchar(4000)
as
begin
declare @Null nvarchar(4) = N'NULL';
set @String = replace(@String, N'{0}', cast(isnull(@Param0, @Null) as nvarchar(4000)));
return replace(@String, N'{1}', cast(isnull(@Param1, @Null) as nvarchar(4000)));
end
Para tres marcadores de posición {0}, {1} y {2}:
create function dbo.Format3
(
@String nvarchar(4000),
@Param0 sql_variant,
@Param1 sql_variant,
@Param2 sql_variant
)
returns nvarchar(4000)
as
begin
declare @Null nvarchar(4) = N'NULL';
set @String = replace(@String, N'{0}', cast(isnull(@Param0, @Null) as nvarchar(4000)));
set @String = replace(@String, N'{1}', cast(isnull(@Param1, @Null) as nvarchar(4000)));
return replace(@String, N'{2}', cast(isnull(@Param2, @Null) as nvarchar(4000)));
end
y así...
Este enfoque nos permite usar estas funciones en la instrucción SELECT y con parámetros de tipos de datos nvarchar, number, bit y datetime.
Por ejemplo:
declare @Param0 nvarchar(10) = N'IPSUM' ,
@Param1 int = 1234567 ,
@Param2 datetime2(0) = getdate();
select dbo.Format3(N'Lorem {0} dolor, {1} elit at {2}', @Param0, @Param1, @Param2);
Creo que hay una pequeña corrección al calcular la posición final.
Aquí está la función correcta
**>>**IF OBJECT_ID( N'[dbo].[FormatString]', 'FN' ) IS NOT NULL
DROP FUNCTION [dbo].[FormatString]
GO
/***************************************************
Object Name : FormatString
Purpose : Returns the formatted string.
Original Author : Karthik D V http://stringformat-in-sql.blogspot.com/
Sample Call:
SELECT dbo.FormatString ( N'Format {0} {1} {2} {0}', N'1,2,3' )
*******************************************/
CREATE FUNCTION [dbo].[FormatString](
@Format NVARCHAR(4000) ,
@Parameters NVARCHAR(4000)
)
RETURNS NVARCHAR(4000)
AS
BEGIN
--DECLARE @Format NVARCHAR(4000), @Parameters NVARCHAR(4000) select @format='{0}{1}', @Parameters='hello,world'
DECLARE @Message NVARCHAR(400), @Delimiter CHAR(1)
DECLARE @ParamTable TABLE ( ID INT IDENTITY(0,1), Parameter VARCHAR(1000) )
Declare @startPos int, @endPos int
SELECT @Message = @Format, @Delimiter = ','**>>**
--handle first parameter
set @endPos=CHARINDEX(@Delimiter,@Parameters)
if (@endPos=0 and @Parameters is not null) --there is only one parameter
insert into @ParamTable (Parameter) values(@Parameters)
else begin
insert into @ParamTable (Parameter) select substring(@Parameters,0,@endPos)
end
while @endPos>0
Begin
--insert a row for each parameter in the
set @startPos = @endPos + LEN(@Delimiter)
set @endPos = CHARINDEX(@Delimiter,@Parameters, @startPos)
if (@endPos>0)
insert into @ParamTable (Parameter)
select substring(@Parameters,@startPos,@endPos - @startPos)
else
insert into @ParamTable (Parameter)
select substring(@Parameters,@startPos,4000)
End
UPDATE @ParamTable SET @Message =
REPLACE ( @Message, '{'+CONVERT(VARCHAR,ID) + '}', Parameter )
RETURN @Message
END
Go
grant execute,references on dbo.formatString to public
Aquí está mi versión. Puede ampliarse para adaptarse a más parámetros y puede ampliar el formato según el tipo. Actualmente, solo se formatean los tipos de fecha y fecha y hora.
Ejemplo:
select dbo.FormatString('some string %s some int %s date %s','"abcd"',100,cast(getdate() as date),DEFAULT,DEFAULT)
select dbo.FormatString('some string %s some int %s date time %s','"abcd"',100,getdate(),DEFAULT,DEFAULT)
Salida:
some string "abcd" some int 100 date 29-Apr-2017
some string "abcd" some int 100 date time 29-Apr-2017 19:40
Funciones:
create function dbo.FormatValue(@param sql_variant)
returns nvarchar(100)
begin
/*
Tejasvi Hegde, 29-April-2017
Can extend formatting here.
*/
declare @result nvarchar(100)
if (SQL_VARIANT_PROPERTY(@param,'BaseType') in ('date'))
begin
select @result = REPLACE(CONVERT(CHAR(11), @param, 106), ' ', '-')
end
else if (SQL_VARIANT_PROPERTY(@param,'BaseType') in ('datetime','datetime2'))
begin
select @result = REPLACE(CONVERT(CHAR(11), @param, 106), ' ', '-')+' '+CONVERT(VARCHAR(5),@param,108)
end
else
begin
select @result = cast(@param as nvarchar(100))
end
return @result
/*
BaseType:
bigint
binary
char
date
datetime
datetime2
datetimeoffset
decimal
float
int
money
nchar
numeric
nvarchar
real
smalldatetime
smallint
smallmoney
time
tinyint
uniqueidentifier
varbinary
varchar
*/
end;
create function dbo.FormatString(
@format nvarchar(4000)
,@param1 sql_variant = null
,@param2 sql_variant = null
,@param3 sql_variant = null
,@param4 sql_variant = null
,@param5 sql_variant = null
)
returns nvarchar(4000)
begin
/*
Tejasvi Hegde, 29-April-2017
select dbo.FormatString('some string value %s some int %s date %s','"abcd"',100,cast(getdate() as date),DEFAULT,DEFAULT)
select dbo.FormatString('some string value %s some int %s date time %s','"abcd"',100,getdate(),DEFAULT,DEFAULT)
*/
declare @result nvarchar(4000)
select @param1 = dbo.formatValue(@param1)
,@param2 = dbo.formatValue(@param2)
,@param3 = dbo.formatValue(@param3)
,@param4 = dbo.formatValue(@param4)
,@param5 = dbo.formatValue(@param5)
select @param2 = cast(@param2 as nvarchar)
EXEC xp_sprintf @result OUTPUT,@format , @param1, @param2, @param3, @param4, @param5
return @result
end;
esto es lo que encontré con mis experimentos usando el integrado
Función FORMATMESSAGE ()
sp_addmessage @msgnum=50001,@severity=1,@msgText='Hello %s you are #%d',@replace='replace'
SELECT FORMATMESSAGE(50001, 'Table1', 5)
cuando llama sp_addmessage, su plantilla de mensaje se almacena en la tabla del sistema master.dbo.sysmessages (verificado en SQLServer 2000).
Debe administrar la adición y eliminación de cadenas de plantilla de la tabla usted mismo, lo cual es incómodo si todo lo que realmente desea es enviar un mensaje rápido a la pantalla de resultados.
La solución proporcionada por Kathik DV parece interesante pero no funciona con SQL Server 2000, así que la modifiqué un poco y esta versión debería funcionar con todas las versiones de SQL Server:
IF OBJECT_ID( N'[dbo].[FormatString]', 'FN' ) IS NOT NULL
DROP FUNCTION [dbo].[FormatString]
GO
/***************************************************
Object Name : FormatString
Purpose : Returns the formatted string.
Original Author : Karthik D V http://stringformat-in-sql.blogspot.com/
Sample Call:
SELECT dbo.FormatString ( N'Format {0} {1} {2} {0}', N'1,2,3' )
*******************************************/
CREATE FUNCTION [dbo].[FormatString](
@Format NVARCHAR(4000) ,
@Parameters NVARCHAR(4000)
)
RETURNS NVARCHAR(4000)
AS
BEGIN
--DECLARE @Format NVARCHAR(4000), @Parameters NVARCHAR(4000) select @format='{0}{1}', @Parameters='hello,world'
DECLARE @Message NVARCHAR(400), @Delimiter CHAR(1)
DECLARE @ParamTable TABLE ( ID INT IDENTITY(0,1), Parameter VARCHAR(1000) )
Declare @startPos int, @endPos int
SELECT @Message = @Format, @Delimiter = ','
--handle first parameter
set @endPos=CHARINDEX(@Delimiter,@Parameters)
if (@endPos=0 and @Parameters is not null) --there is only one parameter
insert into @ParamTable (Parameter) values(@Parameters)
else begin
insert into @ParamTable (Parameter) select substring(@Parameters,0,@endPos)
end
while @endPos>0
Begin
--insert a row for each parameter in the
set @startPos = @endPos + LEN(@Delimiter)
set @endPos = CHARINDEX(@Delimiter,@Parameters, @startPos)
if (@endPos>0)
insert into @ParamTable (Parameter) select substring(@Parameters,@startPos,@endPos)
else
insert into @ParamTable (Parameter) select substring(@Parameters,@startPos,4000)
End
UPDATE @ParamTable SET @Message = REPLACE ( @Message, '{'+CONVERT(VARCHAR,ID) + '}', Parameter )
RETURN @Message
END
Go
grant execute,references on dbo.formatString to public
Uso:
print dbo.formatString('hello {0}... you are {1}','world,good')
--result: hello world... you are good
Por el momento, esto no existe realmente (aunque, por supuesto, puede escribir el suyo). Hay un error de conexión abierta para él: https://connect.microsoft.com/SQLServer/Feedback/Details/3130221 , que al momento de escribir este artículo tiene solo 1 voto.
En realidad, no hay una función incorporada similar a la cadena. La función de formato de .NET está disponible en el servidor SQL.
Hay una función FORMATMESSAGE () en el servidor SQL pero imita la función printf () de C, no la función string.Format de .NET.
SELECT FORMATMESSAGE('This is the %s and this is the %s.', 'first variable', 'second variable') AS Result
No exactamente, pero vería algunos de los artículos sobre manejo de cadenas (entre otras cosas) de "Phil Factor" (¿geddit?) En Simple Talk.