SQL Server - Обработка нулевого ввода в пользовательской функции CLR с помощью OnNullCall - PullRequest
7 голосов
/ 28 декабря 2010

У меня есть пользовательская функция в 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 ]

8 голосов
/ 09 апреля 2011

Вы можете попробовать это

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

    if (input.IsNull) return null;

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

    return cascadingSqlChar;
}

Все типы SqlData со значением Nullable имеют свойство IsNull.

Спасибо Хари

7 голосов
/ 25 февраля 2015

Принятый ответ не верен, хотя технически он работает.Проблема с проверкой 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

1 голос
/ 19 марта 2011

@ Джош, ради чего я стою, я называю свои функции CLR, оборачивая все параметры функцией объединения. Итак, что-то вроде select myFunc(coalesce(fld1,'')). Затем в своей функции CLR я проверяю значения параметров в самом верху, что-то вроде if (param1.ToString() == '') return SqlString.Null. Конечно, вы можете делать все, что вам нужно внутри функции, но это общий шаблон, который я использовал, чтобы обойти нулевую проблему с CLR procs / functions. Трудно помнить оборачивать их каждый раз, когда я их использую, но это работает.

0 голосов
/ 20 января 2011

Редактировать: Это было написано до принятого выше ответа выше.Посмотрите на это вместо этого.

Я все еще убежден, что есть способ сделать это, но я не нашел его (я все равно не знаю достаточно о том, как SQL взаимодействует с CLR).

Чтобы обойти это, я сделал довольно очевидную вещь: проверил наличие нулей.

Select dbo.cleanEstActText(EstActText1)
From BLEstActivity
Where EstActText1 is not NULL
...