I'm looking for the same thing. I came across these two sites: http://www.fotia.co.uk/fotia/Blog/2009/05/indispensable-sql-clr-functions.html & http://stringformat-in-sql.blogspot.com/.
The first uses a CLR function, the other uses a stored procedure.
In the first post, the writer says that UDF parameters aren't optional so you can't have variable number of params (at least the way he is doing it). He just creates a different function with the number or args he will need.
[SqlFunction(DataAccess = DataAccessKind.None)]
public static SqlString FormatString1(SqlString format, object arg0, object arg1)
{
return format.IsNull ? SqlString.Null :
string.Format(format.Value, SqlTypeToNetType(arg0, arg1));
}
EDIT : This is how I solved this problem for me.
Using the stored procedure from the second article, I created this function to format the text for me using a pivot table. Our database is setup with a table dbo.[Rules]
that has a column [Description]
that has a string that needs to be formatted such as: "NET INCOME MARGINAL (${0} TO BELOW ${1})". We then have a 1-many table dbo.[RuleParameters]
with a row for each value that needs to be substituted. The column dbo.[SortOrder]
specifies which order the arguments go in. This function will work for AT MOST 4 arguments which is the most that we have.
CREATE FUNCTION [dbo].[GetRuleDescriptionWithParameters]
(
@Code VARCHAR(3)
)
RETURNS NVARCHAR(MAX)
AS
BEGIN
DECLARE @Result NVARCHAR(400)
SELECT
@Result =
dbo.FormatString([Description],
ISNULL([1], '') + ',' +
ISNULL([2], '') + ',' +
ISNULL([3], '') + ',' +
ISNULL([4], '')
)
FROM
(
SELECT
r.[Description]
,rp.Value
,rp.SortOrder
FROM
[Rules] r
LEFT OUTER JOIN [RuleParameters] rp
ON r.Id = rp.RuleId
WHERE r.Code = @Code
) AS SourceTable
PIVOT
(
MAX(Value)
FOR SortOrder IN ([1], [2], [3], [4])
) AS PivotTable;
RETURN @Result
END
EDIT #2: Adding more examples
Format string function:
CREATE FUNCTION [dbo].[FormatString]
(
@Format NVARCHAR(4000) ,
@Parameters NVARCHAR(4000)
)
RETURNS NVARCHAR(MAX)
AS
BEGIN
DECLARE @Message NVARCHAR(400),
@Delimiter CHAR(1)
DECLARE @ParamTable TABLE ( ID INT IDENTITY(0,1), Paramter VARCHAR(1000) )
SELECT @Message = @Format, @Delimiter = ','
;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 WHENEndPos > 0 THEN EndPos - StartPos ELSE 4000 END )
FROM CTE
UPDATE @ParamTable SET @Message = REPLACE ( @Message, '{'+CONVERT(VARCHAR,ID) + '}', Paramter )
RETURN @Message
END
GO
Here is how I call the stored procedure:
SELECT r.[Id]
,[Code]
,[Description]
,dbo.GetRuleDescriptionWithParameters([Code])
,rp.[Value]
,rp.SortOrder
FROM [Rules] r
INNER JOIN [RuleParameters] rp
ON r.Id = rp.RuleId
Now I can just call the function like this to get everything formatted nicely for me! Here is sample usage with the results:
Id Code Description (No column name) Value SortOrder
1 1 NOT THE MINIMUM AGE NOT THE MINIMUM AGE 18 1
3 8 NET INCOME (BELOW ${0}) NET INCOME (BELOW $400) 400 1
4 9 NET (${0} TO BELOW ${1}) NET ($400 TO BELOW $600) 400 1
4 9 NET (${0} TO BELOW ${1}) NET ($400 TO BELOW $600) 600 2
Normally when calling this, I wouldn’t join on the [RuleParameters] table, but I did in this case so that you can see the data before and after in one data set.