Как выполнить скалярную функцию sql
Скалярные определяемые пользователем функции для выполняющейся в памяти OLTP
В SQL Server 2016 (13.x);можно создавать и удалять скомпилированные в собственном коде определяемые пользователем скалярные функции. Их также можно изменять. Компиляция в собственном коде повышает производительность вычисления определяемых пользователем функций в Transact-SQL.
Если изменить скомпилированную в собственном коде скалярную определяемую пользователем функцию, приложение остается доступным при выполнении операции и компилируется новая версия функции.
Создание, удаление и изменение определяемых пользователем функций
Для создания, удаления и изменения определяемых пользователем скомпилированных в собственном коде скалярных функций используются инструкции CREATE FUNCTION, DROP FUNCTION и ALTER FUNCTION соответственно. Инструкция BEGIN ATOMIC WITH требуется для определяемых пользователем функций.
Сведения о поддерживаемом синтаксисе и ограничениях см. в следующих статьях.
Синтаксис инструкции DROP FUNCTION для скомпилированных в собственном коде скалярных определяемых пользователем функций аналогичен синтаксису для интерпретируемых определяемых пользователем функций.
Хранимую процедуру sp_recompile (Transact-SQL) можно использовать со скомпилированными в собственном коде определяемыми пользователем скалярными функциями. При этом произойдет повторная компиляция функции с использованием определения в метаданных.
Вызов пользовательских функций
Скомпилированные в собственном коде скалярные определяемые пользователем функции можно использовать в выражениях там же, где и встроенные скалярные функции, и интерпретируемые скалярные определяемые пользователем функции. Скомпилированные в собственном коде скалярные определяемые пользователем функции можно также использовать с инструкцией EXECUTE, в инструкции Transact-SQL и в скомпилированной в собственном коде хранимой процедуре.
Эти скалярные определяемые пользователем функции можно использовать в скомпилированных в собственном коде хранимых процедурах и скомпилированных в собственном коде определяемых пользователем функциях, а также везде, где можно использовать встроенные функции. Кроме того, скомпилированные в собственном коде скалярные определяемые пользователем функции можно использовать в традиционных модулях Transact-SQL.
Эти функции можно использовать в режиме взаимодействия при условии поддержки интерпретируемых скалярных определяемых пользователем функций. В этом случае есть ограничения для транзакций между контейнерами, как описано в разделе Поддерживаемые уровни изоляции для транзакций между контейнерами статьи Операции с таблицами, оптимизированными для памяти. Дополнительные сведения о режиме взаимодействия см. в статье Доступ к таблицам, оптимизированным для памяти, с помощью интерпретируемых инструкций Transact-SQL.
Скомпилированным в собственном коде скалярным определяемым пользователем функциям требуется явно выраженный контекст выполнения. Дополнительные сведения см. в разделе Предложение EXECUTE AS (Transact-SQL). Инструкция EXECUTE AS CALLER не поддерживается. Дополнительные сведения см. в разделе EXECUTE (Transact-SQL).
Сведения о поддерживаемом синтаксисе инструкций EXECUTE Transact-SQL для скомпилированных в собственном коде определяемых пользователем скалярных функций см. в статье EXECUTE (Transact-SQL). Сведения о поддерживаемом синтаксисе для выполнения определяемых пользователем функций в скомпилированной в собственном коде хранимой процедуре см. в статье Поддерживаемые функции для модулей, скомпилированных в собственном коде T-SQL.
Указания и параметры
Поддержка указаний таблиц, соединений и запросов в скомпилированных в собственном коде скалярных определяемых пользователем функциях осуществляется так же, как и в скомпилированных хранимых процедурах. Как и в случае с интерпретируемыми скалярными определяемыми пользователем функциями, указания запросов в Transact-SQL, которые ссылаются на скомпилированные в собственном коде скалярные определяемые пользователем функции, не влияют на план запроса для этой определяемой пользователем функции.
Скомпилированные в собственном коде скалярные определяемые пользователем функции поддерживают те же параметры, что и скомпилированные в собственном коде хранимые процедуры, при условии, что эти параметры можно использовать в скалярных определяемых пользователем функциях. Пример поддерживаемого параметра — параметр с табличным значением.
Привязка к схеме
Следующие сведения касаются скомпилированных в собственном коде скалярных определяемых пользователем функций.
Функции нужно привязать к схеме, использовав аргумент WITH SCHEMABINDING в инструкции CREATE FUNCTION и ALTER FUNCTION.
Функцию нельзя удалить или изменить, если на нее ссылается хранимая процедура с привязкой к схеме или определяемая пользователем функция.
SHOWPLAN_XML
Скомпилированные в собственном коде скалярные определяемые пользователем функции не поддерживают STATISTICS XML. При выполнении запроса со ссылкой на определяемую пользователем функцию с заданной инструкцией STATISTICS XML содержимое XML возвращается без части, отвечающей за определяемую пользователем функцию.
Разрешения
Как и в случае со скомпилированными в собственном коде хранимыми процедурами, разрешения для объектов, указанных в скомпилированной в собственном коде скалярной определяемой пользователем функции, проверяются при создании функции. CREATE FUNCTION завершается сбоем, если у воплощаемого пользователя нет необходимых разрешений. Если во время изменения разрешений воплощаемый пользователь теряет соответствующие разрешения, последующее выполнение определяемой пользователем функции также завершается сбоем.
При использовании скомпилированной в собственном коде скалярной определяемой пользователем функции в скомпилированной в собственном коде хранимой процедуре разрешения на выполнение определяемой пользователем функции проверяются при создании внешней процедуры. Если у пользователя, олицетворенного внешней процедурой, нет разрешений EXEC для определяемой пользователем функции, происходит сбой создания хранимой процедуры. Если во время изменения разрешений пользователь теряет разрешения EXEC, происходит сбой выполнения внешней процедуры.
Вызовы скалярных функций
Скалярные функции возвращают значение для каждой строки. Например, скалярная функция абсолютного значения принимает числовой столбец в качестве аргумента и возвращает абсолютное значение каждого значения в столбце. Escape-последовательность для вызова скалярной функции:
где Скалярная функция — одна из функций, перечисленных в приложении E: скалярные функции. дополнительные сведения о escape-последовательности скалярной функции см. в разделе escape-последовательность скалярной функции в приложении C: SQL грамматики.
например, следующие инструкции SQL создают тот же результирующий набор имен клиентов в верхнем регистре. В первой инструкции используется синтаксис escape-последовательности. Во втором операторе используется собственный синтаксис для входных данных OS/2, который не поддерживает взаимодействие.
Приложение может смешивать вызовы скалярных функций, использующих собственный синтаксис и вызовы скалярных функций, использующих синтаксис ODBC. Например, предположим, что имена в таблице Employee хранятся в виде фамилии, запятой и имени. следующая инструкция SQL создает результирующий набор фамилий сотрудников в таблице Employee. инструкция использует подстроку скалярной функции ODBC и SQL Server скалярную функцию CHARINDEX и будет правильно выполняться только в SQL Server.
Convert ( value_exp , data_type)
Как выполнить скалярную функцию sql
С SQL Server вы можете создавать ваши собственные функции, добавляющие и расширяющие функции, предоставляемые системой. Функции могут получать 0 или более параметров и возвращать скалярное значение или таблицу. Входные параметры могут быть любого типа, исключая timestamp, cursor, table.
Сервер SQL поддерживает три типа функций определенных пользователем:
1. Создание хранимой функции
Создание функций очень похоже на создание процедур и объектов просмотра. эедаром мы рассматриваем все эти темы в одной главе. Для создания функции используется оператор CREATE FUNCTION. В зависимости от типа, Объявление будет отличаться. э ассмотрим все три типа объявления.
Функция, возвращающая таблицу:
2. Скалярные функции в Transact-SQL
Давайте для примера создадим функцию, которая будет возвращать скалярное значение. эапример, результат перемножение цены на количество указанного товара. Товар будет идентифицироваться по названию и дате, ведь мы договорились, что сочетание этих полей дает уникальность. эо будьте осторожны, при тестировании запроса, если в разделе 3.2.8 вы выполнили запрос на изменение данных и создали дубликаты покупок за 1.1.2005-го года.
Итак, посмотрим сначала на код создание скалярной функции:
После оператора CREATE FUNCTION мы указываем имя функции. Далее, в скобках идут параметры, которые необходимо передать. Да, параметры должны передаваться через запятую в круглых скобках. В этом объявление отличается от процедур и эту разницу необходимо помнить.
Далее указывается ключевое слово RETURNS, за которым идет описание типа возвращаемого значения. Для скалярной функции это могут быть любые типы (строки, числа, даты и т.д.).
Код, который должна выполнять функция пишется между ключевыми словами BEGIN (начало) и END (конец). В коде можно использовать любые операторы Transact-SQL, которые мы изучали ранее. Итак, объявление нашей функции в упрощенном виде можно описать следующим образом:
Между ключевыми словами BEGIN и END у нас выполняется следующий код:
В первой строке объявляется переменная @Summ. Она нужна для хранения промежуточного результата расчетов. Далее выполняется запрос SELECT, в котором происходит поиск строки по дате и названию товара в таблице товаров. В найденной строке перемножаются поля цены и количества, и результат записывается в переменную @Summ.
Обратите внимание, что в конце запроса стоит знак точки с запятой. Каждый запрос должен заканчиваться этим символом, но в большинстве примеров мы этим пренебрегали, но в функции отсутствие символа «;» может привести к ошибке.
В последней строке возвращаем результат. Для этого нужно написать ключевое слово RETURN, после которого пишется возвращаемое значение или переменная. В данном случае, возвращаться будет содержимое переменной @Summ.
Так как функция скалярная, то и возвращаемое значение должно быть скалярным и при этом соответствовать типу, описанному после ключевого слова RETURNS.
3. Использование функций
Как выполнить такую функцию? Да также, как и многие другие системные функции (например, GETDATE()). эапример, следующий пример использует функцию в операторе SELECT:
В этом примере, оператор SELECT возвращает результат выполнения функции GetSumm. Функция принадлежит пользователю dbo, поэтому перед именем я указал владельца. После имени в скобках должны быть перечислены параметры в том же порядке, что и при объявлении функции. В данном примере я запрашиваю затраты на картофель, купленный 3.3.2005.
Выполните следующий запрос и убедитесь, что он вернул тот же результат, что и созданная нами функция:
Функции можно использовать не только в операторе SELECT, но и напрямую, присваивая значение переменной. эапример:
В этом примере мы объявили переменную @Summ типа numeric(10,2). Именно такой тип возвращает функция. В следующей строке переменной присваивается результат выполнения Summ, с помощью SET.
Давайте посмотрим, что произойдет, если передать функции такие параметры, при которых запрос функции вернет более одной строки. В нашей таблице товаров сочетание даты и название не дает уникальности, потому что мы ее нарушили. Первичного ключа в таблице также нет, и среди товаров у меня есть четыре строки, которые имеют свои точные копии. это нарушает правило уникальности строк в реляционных базах, но очень наглядно показывает, что в реальной жизни нарушать его нельзя.
Итак, в моей таблице есть две покупки хлеба 1.1.2005-го числа. Попробую запросить у функцию сумму:
э езультатом будет только одно число, хотя строки две. э какую строку из двух вернул сервер? эикто точно сказать не может, потому что они обе одинаковые и без единого различия. Поэтому сервер скорей всего вернул первую из строк.
4. Функция, возвращающая таблицу
В следующем примере мы создаем функцию, которая будет возвращать в качестве результата таблицу. В качестве примера, создадим функцию, которая будет возвращать таблицу товаров, и для каждой строки рассчитаем произведение колонок количества и цены:
эачало функции такое же, как у скалярной – указываем оператор CREATE FUNCTION и имя функции. Я специально создал эту функцию без параметров, чтобы вы увидели, как это делается. эе смотря на то, что параметров нет, после имени должны идти круглые скобки, в которых не надо ничего писать. Если не указать скобок, то сервер вернет ошибку и функция не будет создана.
э азница есть и в секции RETURNS, после которой указывается тип TABLE, что говорит о необходимости вернуть таблицу. После этого идет ключевое слово AS и RETURN, после которого должно идти возвращаемое значение. Для функции данного типа в секции RETURN нужно в скобках указать запрос, результат которого и будет возвращаться функцией.
Когда пишете запрос, то все его поля должны содержать имена. Если одно из полей не имеет имени, то результатом выполнения оператора CREATE FUNCTION будет ошибка. В нашем примере последнее поле является результатом перемножения полей «Цена» и «Количество», а такие поля не имеют имени, поэтому мы его задаем с помощью ключевого слова AS.
Посмотрим, как можно использовать такую функцию с помощью оператора SELECT:
Так как мы используем простой оператор SELECT, то мы можем и ограничивать вывод определенными строками, с помощью ограничений в секции WHERE. эапример, в следующем примере выбираем из результата функции только те строки, в которых поле «Количество» содержит значение 1:
Функция возвращает в качестве результата таблице, которую вы можете использовать как любую другую таблицу базы данных. Давайте создадим пример в котором можно будет увидеть использование функции в связи с таблицами. Для начала создадим функцию, которая будет возвращать идентификатор работников таблицы tbPeoples и объединенные в одно поле ФИО:
Функция возвращает нам идентификатор строки, с помощью которого мы легко можем связать результат с таблицей телефонов. Попробуем сделать это с помощью простого SQL запроса:
Как видите, функции, возвращающие таблицы очень удобны. Они больше, чем процедуры похожи на объекты просмотра, но при этом позволяют принимать параметры. Таким образом, можно сделать так, чтобы сама функция возвращала нам только то, что нужно. Вьюшки такого не могут делать по определению. Чтобы получить нужные данные, вьюшка должна выполнить свой SELECT запрос, а потом уже во внешнем запросе мы пишем еще один оператор SELECT, с помощью которого ограничивается вывод до необходимого. Таким образом, выполняется два запроса SELECT, что для большой таблицы достаточно накладно. Функция же может сразу вернуть только то, что нужно.
э ассмотрим пример, функция GetPeoples у нас возвращает все строки таблицы. Чтобы получить только нужную фамилию, нужно писать запрос типа:
В этом случае будут выполняться два запроса: этот и еще один внутри функции. эо если передавать фамилию в качестве параметра в функцию и там сделать секцию WHERE, то можно обойтись и одним запросом SELECT:
5. Многооператорная функция возвращающая таблицу
Все функции, созданные в разделе 3.3.5 могут возвращать таблицу, сгенерированную только одним оператором SQL. э как же тогда сделать возможность выполнять несколько операций? эапример, вы можете захотеть выполнять дополнительные проверки входных параметров для обеспечения безопасности. Проверки лишними не бывает, особенно входных данных и особенно, если эти входные данные указываются пользователем.
Следующий пример показывает, как создать функцию, которая может вернуть в качестве результата таблицу, и при этом, в теле функции могут выполняться несколько операторов:
это упрощенный вид создания процедуры. Более полный вид мы рассматривали в начале главы, а сейчас я упростил объявление, чтобы проще было его разбирать.
Объявление больше похоже на создание скалярных функций. Первая строка без изменений. В секции RETURNS объявляется переменная, которая имеет тип TABLE. После этого, в скобках нужно описать поля результирующей таблицы. После ключевого слова AS идtт пара операторов BEGIN и END, между которыми может выполняться какое угодно количество операций. Выполнение операций заканчивается ключевым словом RETURN.
Вот тут есть одно отличие от скалярных функций – после RETURN мы указывали имя переменной, значение которой должно стать результатом. В данном случае ничего указывать не надо. Мы уже объявили переменную в секции RETURNS и описали формат этой переменной. В теле функции мы можем и должны наполнить эту переменную значениями и именно это попадет в результат.
Теперь посмотрим на пример создания функции:
В данном примере в качестве результата объявлена переменная @ret, которая является таблицей из двух полей «idPeoples» типа int и «vcFIO» типа varchar длинной в 50 символов. В теле функции в эту таблицу записываются значения из таблицы tbPeoples и выполняется оператор RETURN, завершающий выполнение функции.
В использовании, такая функция ничем не отличается от рассмотренных ранее. эапример, следующий запрос выбирает все данные, которые возвращает функция:
6. Опции функций
При создании функций могут использоваться следующие опции SCHEMABINDING (привязать к схеме) и/или ENCRYPTION (шифровать текст функции). Если вторая опция нам уже известна по вьюшкам и процедурам (позволяет шифровать исходный код функции в системных таблицах), то вторая встречается впервые, но при этом предоставляет удобное средство защиты данных.
Если функция создана с опцией SCHEMABINDING, то объекты базы данных, на которые ссылается функция, не могут быть изменены (с использованием оператора ALTER) или удалены (с помощью оператора DROP). эапример, следующая функция использует таблицу tbPeoples и при этом используется опция SCHEMABINDING:
Функция может быть связанной со схемой, только если следующие ограничения истины:
Создайте функцию и попробуйте после этого удалить таблицу tbPeoples.
В ответ на это сервер выдаст сообщение с ошибкой о том, что объект не может быть удален, из-за присутствия внешнего ключа. Даже если избавиться от ключа, удаление будет невозможно, потому что на таблицу ссылается функция, привязанная к схеме.
Чтобы увидеть сообщение без удаления ключа, давайте добавим к таблице колонку, а потом попробуем ее удалить:
Создание пройдет успешно, а вот во время удаления произойдет ошибка, с сообщением о том, что существует ограничение, которое зависит от колонки. Мы же не создавали никаких ограничений, а просто добавили колонку и попытались ее удалить. Ограничение уже давно существует, но не на отдельную колонку, а на все колонки таблицы и это ограничение создано функцией GetPeoples2, которая связана со схемой.
7. Изменение функций
Вы можете изменять функцию с помощью оператора ALTER FUNCTION. Общий вид для каждого варианта функции отличается. Давайте рассмотрим каждый из них.
1. Общий вид команды изменения скалярной функции:
2. Общий вид изменения функции, возвращающей таблицу:
3. Общий вид команды изменения функции с множеством операторов, возвращающей таблицу.
Следующий пример показывает упрощенный вариант команды, изменяющей функцию:
8. Удаление функций
Если вы внимательно читали об объектах просмотра и функциях, то не трудно догадаться, как можно удалить функцию. Конечно же для этого используется оператор DROP FUNCTION:
Встраивание скалярных пользовательских функций
В этой статье приводятся общие сведения о функции встраивания скалярных пользовательских функций, которая входит в состав набора функций интеллектуальной обработки запросов. Эта функция повышает производительность запросов, вызывающих скалярные пользовательские функции, в SQL Server (начиная с SQL Server 2019 (15.x)).
Скалярные пользовательские функции T-SQL
Пользовательские функции, которые реализованы на языке Transact-SQL и возвращают одно значение, называются скалярными пользовательскими функциями T-SQL. Это элегантное решение для обеспечения повторного использования и модульности кода запросов Transact-SQL. Некоторые вычисления (например, сложные бизнес-правила) проще выражать в императивной форме пользовательских функций. Такие функции позволяют конструировать комплексную логику, не имея опыта в написании сложных SQL-запросов. Дополнительные сведения о пользовательских функциях см. в разделе Создание определяемых пользователем функций (ядро СУБД).
Производительность скалярных пользовательских функций
Как правило, производительность скалярных пользовательских функций оказывается невысокой по указанным ниже причинам:
Итеративные вызовы. Пользовательские функции вызываются итеративно — однократно в соответствующем кортеже. Постоянные переключения контекста при вызове функций требуют дополнительных ресурсов. Особенно это проявляется в случаях, когда запросы Transact-SQL выполняются в определении пользовательской функции.
Отсутствие оценки затрат. Во время оптимизации оцениваются только реляционные операторы, но не скалярные. До появления скалярных пользовательских функций скалярные операторы, как правило, были нетребовательны к ресурсам и не нуждались в оценке. Достаточно было учитывать небольшое увеличение загрузки ЦП. Ниже представлены сценарии, в которых фактические затраты значительны, но по-прежнему не принимаются во внимание в полной мере.
Выполнение, ориентированное на интерпретацию. Пользовательские функции оцениваются как пакеты инструкций, но инструкции выполняются поочередно. Каждая инструкция компилируется отдельно, а затем скомпилированный план кэшируется. Хотя такая стратегия кэширования позволяет избежать повторной компиляции и немного сэкономить время, каждая инструкция выполняется изолированно. Перекрестная оптимизация инструкций не производится.
Последовательное выполнение. В SQL Server не допускается параллелизм внутри запросов, вызывающих пользовательские функции.
Автоматическое встраивание скалярных пользовательских функций
Цель встраивания скалярных пользовательских функций заключается в повышении производительности запросов, которые вызывают скалярные пользовательские функции T-SQL, являющиеся основным узким местом.
Эта новая функция автоматически преобразует скалярные пользовательские функции в скалярные выражения или скалярные вложенные запросы, которые подставляются в вызывающий запрос вместо оператора пользовательской функции. Затем выражения и вложенные запросы оптимизируются. В итоге в плане запроса не будет оператора пользовательской функции, но логика функции сохраняется в виде представлений или встроенных функций с табличными значениями.
Пример 1. Скалярная пользовательская функция с одной инструкцией
Обратите внимание на следующий запрос.
Теперь запрос можно изменить так, чтобы в нем вызывалась эта пользовательская функция.
По изложенным выше причинам запрос с пользовательской функцией выполняется медленно. Однако благодаря встраиванию скалярных пользовательских функций скалярное выражение из тела пользовательской функции подставляется непосредственно в запрос. Результаты выполнения этого запроса показаны в приведенной ниже таблице.
Запрос: | Запрос без пользовательской функции | Запрос с пользовательской функцией (без встраивания) | Запрос со встраиванием скалярной пользовательской функции |
---|---|---|---|
Время выполнения: | 1,6 секунды | 29 минут 11 секунд | 1,6 секунды |
Эти показатели получены для базы данных CCI размером 10 ГБ (использующей схему TPC-H), которая размещена на компьютере с двумя процессорами (12 ядер), 96 ГБ ОЗУ и дисками SSD. В них было учтено время компиляции и выполнения с холодным кэшем процедур и буферным пулом. Использовалась конфигурация по умолчанию. Другие индексы не создавались.
Пример 2. Скалярная пользовательская функция с несколькими инструкциями
Теперь рассмотрим запрос, вызывающий эту пользовательскую функцию.
План выполнения для этого запроса в SQL Server 2017 (14.x); (уровень совместимости 140 и ниже) выглядит так:
Как видно из плана, в SQL Server применяется простая стратегия: для каждого кортежа в таблице CUSTOMER вызывается пользовательская функция и выводятся результаты. Такой подход примитивен и неэффективен. Благодаря встраиванию подобные пользовательские функции преобразуются в эквивалентные скалярные вложенные запросы, которые подставляются в вызывающий запрос вместо пользовательской функции.
Для этого же запроса план со встроенной пользовательской функцией выглядит так:
Как уже говорилось, в плане запроса теперь нет оператора пользовательской функции, но логика функции сохраняется в виде представлений или встроенных функций с табличными значениями. Изучив план, можно заметить следующее.
В зависимости от сложности логики в пользовательской функции план запроса также может быть больше и сложнее. Как видите, операции внутри пользовательской функции теперь прозрачны, поэтому оптимизатор запросов может оценить затраты и оптимизировать эти операции. Кроме того, так как в плане больше нет пользовательской функции, полностью устраняются накладные расходы, связанные с ее итеративными вызовами.
Требования к встраиваемым скалярным пользовательским функциям
Скалярную пользовательскую функцию T-SQL можно встраивать, если выполняются все перечисленные ниже условия:
1 Встраивание инструкций SELECT с накоплением или агрегированием переменных (например, SELECT @val += col1 FROM table1 ) не поддерживается.
2 Рекурсивные пользовательские функции встраиваются только до определенной глубины.
3 Зависимыми от времени являются такие встроенные функции, результаты которых зависят от текущего системного времени. Примером встроенной функции с побочными эффектами служит функция, которая может изменять некоторое внутреннее глобальное состояние. Такие функции возвращают разные результаты в зависимости от внутреннего состояния.
4 Ограничение добавлено в накопительный пакет обновления 2 для SQL Server 2019 (15.x)
5 Ограничение добавлено в накопительный пакет обновления 4 для SQL Server 2019 (15.x)
6 Ограничение добавлено в накопительный пакет обновления 5 для SQL Server 2019 (15.x)
7 Ограничение добавлено в накопительном пакете обновления 6 для SQL Server 2019 (15.x)
8 Ограничение добавлено в накопительном пакете обновления 11 для SQL Server 2019 (15.x)
Сведения о последних исправлениях и изменениях встраивания скалярных пользовательских функций T-SQL см. в статье базы знаний Устранение проблем встраивания скалярных пользовательских функций в SQL Server 2019.
Проверка возможности встраивания пользовательской функции
Свойство is_inlineable является производным от конструкций в определении пользовательской функции. При этом оно не проверяет, является ли пользовательская функция фактически встраиваемой во время компиляции. Дополнительные сведения см. в разделе Условия встраивания.
Значение 1 указывает, что она встраиваемая, а значение 0 — не встраиваемая. Это свойство также имеет значение 1 для всех встроенных функций с табличными значениями. Для остальных модулей значение будет равно 0.
Если скалярная пользовательская функция является встраиваемой, это не означает, что она обязательно будет встроенной. Целесообразность встраивания определяется в SQL Server для каждого конкретного запроса и каждой пользовательской функции. Ниже приведены примеры ситуаций, в которых невозможно встраивание пользовательских функций:
Если определение пользовательской функции состоит из тысяч строк кода, возможно, SQL Server не будет встраивать ее.
Пользовательская функция подписана с помощью сертификата. Поскольку подписи могут добавляться и удаляться после создания пользовательской функции, решение о возможности встраивания принимается при компиляции запроса, ссылающегося на скалярную пользовательскую функцию. Например, большинство системных функций подписано с помощью сертификатов. Для определения подписанных объектов можно использовать sys.crypt_properties.
Проверка применения встраивания
Если все предварительные условия соблюдены и сервер SQL Server решает выполнить встраивание, пользовательская функция преобразуется в реляционное выражение. По плану запроса можно легко выяснить, произошло ли встраивание.
Включение встраивания скалярных пользовательских функций
Рабочие нагрузки можно автоматически сделать подходящими для встраивания скалярных пользовательских функций, включив для базы данных уровень совместимости 150. Для этого можно использовать Transact-SQL. Пример:
Для использования этой функции других изменений в пользовательские функции или запросы вносить не требуется.
Отключение встраивания скалярных пользовательских функций без изменения уровня совместимости
Встраивание скалярных пользовательских функций можно отключить в области базы данных, инструкции или пользовательской функции, сохранив уровень совместимости базы данных 150 или более высокий. Чтобы отключить встраивание в области базы данных, выполните следующую инструкцию в контексте соответствующей базы данных.
Чтобы снова включить встраивание для базы данных, выполните следующую инструкцию в контексте соответствующей базы данных:
Указание запроса USE HINT имеет приоритет над конфигурацией, областью действия которой является база данных, или уровнем совместимости.
После выполнения этой инструкции данная пользовательская функция никогда не будет встраиваться в вызывающие ее запросы. Чтобы повторно включить встраивание для пользовательской функции, выполните следующую инструкцию.
Важные примечания
Как уже говорилось в этой статье, при встраивании скалярных пользовательских функций запрос с такими функциями преобразуется в запрос с эквивалентными скалярными вложенными запросами. Из-за этого пользователи могут заметить отличия в поведении в описанных ниже ситуациях.