Estoy buscando una función incorporada/función extendida en T-SQL para la manipulación de cadenas similar al método String.Format
en .NET.String.Formato como funcionalidad en T-SQL?
Respuesta
Raw t-sql está limitado a CHARINDEX(), PATINDEX(), REPLACE() y SUBSTRING() para la manipulación de cadenas. Pero con sql server 2005 y posterior puede configurar funciones definidas por el usuario que se ejecutan en .Net, lo que significa que la configuración de un string.format() UDF no debería ser demasiado difícil.
No exactamente, pero me gustaría echar un vistazo a algunos de los articles en el manejo de cadenas (entre otras cosas) por "Factor de Phil" (geddit?) En Simple Talk.
Hay una manera, pero tiene sus limitaciones. Puede usar la función FORMATMESSAGE()
. Le permite formatear una cadena con un formato similar a la función printf()
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 lástima que no hay una manera más fácil de hacerlo, porque hay ocasiones en que desea formatear una cadena/varchar en la base de datos. Con suerte, solo busca formatear una cadena de forma estándar y puede usar la tabla sys.messages
.
Coincidentemente, también puede usar la función RAISERROR()
con una gravedad muy baja, la documentación para raiseerror incluso menciona hacerlo, pero los resultados solo se imprimen. Entonces no podrías hacer nada con el valor resultante (según tengo entendido).
¡Buena suerte!
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 es el siguiente:
INSERT INTO table1 VALUES (1, 2)
acaba de encontrar un problema con el tamaño máximo (255 límite de caracteres) de la cadena con este modo hay una alternative function puede utilizar:
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(@[email protected], 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)
Solo un FYI si alguno de tus parámetros contiene una coma, entonces no tienes suerte. Si pasa uno por accidente, tendrá algunos problemas para descubrir qué salió mal. – Kyle
problemas con unicode? Veo que te refieres a varchar, no a nvarchar ... – barrypicker
He creado una función definida por el usuario para imitar la funcionalidad de string.format. Puedes usarlo.
Agradable. Gracias por hacer esto – NotMe
Me gusta esta solución ya que tengo reservas contra el uso de xp_ funciones/SP en producción. Utilicé el código como base y permití el paso del delimitador, lo que elimina cualquier preocupación sobre las comas que se usan en los datos. –
aquí es lo que me encontré con mis experimentos utilizando la función incorporada
FORMATMESSAGE()
sp_addmessage @msgnum=50001,@severity=1,@msgText='Hello %s you are #%d',@replace='replace'
SELECT FORMATMESSAGE(50001, 'Table1', 5)
cuando llame sp_addmessage, su plantilla de mensaje se almacena en el sistema tabla master.dbo.sysmessages (verificado en SQLServer 2000).
Debe gestionar la adición y eliminación de las cadenas de plantillas de la tabla usted mismo, lo que 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, se ve interesante, pero no funciona con SQL Server 2000, por lo que alteré 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
Creo que hay una pequeña corrección al calcular la posición final.
Aquí es correcto funcionamiento
**>>**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
este enfoque es malo. deberías trabajar con dll de ensamblaje, en el que harás lo mismo para ti con un mejor rendimiento.
Una idea más.
Aunque esto no es una solución universal - que es simple y funciona, al menos para mí :)
Por 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
Durante 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
Por 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í sucesivamente ...
Este enfoque nos permite utilizar estas funciones en la instrucción SELECT y con los parámetros de los 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);
Si está utilizando SQL Server 2012 y anteriormente, el primer argumento para FORMATMESSAGE puede ser una cadena. p.ej.
-- RETURNS Hello World, 123
DECLARE @s VARCHAR(50) = 'World';
DECLARE @d INT = 123;
SELECT FORMATMESSAGE('Hello %s, %d', @s, @d)
Para escapar del signo%, debe duplicarlo.
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:
- indocumentados en 2012
- limitada a 2044 caracteres
- Si está registrando errores en eventos prolongados, FORMATMESSAGE llamando viene como un error (inofensivo).
Si está utilizando SQL 2012, puede usar la [función FORMATO] (https://msdn.microsoft.com/en-us/library/hh213505 (v = sql.110) .aspx) sin todas las complicaciones anteriores:) – DaveBoltman
Oh, sí, ¡por supuesto que tienes razón! – DaveBoltman
¡Esto debería tener mucho más votos! Siempre se ha evitado el descubrimiento impresionante porque se suponía que solo funcionaría con el * 'msg_number' * incorporado. – Lankymart
Aquí está mi versión. Puede ampliarse para acomodar más parámetros y ampliar el formato según el tipo.Actualmente, solo los tipos de fecha y fecha y hora están formateados.
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)
de 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;
Respuesta más simple para SQL Server 2008+. Mantiene las entradas como parámetros separados. Utiliza la función xp_sprintf y se puede ampliar fácilmente. xp_sprintf - https://docs.microsoft.com/en-us/sql/relational-databases/system-stored-procedures/xp-sprintf-transact-sql –
En el momento presente no existe realmente (aunque por supuesto puede escribir su propia) . Hay un error de conexión abierta para él: https://connect.microsoft.com/SQLServer/Feedback/Details/3130221, que a partir de este escrito tiene solo 1 voto.
- 1. VB.NET tienen una funcionalidad similar a "IN" de TSQL?
- 2. cola como funcionalidad para gvim
- 3. inversa funcionalidad gama-como en matrices php
- 4. TSQL: actualizar una columna como null
- 5. android como la funcionalidad de repetidor
- 6. Geany intellisense como funcionalidad para C++
- 7. cscope como funcionalidad para C++ (usando vim)
- 8. Seleccionar datos del archivo XML como tabla en TSQL
- 9. ¿Simular enumeraciones en TSQL?
- 10. Ir a Definición Como Funcionalidad en SQL SERVER
- 11. Buscando la funcionalidad de rsync multiplataforma en python, como rsync.py
- 12. Transacciones anidadas en TSQL
- 13. TSQL - Caso - ¿Valores en?
- 14. tsql usando como con comodín y espacio final?
- 15. TSQL: ¿cómo ejecutar una consulta como una variable?
- 16. TSQL - ISNULL en varias columnas
- 17. transacción tsql
- 18. ¿Puedo usar WITH en TSQL dos veces para filtrar un conjunto de resultados como mi ejemplo?
- 19. ¿Qué hace "%% DatabaseEx" en TSQL?
- 20. TSQL - Desactivar disparadores en transacciones
- 21. Funcionalidad CDPATH en Powershell?
- 22. Diseño de Android como botón con funcionalidad seleccionable
- 23. cómo implementar la funcionalidad atrás y hacia adelante como navegador
- 24. ¿Inconsistencia de TSQL Round()?
- 25. TSQL Complejo Merge
- 26. PHP `` preg_match_all` funcionalidad en Java
- 27. Copiar/Pegar funcionalidad en UITableViewController
- 28. ¿Funcionalidad de XmlSerializer en PowerShell?
- 29. TSQL Conde 'Dónde' Condición
- 30. TSQL Default Minimum DateTime
Comprenda que esta es una respuesta anterior, pero la suposición de que 'FORMATMESSAGE()' es incorrecta, aunque comprensible porque no está documentada, pero aceptará cualquier cadena como primer parámetro, consulte [esta respuesta] (http://stackoverflow.com/a/30260729/692942) por [@ g2server] (http://stackoverflow.com/users/2293226/g2server). – Lankymart
@Lankymart Tiene razón; esta es una respuesta antigua. La capacidad de aceptar una cadena no se agregó hasta SQL 2012. –