26

Mam następujący zdefiniowanej przez użytkownika funkcji:SQL Server deterministyczny zdefiniowana przez użytkownika funkcja

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 

Nie mogę utworzyć indeks na kolumnie obliczone z wykorzystaniem tej funkcji, bo to nie jest deterministyczny. Ktoś może wyjaśnić, dlaczego nie jest on deterministyczny, a ostatecznie jak go zmodyfikować, aby stał się deterministyczny? Dzięki

Odpowiedz

40

Po prostu trzeba go utworzyć with schemabinding.

Serwer SQL następnie sprawdzi, czy spełnia kryteria, które należy uznać za deterministyczne (robi to, ponieważ nie ma dostępu do żadnych zewnętrznych tabel ani nie używa funkcji innych niż deterministyczne, takich jak getdate()).

Można sprawdzić, że pracował z

SELECT OBJECTPROPERTY(OBJECT_ID('[dbo].[FullNameLastFirst]'), 'IsDeterministic') 

Dodanie opcji schemabinding do oryginalnego kodu działa dobrze, ale nieco prostsza wersja będzie.

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 
+1

tworzę indeks wskazujący na kolumnie komputerowej. Mam również widok, który odnosi się do mojego stołu. Myślę, że muszę również określić SchemaBinding w widoku również, aby utworzyć indeks w tej samej kolumnie. O tym, jeśli moja tabela podstawowa jako indeks w kolumnie obliczeniowej jest zbędna, należy utworzyć inny indeks w widoku? – opaera

+0

@opaera - Tak - Nie trzeba również indeksować tej kolumny w widoku. –

+0

Ostatnie pytanie, jeśli możesz. Mam sp, który tworzy zapytanie w widoku (widok odwołujący się do mojej tabeli indeksowanej). Mogę/powinienem podać nazwę indeksu do klauzuli query from? na przykład Wybierz * From MyView (With MyTableIndex) ... Może mam jakieś korzyści z tego powodu? – opaera

4

Musisz zadeklarować User Defined Function z SchemaBinding

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