26

Ho la seguente funzione definita dall'utente:Sql Server funzione definita dall'utente deterministico

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 

Non riesco a creare un indice su una colonna calcolata utilizza questa funzione causa non è deterministico. Qualcuno potrebbe spiegare perché non è deterministico e alla fine come modificarlo per renderlo deterministico? Grazie

risposta

40

Hai solo bisogno di crearlo with schemabinding.

SQL Server verificherà quindi se soddisfa o meno i criteri da considerare come deterministici (che esegue poiché non accede a nessuna tabella esterna o utilizza funzioni non deterministiche come getdate()).

È possibile verificare che ha funzionato con

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

Aggiunta l'opzione SCHEMABINDING al codice originale funziona bene, ma una versione leggermente più semplice sarebbe.

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

ho creato il mio indice che indica per la colonna calcolata. Ho anche una vista che si riferisce al mio tavolo. Penso di dover specificare SchemaBinding anche sulla vista per creare un indice sulla stessa colonna. A questo proposito, se la mia tabella di base come un indice sulla colonna calcolata, è ridondante creare un altro indice sulla vista? – opaera

+0

@opaera - Sì: non è necessario indicizzare la colonna nella vista. –

+0

Un'ultima domanda, se puoi. Ho uno sp che fa una query sulla vista (la vista che fa riferimento alla mia tabella indicizzata). Posso/dovrei specificare il nome dell'indice nella query dalla clausola? per esempio. Seleziona * Da MyView (con MyTableIndex) ... Forse ho dei vantaggi? – opaera

4

è necessario dichiarare la funzione definita dell'utente con 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 
Problemi correlati