26

je la fonction définie par l'utilisateur suivant:Sql Server déterministe fonction définie par l'utilisateur

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 

Je ne peux pas créer un index sur une colonne calculée en utilisant cette fonction parce que ce n'est pas déterministe. Quelqu'un pourrait expliquer pourquoi n'est-il pas déterministe et éventuellement comment le modifier pour le rendre déterministe? Merci

Répondre

40

Vous avez juste besoin de le créer with schemabinding. SQL Server vérifie ensuite s'il répond ou non aux critères pour être considéré comme déterministe (ce qu'il fait car il n'accède à aucune table externe ou n'utilise des fonctions non déterministes telles que getdate()).

Vous pouvez vérifier que cela a fonctionné avec

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

Ajout de l'option SCHEMABINDING à votre code d'origine fonctionne très bien, mais une version légèrement plus simple serait.

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

J'ai créé mon index pointant vers la colonne calculée. J'ai aussi une vue qui se réfère à ma table. Je pense que je dois aussi spécifier SchemaBinding sur la vue pour créer un index sur la même colonne. A ce propos, si ma table de base en tant qu'index sur la colonne calculée est redondante, créez un autre index sur la vue? – opaera

+0

@opaera - Oui - Vous n'avez pas non plus besoin d'indexer cette colonne dans la vue. –

+0

Une dernière question, si vous le pouvez. J'ai un sp qui fait une requête sur la vue (la vue référençant ma table indexée). Je peux/dois spécifier le nom de l'index dans la requête de la clause? par exemple. Sélectionnez * De MyView (avec MyTableIndex) ... Peut-être que j'ai quelques avantages à faire cela? – opaera

4

Vous devez déclarer la fonction utilisateur avec 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 
Questions connexes