Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

SQL CLR - "Static" variable for the current context

Tags:

c#

sqlclr

t-sql

I know the use of a static variable in your DLL is unsafe, but is there any way to have something similar, or a variable that only exists for the current context?

What I'm trying to do is create a UDF which takes a comma-separated string, and returns a table with two columns, one is the index/order of the value in the original string, the other is the value itself. The splitting is easy (there's plenty of examples on-line, my code is below), but getting the order seems impossible.

I've tried using an IDENTITY column, but they're disallowed ("Cannot use 'IDENTITY' column in the result table of a streaming user-defined function"), and using a static vaiable is a no-go. In a web project, you get System.Web.HttpContext.Current, is there anything similar for a SQL project? Or is there a better way to do what I'm looking for?

SQL

CREATE FUNCTION SplitToInt(@list nvarchar(MAX), @delim nchar(1) = N',')
RETURNS TABLE (Value int)
AS EXTERNAL NAME CompanyName.Functions.SplitToInt
GO

C#

[SqlFunction(FillRowMethodName = "SplitToIntFillRow")]
public static IEnumerable SplitToInt(SqlString str, SqlString separator)
{
    return str.Value.Split(!separator.IsNull && separator.Value.Length > 0 ? separator.Value[0] : ',');
}

public static void SplitToIntFillRow(object row, out int Value)
{
    Value = System.Convert.ToInt32((string)row);
}
like image 654
Vitani Avatar asked Feb 16 '26 08:02

Vitani


1 Answers

My solution (funny how writing things down, walking away, and coming back makes you see the obvious)

SQL

CREATE FUNCTION SplitToInt(@list nvarchar(max), @separator nchar(1) = N',')
RETURNS TABLE (InLevelOrder int, Value int)
AS EXTERNAL NAME CompanyName.Functions.SplitToInt
GO

C#

[SqlFunction(FillRowMethodName = "SplitToIntFillRow")]
public static IEnumerable SplitToInt(SqlString str, SqlString separator)
{
    var s = str.Value.Split(!separator.IsNull && separator.Value.Length > 0 ? separator.Value[0] : ',');
    var rtn = new List<int[]>(s.Length);
    for (int i = 0; i < s.Length; i++)
        rtn.Add(new[] { i, System.Convert.ToInt32(s[i]) });
    return rtn;
}

public static void SplitToIntFillRow(object row, out int InLevelOrder, out int Value)
{
    InLevelOrder = ((int[])row)[0];
    Value = ((int[])row)[1];
}

If anyone can improve on this, feel free to comment.

like image 180
Vitani Avatar answered Feb 17 '26 21:02

Vitani



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!