SQL Server - Обработка нулевого ввода в пользовательской функции CLR с помощью OnNullCall
У меня есть пользовательская функция в SQL Server (написана на.NET), которая очищает текст. Мне интересно, как обрабатывать нулевой ввод.
Вот функция в C#:
[Microsoft.SqlServer.Server.SqlFunction]
public static SqlChars cleanEstActText(SqlChars input)
{
SqlChars cascadingSqlChar = removeNBSP(input);
cascadingSqlChar = optimizeFontTags(cascadingSqlChar);
return cascadingSqlChar;
}
Это ошибка в SQL, если функция получает нулевые данные:
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)
Чтение на SO и Google привело меня к атрибуту OnNullCall, который выглядит многообещающим.
Из MSDN:
Значение true, если метод вызывается, когда в вызове метода указаны входные аргументы null (Nothing в Visual Basic); false, если метод возвращает значение NULL (Nothing в Visual Basic), когда любой из его входных параметров имеет значение NULL (Nothing в Visual Basic).
Звучит так, как я хочу; если я получу ноль, просто пропустите ноль. Я не совсем уверен, как это реализовать, поэтому я снова проверяю MSDN (http://msdn.microsoft.com/en-us/library/microsoft.sqlserver.server.sqlmethodattribute.aspx) и переписываю первую строку моя функция от
[Microsoft.SqlServer.Server.SqlFunction]
в
[Microsoft.SqlServer.Server.SqlMethod(OnNullCall = false, IsMutator = false, InvokeIfReceiverIsNull = false)]
Если я делаю это, я получаю ошибку в SQL каждый раз, когда использую его:
Cannot find either column "dbo" or the user-defined function or aggregate "dbo.cleanEstActText", or the name is ambiguous.
Я неправильно внедряю OnNullCall? Должен ли я делать что-то еще? Есть ли действительно хороший способ сделать так, чтобы моя функция передавала нули через?
4 ответа
Вы можете попробовать это
[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.
Спасибо Хари
Принятый ответ не верен, хотя он технически работает. Проблема с проверкой NULL в самом коде состоит в том, что код вызывается и должен выполнить эту проверку. Это требуется только в том случае, если необходимо разрешить одному или нескольким параметрам передавать допустимый NULL без пропуска выполнения метода.
Это определенно возможно сделать, но, к сожалению, не через механизм публикации Visual Studio / SSDT, который создает весь T-SQL для вас. Для этого вам необходимо:
- Вручную разверните T-SQL
CREATE FUNCTION
заявление - Сделать
ALTER FUNCTION
после того, как код был опубликован на SQL Server
В любом случае, синтаксис для этого, как описано на странице MSDN для CREATE FUNCTION, таков: WITH RETURNS NULL ON NULL INPUT
,
Чтобы выразить это в полном контексте:
CREATE FUNCTION SchemaName.FunctionName ( { parameter_list } )
RETURNS DataType
WITH RETURNS NULL ON NULL INPUT
AS EXTERNAL NAME ...
Опять же, имейте в виду, что если указан этот параметр, то любой входной параметр, который NULL
приведет к пропуску функции и ее возврату NULL
,
ОБНОВИТЬ:
Проголосуйте за следующее предложение Microsoft Connect, так что, надеюсь, будет добавлена поддержка OnNullCall
собственность SqlFunction
атрибут:
Реализуйте свойство OnNullCall в SqlFunctionAttribute для ВОЗВРАЩАЕТСЯ NULL ON NULL INPUT
@ Джош, для чего это стоит, я называю свои функции CLR, оборачивая все параметры функцией объединения. Итак, что-то вроде select myFunc(coalesce(fld1,''))
, Затем в своей функции CLR я проверяю значения параметров в самом верху, что-то вроде if (param1.ToString() == '') return SqlString.Null
, Конечно, вы можете делать все, что вам нужно, внутри функции, но это общий шаблон, который я использовал, чтобы обойти нулевую проблему с CLR procs/functions. Стоит помнить, чтобы оборачивать их каждый раз, когда я их использую, но это работает.
Редактировать: это было написано до теперь принятого ответа выше. Посмотри вместо этого.
Я все еще убежден, что есть способ сделать это, но я не нашел его (я не знаю достаточно о том, как SQL взаимодействует с CLR в любом случае).
Чтобы обойти это, я сделал довольно очевидную вещь: проверил наличие нулей.
Select dbo.cleanEstActText(EstActText1)
From BLEstActivity
Where EstActText1 is not NULL