26

Ich habe die folgende benutzerdefinierte Funktion:SQL Server-deterministische benutzerdefinierte Funktion

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 

Ich kann keinen Index für eine berechnete Spalte erstellen mit dieser Funktion Ursache es nicht deterministisch ist. Jemand könnte erklären, warum ist es nicht deterministisch und schließlich, wie man es ändert, um es deterministisch zu machen? Danke

Antwort

40

Sie müssen nur with schemabinding erstellen.

SQL Server wird dann überprüfen, ob es die Kriterien erfüllt, die als deterministisch angesehen werden (was es tut, da es nicht auf externe Tabellen zugreift oder nicht deterministische Funktionen wie getdate() verwendet).

können Sie überprüfen, ob es

Hinzufügen der SCHEMAB Option zu Ihrem ursprünglichen Code funktioniert gut, aber eine etwas einfachere Version wäre mit

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

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

Ich habe meine Index auf die berechnete Spalte zeigt erklären. Ich habe auch eine View, die sich auf meinen Tisch bezieht. Ich denke, ich muss auch SchemaBinding auf der Ansicht angeben, um einen Index für dieselbe Spalte zu erstellen. Wenn meine Basistabelle als Index für die berechnete Spalte redundant ist, erstellen Sie einen anderen Index in der Ansicht? – opaera

+0

@opaera - Ja - Sie müssten diese Spalte auch nicht in der Ansicht indizieren. –

+0

Eine letzte Frage, wenn Sie können. Ich habe eine SP, die eine Abfrage auf die Ansicht (die View, die auf meine indizierte Tabelle verweist) macht. Ich kann/sollte den Indexnamen in der Abfrage von Klausel angeben? z.B. Wählen Sie * aus MyView (mit MyTableIndex) ... Vielleicht habe ich einige Vorteile dabei? – opaera

4

Sie müssen die benutzerdefinierte Funktion mit SCHEMA

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