Вам просто нужно создать его with schemabinding
.
Затем SQL Server проверяет, соответствует ли он критериям, которые будут считаться детерминированными (что он делает, поскольку он не имеет доступа к каким-либо внешним таблицам или использует не детерминированные функции, такие как getdate()
).
Вы можете проверить, что это сработало с
SELECT OBJECTPROPERTY(OBJECT_ID('[dbo].[FullNameLastFirst]'), 'IsDeterministic')
. Добавление опции schemabinding к исходному коду работает отлично, но будет немного более простая версия.
CREATE FUNCTION [dbo].[FullNameLastFirst] (@IsPerson BIT,
@LastName NVARCHAR(100),
@FirstName NVARCHAR(100))
RETURNS NVARCHAR(201)
WITH SCHEMABINDING
AS
BEGIN
RETURN CASE
WHEN @IsPerson = 0
OR @FirstName = '' THEN @LastName
ELSE @LastName + ' ' + @FirstName
END
END
Вам нужно объявить функцию, определенную пользователем WITH SCHEMABINDING
, чтобы успокоить «детерминированное» требование индекса в вычисленном столбце.
Функция, объявленная WITH SCHEMABINDING
, сохранит дополнительные знания об объектных зависимостях (например, столбцы в таблице) и предотвратит любые изменения этих столбцов, если только сама функция не будет удалена заранее.
Детерминированные функции также могут помочь Sql Server в оптимизации его планов выполнения, большинство особенно проблема защиты Хэллоуина .
Вот пример создания индекса в вычисленном столбце с использованием связанной с схемой функции:
create function [dbo].[FullNameLastFirst]
(
@IsPerson bit,
@LastName nvarchar(100),
@FirstName nvarchar(100)
)
returns nvarchar(201)
with schemabinding
as
begin
declare @Result nvarchar(201)
set @Result = (case when @IsPerson = 0 then @LastName
else case when @FirstName = '' then @LastName
else (@LastName + ' ' + @FirstName) end end)
return @Result
end
create table Person
(
isperson bit,
lastname nvarchar(100),
firstname nvarchar(100),
fullname as [dbo].[FullNameLastFirst] (isperson, lastname, firstname)
)
go
insert into person(isperson, lastname, firstname) values (1,'Firstname', 'Surname')
go
create index ix1_person on person(fullname)
go
select fullname from Person with (index=ix1_person) where fullname = 'Firstname Surname'
go
ARITHABORT
илиANSI_WARNINGS
. Вы можете проверить план выполнения, чтобы определить это. – Martin Smith 6 September 2010 в 15:19