Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

SQL Server -- Handling null input in CLR User-Defined Function (UDF) with OnNullCall

I have a user-defined function in SQL Server (written in .NET) that cleans text. I'm wondering how to handle null input.

Here is the function in C#:

[Microsoft.SqlServer.Server.SqlFunction]
public static SqlChars cleanEstActText(SqlChars input)
{
    SqlChars cascadingSqlChar = removeNBSP(input);
    cascadingSqlChar = optimizeFontTags(cascadingSqlChar);

    return cascadingSqlChar;
}

This is the error in SQL if the function gets any null data:

A .NET Framework error occurred during execution of user-defined routine or aggregate "removeNBSP": 
System.Data.SqlTypes.SqlNullValueException: Data is Null. This method or property cannot be called on Null values.
System.Data.SqlTypes.SqlNullValueException: 
   at System.Data.SqlTypes.SqlChars.get_Value()
   at UserDefinedFunctions.removeNBSP(SqlChars input)

Reading on SO and Google led me to the OnNullCall attribute, which looks promising.

From MSDN:

true if the method is called when null (Nothing in Visual Basic) input arguments are specified in the method invocation; false if the method returns a null (Nothing in Visual Basic) value when any of its input parameters are null (Nothing in Visual Basic).

Sounds exactly like what I want; if I get null, just pass null through. I'm not quite sure how to implement it, so I check MSDN again (http://msdn.microsoft.com/en-us/library/microsoft.sqlserver.server.sqlmethodattribute.aspx), and rewrite the first line of my function from

[Microsoft.SqlServer.Server.SqlFunction]

to

[Microsoft.SqlServer.Server.SqlMethod(OnNullCall = false, IsMutator = false, InvokeIfReceiverIsNull = false)]

If I do this, I get an error in SQL any time I use it:

Cannot find either column "dbo" or the user-defined function or aggregate "dbo.cleanEstActText", or the name is ambiguous.

Am I implementing OnNullCall incorrectly? Should I be doing something else? Is there really any good way to make my function pass nulls through?

like image 711
jtpereyda Avatar asked Dec 27 '10 21:12

jtpereyda


People also ask

Is it possible to return null inside a UDF?

However, SQL Server does not allow this inside a UDF (though you can raise exceptions in CLR-based UDFs, go figure). My last resort would be to return a NULL (or some other error-indicator value) from the function if the input value is in error. However, I don't like this option, as it:

What is a user defined function in CLR?

CLR User-Defined Functions. User-defined functions are routines that can take parameters, perform calculations or other actions, and return a result. Beginning with SQL Server 2005 (9.x), you can write user-defined functions in any Microsoft .NET Framework programming language, such as Microsoft Visual Basic .NET or Microsoft Visual C#.

How do I return NULL values from a function in SQL?

There is an option introduced in SQL Server 2005 “WITH RETURNS NULL ON NULL INPUT” to handle this with a grace as below. This way, if any of your input parameters is passed as NULL value, then the function will immediately return NULL value without actually invoking the body of the function.

How do I check if an expression is null in SQL Server?

SQL Server provides 2 functions for doing this; (i) the ISNULL; and (ii) the COALESCE. (1) ISNULL takes only two parameters as input; (a) the expression to be checked and (b) the replacement value (2) COALESCE takes N parameters as input ( N>=2 ). By having N expressions as input parameters it returns the first expression that IS NOT NULL.


2 Answers

You can try this

[Microsoft.SqlServer.Server.SqlFunction]
public static SqlChars cleanEstActText(SqlChars input)
{

    if (input.IsNull) return null;

    SqlChars cascadingSqlChar = removeNBSP(input);
    cascadingSqlChar = optimizeFontTags(cascadingSqlChar);

    return cascadingSqlChar;
}

All Nullable SqlData Types have an IsNull Propery.

Thanks Hari

like image 178
Hari Sandeep Gutta Avatar answered Nov 05 '22 05:11

Hari Sandeep Gutta


The accepted answer is not correct, though it does technically work. The problem with checking for NULLs in the code itself is that the code is called and has to perform that check. This is required only when wanting to allow one or more parameters to pass a valid NULL in without causing the execution of the method to be skipped.

This is definitely possible to do, though unfortunately not through the Visual Studio / SSDT publishing mechanism that creates all of the T-SQL for you. In order to accomplish this, you need to either:

  • Manually deploy the T-SQL CREATE FUNCTION statement
  • Do an ALTER FUNCTION after the code has been published to SQL Server

In either case, the syntax for this, as described in the MSDN page for CREATE FUNCTION, is: WITH RETURNS NULL ON NULL INPUT.

To put it in full context:

CREATE FUNCTION SchemaName.FunctionName ( { parameter_list } )
RETURNS DataType
WITH RETURNS NULL ON NULL INPUT
AS EXTERNAL NAME ...

Again, keep in mind that if this option is specified, then any input parameter that is NULL will cause the function to be skipped and return NULL.

UPDATE:
Please vote on the following Microsoft Connect suggestion so that hopefully support is added for the OnNullCall property of the SqlFunction attribute:

Implement OnNullCall property in SqlFunctionAttribute for RETURNS NULL ON NULL INPUT

like image 43
Solomon Rutzky Avatar answered Nov 05 '22 06:11

Solomon Rutzky