问题
I am currently receiving an error when trying to execute a simple SELECT
statement that references an assembly that contains the C# code for the Jaro-Winkler distance algorithm. This is my first time working with SQLCLRs.
I am able to run the code successfully below without the additional OR
statement
Example:
SELECT
*
FROM
USERS
WHERE
(
DATE_OF_BIRTH IS NOT NULL
AND DBO.JAROWINKLER(CONVERT(VARCHAR(6),DATE_OF_BIRTH,12),@DOB) > 0.9
)
OR
(
USERID = @USERID
)
However when I include the OR
statement I receive this error message:
A .NET Framework error occurred during execution of user-defined routine or aggregate "JaroWinkler":
System.NullReferenceException: Object reference not set to an instance of an object. System.NullReferenceException: at JaroWinklerDistanceCLR.JaroWinklerDistance.proximity(String aString1, String aString2)
The code below works and does what is needed. I just wondered if there was another way? Ideally, I would like it contained to one SELECT
statement. I have no idea what the error above is referring to, there are no NULL
values in the UserID
column.
The permission set for the assembly is set to Safe.
Working example:
SELECT
*
FROM
USERS
WHERE
DATE_OF_BIRTH IS NOT NULL
AND DBO.JAROWINKLER(CONVERT(VARCHAR(6),DATE_OF_BIRTH,12),@DOB) > 0.9
UNION ALL
SELECT
*
FROM
USERS
WHERE
USERID = @USERID
回答1:
The other two answers are work arounds, not solutions. And this work-around will have to be duplicated in every place where this function is used, and that is very error-prone and difficult to maintain.
Before getting into the main problem here, there is a minor, related problem that should be fixed first: the input parameter types are incorrect. For SQLCLR methods, you should use the Sql*
types instead of the standard .NET types. For this particular code, that means using SqlString
instead of String
. For more details on why SqlString
instead of String
, please see my answer to the following S.O. question: Should I use SqlString or string as parameter type to SQLCLR UDF's.
Now, the problem is that the SQLCLR code is not properly handling NULL
s. Fortunately, it is not difficult to get it to handle them. There are two options, depending on if any of the input parameters can accept a NULL
or not:
If any of the input parameters can validly pass in a
NULL
, then you need to handle this in the code (and this also applies to all cases when working with Table-Valued Functions and Stored Procedures). And you check in the code via the.IsNull
property that all of theSql*
types have. For example (assumingaString2
can pass in aNULL
):if (aString1.IsNull) { return SqlDouble.Null; }
If none of the input parameters can validly accept
NULL
, then you should bypass all processing without entering the code in the first place by creating the Scalar UDF with theWITH RETURNS NULL ON NULL INPUT
option of theCREATE FUNCTION
statement. With this option set, if any input parameter isNULL
, then the code is skipped and aNULL
return value is assumed. Please note that this only works with Scalar UDFs and User-Defined Type methods.
For more information on working with SQLCLR in general, please see the series of articles I am writing on this topic on SQL Server Central (free registration is required to read content on that site): Stairway to SQLCLR.
On a related note, I would question the use of a string distance function to do what is a rather simple date calculation. I would think that this code would benefit greatly from replacing the JaroWinkler function with a DATEDIFF
based on converting the string @DOB
to DATE
or DATETIME
.
回答2:
The OR statement is most likely including NULL values into your result set which are returning as a different data type. Try using
OR (USERID = @USERID AND AND P.DATE_OF_BIRTH IS NOT NULL)
or, if you require the NULL values then select the field names explicitly (rather than select *) and wrap the date_of_birth field in a convert statement
回答3:
Thank you. NULL
values in the date of birth field.
Working!
SELECT
*
FROM
USERS
WHERE
(
DBO.JAROWINKLER(CONVERT(VARCHAR(6),ISNULL(P.DATE_OF_BIRTH,''),12),@DOB) > 0.9
)
OR
(
USERID = @USERID
)
来源:https://stackoverflow.com/questions/45352980/sqlclr-net-error-object-reference-not-set-to-an-instance-of-an-object