I'm looking for a built-in function/extended function in T-SQL for string manipulation similar to the String.Format method in .NET.
I'm looking for a built-in function/extended function in T-SQL for string manipulation similar to the String.Format method in .NET.
take a look at xp_sprintf. example below.
DECLARE @ret_string varchar (255)
EXEC xp_sprintf @ret_string OUTPUT,
'INSERT INTO %s VALUES (%s, %s)', 'table1', '1', '2'
PRINT @ret_string
Result looks like this:
INSERT INTO table1 VALUES (1, 2)
Just found an issue with the max size (255 char limit) of the string with this so there is an alternative function you can use:
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
To get the same result as above you call the function as follows:
print dbo.fnSprintf('INSERT INTO %s VALUES (%s, %s)', 'table1,1,2', default)
I have created a user defined function to mimic the string.format functionality. You can use it.
UPDATE:
This version allows the user to change the delimitter.
-- DROP function will loose the security settings.
IF object_id('[dbo].[svfn_FormatString]') IS NOT NULL
DROP FUNCTION [dbo].[svfn_FormatString]
GO
CREATE FUNCTION [dbo].[svfn_FormatString]
(
@Format NVARCHAR(4000),
@Parameters NVARCHAR(4000),
@Delimiter CHAR(1) = ','
)
RETURNS NVARCHAR(MAX)
AS
BEGIN
/*
Name: [dbo].[svfn_FormatString]
Creation Date: 12/18/2020
Purpose: Returns the formatted string (Just like in C-Sharp)
Input Parameters: @Format = The string to be Formatted
@Parameters = The comma separated list of parameters
@Delimiter = The delimitter to be used in the formatting process
Format: @Format = N'Hi {0}, Welcome to our site {1}. Thank you {0}'
@Parameters = N'Karthik,google.com'
@Delimiter = ','
Examples:
SELECT dbo.svfn_FormatString(N'Hi {0}, Welcome to our site {1}. Thank you {0}', N'Karthik,google.com', default)
SELECT dbo.svfn_FormatString(N'Hi {0}, Welcome to our site {1}. Thank you {0}', N'Karthik;google.com', ';')
*/
DECLARE @Message NVARCHAR(400)
DECLARE @ParamTable TABLE ( Id INT IDENTITY(0,1), Paramter VARCHAR(1000))
SELECT @Message = @Format
;WITH CTE (StartPos, EndPos) AS
(
SELECT 1, CHARINDEX(@Delimiter, @Parameters)
UNION ALL
SELECT EndPos + (LEN(@Delimiter)), CHARINDEX(@Delimiter, @Parameters, EndPos + (LEN(@Delimiter)))
FROM CTE
WHERE EndPos > 0
)
INSERT INTO @ParamTable ( Paramter )
SELECT
[Id] = SUBSTRING(@Parameters, StartPos, CASE WHEN EndPos > 0 THEN EndPos - StartPos ELSE 4000 END )
FROM CTE
UPDATE @ParamTable
SET
@Message = REPLACE(@Message, '{'+ CONVERT(VARCHAR, Id) + '}', Paramter )
RETURN @Message
END
There is a way, but it has its limitations. You can use the FORMATMESSAGE() function. It allows you to format a string using formatting similar to the printf() function in C.
However, the biggest limitation is that it will only work with messages in the sys.messages table. Here's an article about it: microsoft_library_ms186788
It's kind of a shame there isn't an easier way to do this, because there are times when you want to format a string/varchar in the database. Hopefully you are only looking to format a string in a standard way and can use the sys.messages table.
Coincidentally, you could also use the RAISERROR() function with a very low severity, the documentation for raiseerror even mentions doing this, but the results are only printed. So you wouldn't be able to do anything with the resulting value (from what I understand).
Good luck!
Raw t-sql is limited to CHARINDEX(), PATINDEX(), REPLACE(), and SUBSTRING() for string manipulation. But with sql server 2005 and later you can set up user defined functions that run in .Net, which means setting up a string.format() UDF shouldn't be too tough.
I think there is small correction while calculating end position.
Here is correct 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 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
Actually there is no built in function similar to string.Format function of .NET is available in SQL server.
There is a function FORMATMESSAGE() in SQL server but it mimics to printf() function of C not string.Format function of .NET.
SELECT FORMATMESSAGE('This is the %s and this is the %s.', 'first variable', 'second variable') AS Result
here's what I found with my experiments using the built-in
FORMATMESSAGE() function
sp_addmessage @msgnum=50001,@severity=1,@msgText='Hello %s you are #%d',@replace='replace'
SELECT FORMATMESSAGE(50001, 'Table1', 5)
when you call up sp_addmessage, your message template gets stored into the system table master.dbo.sysmessages (verified on SQLServer 2000).
You must manage addition and removal of template strings from the table yourself, which is awkward if all you really want is output a quick message to the results screen.
The solution provided by Kathik DV, looks interesting but doesn't work with SQL Server 2000, so i altered it a bit, and this version should work with all versions of 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
Usage:
print dbo.formatString('hello {0}... you are {1}','world,good')
--result: hello world... you are good
Not exactly, but I would check out some of the articles on string handling (amongst other things) by "Phil Factor" (geddit?) on Simple Talk.
this is bad approach. you should work with assembly dll's, in which will do the same for you with better performance.