views:

170

answers:

1

How can I return a identity column with a standard SQL CLR Split UDF for example the code below will return a table with the string value split by delimiter, I need to somehow return an identity column as well.

<SqlFunction(FillRowMethodName:="FillRow", TableDefinition:="value nvarchar(4000)")> _
Public Shared Function GetStrings(ByVal str As SqlString, ByVal delimiter As SqlString) As IEnumerable
    If (str.IsNull OrElse delimiter.IsNull) Then
        Return Nothing
    Else
        Return str.Value.Split(CChar(delimiter))
    End If
End Function
Public Shared Sub FillRow(ByVal row As Object, ByRef str As String)
    str = CType(row, String).Trim()
End Sub
+2  A: 

In terms of a CLR UDF, "identity" doesn't have any particular meaning, since you are generating all of the rows yourself. All you want is a counter.

Simple answer would be to just generate the indexes on the spot and then send an IEnumerable of composite values. So something like this:

[SqlFunction(FillRowMethodName = "FillMyRow",
    TableDefinition = "ID int, Value nvarchar(4000)")]
public static IEnumerable GetStrings(SqlString str, SqlString delimiter)
{
    if (str.IsNull || delimiter.IsNull)
    {
        return null;
    }

    string[] values = str.Value.Split(delimiter.Value.ToCharArray());
    StringPair[] results = new StringPair[values.Length];
    for (int i = 0; i < values.Length; i++)
    {
        results[i] = new StringPair(i + 1, values[i]);
    }
    return results;
}

public static void FillMyRow(object row, ref int id, ref string value)
{
    StringPair pair = (StringPair)row;
    id = pair.ID;
    value = pair.Value;
}

public class StringPair
{
    public StringPair(int id, string value)
    {
        this.id = id;
        this.value = value;
    }

    public int ID { get; private set; }
    public string Value { get; private set; }
}

It's the exact same thing as an identity column; you're just incrementing a counter for the ID, starting from the number 1.

You might also want to consider that a surrogate ID can be generated in SQL itself with ROW_NUMBER, so it may not be necessary to do this at all. That would be my choice, personally, but if you need to do it in the CLR output, the above code should do the trick.

Aaronaught