像T-SQL中的function类似String.Format?

我在T-SQL中寻找一个类似于.NET中的String.Format方法的内置函数/扩展函数。

看看xp_sprintf 。 下面的例子。

 DECLARE @ret_string varchar (255) EXEC xp_sprintf @ret_string OUTPUT, 'INSERT INTO %s VALUES (%s, %s)', 'table1', '1', '2' PRINT @ret_string 

结果如下所示:

 INSERT INTO table1 VALUES (1, 2) 

刚刚发现这个string的最大大小(255字符限制)的问题,所以有一个替代function,你可以使用:

 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 

要获得与上面相同的结果,请按以下方式调用该函数:

 print dbo.fnSprintf('INSERT INTO %s VALUES (%s, %s)', 'table1,1,2', default) 

如果您使用SQL Server 2012及更高版本,FORMATMESSAGE的第一个参数可以是一个string。 例如。

 -- RETURNS Hello World, 123 DECLARE @s VARCHAR(50) = 'World'; DECLARE @d INT = 123; SELECT FORMATMESSAGE('Hello %s, %d', @s, @d) 

为了逃避%符号,你需要加倍。

更多来自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'); 

笔记:

  • 无证2012年
  • 限制为2044个字符
  • 如果您在扩展事件中logging错误,则调用FORMATMESSAGE会出现(无害)错误。

我创build了一个用户定义的函数来模仿string.format的function。 你可以使用它。

的StringFormatfunction于SQL

对于string操作,原始t-sql仅限于CHARINDEX(),PATINDEX(),REPLACE()和SUBSTRING()。 但是对于SQL Server 2005及更高版本,您可以设置以.Net运行的用户定义函数,这意味着设置一个string.format()UDF不应该太难。

有一种方法,但有其局限性。 您可以使用FORMATMESSAGE()函数。 它允许你使用类似于C中的printf()函数的格式来格式化一个string。

但是,最大的限制是它只能在sys.messages表中使用消息。 这里有一篇关于它的文章: microsoft_library_ms186788

有点不好意思,有没有更简单的方法来做到这一点,因为有时你想在数据库中格式化string/ varchar。 希望你只是想以一种标准的方式来格式化一个string,并且可以使用sys.messages表。

巧合的是,您也可以使用RAISERROR()函数,其严重程度非常低,即使提到这个问题,文档也会提到这个问题,但结果只是打印出来的。 所以你不能做任何事情的结果价值(从我的理解)。

祝你好运!

我认为在计算结束位置时有小的修正。

这是正确的function

 **>>**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 DV 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 

这是我的版本。 可以扩展以容纳更多数量的参数,并可以扩展基于types的格式。 目前仅格式化date和date时间types。

例:

 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) 

输出:

 some string "abcd" some int 100 date 29-Apr-2017 some string "abcd" some int 100 date time 29-Apr-2017 19:40 

function:

 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; 

不完全是这样,但是我会通过Simple Talk上的“Phil Factor”(geddit?)检查一些关于string处理的文章 (除其他外)。

这是我用我内置的实验发现的

FORMATMESSAGE()函数

 sp_addmessage @msgnum=50001,@severity=1,@msgText='Hello %s you are #%d',@replace='replace' SELECT FORMATMESSAGE(50001, 'Table1', 5) 

当调用sp_addmessage时,消息模板将被存储到系统表master.dbo.sysmessages中(在SQL Server 2000上进行validation)。

您必须自行pipe理表格中模板string的添加和删除操作,如果您真正想要的只是向结果屏幕输出一条快速消息,则会很尴尬。

由Kathik DV提供的解决scheme,看起来很有趣,但不适用于SQL Server 2000,所以我修改了一下,这个版本应该适用于所有版本的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 DV 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 

用法:

 print dbo.formatString('hello {0}... you are {1}','world,good') --result: hello world... you are good 

还有一个想法。

虽然这不是一个通用的解决scheme – 它是简单的,至less对我来说:)

对于一个占位符{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 

对于两个占位符{0}和{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 

对于三个占位符{0},{1}和{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 

等等…

这种方法允许我们在SELECT语句中使用这些函数,并使用nvarchar,number,bit和datetime数据types的参数。

例如:

 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); 

这是不好的方法。 你应该使用程序集的DLL,其中将为你做更好的性能相同。