次のユーザー定義関数があります。
create function [dbo].[FullNameLastFirst]
(
@IsPerson bit,
@LastName nvarchar(100),
@FirstName nvarchar(100)
)
returns nvarchar(201)
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
この関数を使用して計算列にインデックスを作成することはできません。これは決定論的ではないためです。なぜそれが決定論的ではないのか、そして最終的にはそれを決定論的にするためにどのように修正するのかを誰かが説明できますか?ありがとう
_with schemabinding
_を作成する必要があります。
次に、SQL Serverは、決定論的と見なされる基準を満たしているかどうかを検証します(外部テーブルにアクセスしたり、getdate()
などの非決定論的関数を使用したりしないためです)。
あなたはそれが動作したことを確認することができます
_SELECT OBJECTPROPERTY(OBJECT_ID('[dbo].[FullNameLastFirst]'), 'IsDeterministic')
_
元のコードにスキーマバインディングオプションを追加することは問題なく機能しますが、少し単純なバージョンの方がうまくいきます。
_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が実行プランを最適化するのにも役立ちます。特に、 Halloween Protection の問題です。
スキーマバインド関数を使用して計算列にインデックスを作成する例を次に示します。
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