26

tengo la siguiente función definida por el usuario:servidor SQL función determinista definida por el usuario

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 

No puedo crear un índice en una columna calculada usando esta función porque no es determinista. Alguien podría explicar por qué no es determinista y, finalmente, cómo modificar para que sea determinista? Gracias

Respuesta

40

Solo tiene que crearlo with schemabinding.

SQL Server verificará si cumple o no los criterios para ser considerado como determinista (que lo hace ya que no accede a ninguna tabla externa ni utiliza funciones no determinísticas como getdate()).

Usted puede verificar que se trabajó con

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

Añadiendo la opción SCHEMABINDING a su código original funciona bien, pero una versión ligeramente más simple sería.

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

creé mi índice que apunta a la columna calculada. También tengo una Vista que se refiere a mi mesa. Creo que también debo especificar SchemaBinding en la Vista para crear un índice en la misma columna. Acerca de esto, si mi tabla base como un índice en la columna calculada, es redundante, ¿crear otro índice en la vista? – opaera

+0

@opaera - Sí - No necesitaría también indexar esa columna en la vista. –

+0

Una última pregunta, si puedes. Tengo un sp que hace una consulta en la Vista (la Vista que hace referencia a mi tabla indexada). Puedo/debo especificar el nombre del índice en la cláusula query from? p.ej. Seleccione * de MyView (con MyTableIndex) ... ¿Tal vez tenga algunos beneficios haciendo eso? – opaera

4

tiene que declarar la función definida por el usuario 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 
Cuestiones relacionadas