Sql Server 确定性用户定义函数

发布于 2024-09-17 17:27:30 字数 479 浏览 10 评论 0原文

我有以下用户定义函数:

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

我无法使用此函数在计算列上创建索引,因为它不是确定性的。 有人可以解释为什么它不是确定性的,以及最终如何修改以使其具有确定性? 谢谢

I have the following user-defined function:

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

I can't create an Index on a computed column using this function cause it's not deterministic.
Someone could explain why is it not deterministic and eventually how to modify to make it deterministic?
Thanks

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

今天小雨转甜 2024-09-24 17:27:30

您只需使用模式绑定创建它。

然后,SQL Server 将验证它是否满足确定性的标准(它这样做是因为它不访问任何外部表或使用非确定性函数,例如 getdate())。

您可以验证它是否可以使用

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

“将架构绑定选项添加到原始代码”工作正常,但版本会稍微简单一些。

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

You just need to create it with schemabinding.

SQL Server will then verify whether or not it meets the criteria to be considered as deterministic (which it does as it doesn't access any external tables or use non deterministic functions such as getdate()).

You can verify that it worked with

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

Adding the schemabinding option to your original code works fine but a slightly simpler version would be.

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
带上头具痛哭 2024-09-24 17:27:30

您需要声明用户定义函数 WITH SCHEMABINDING 以满足计算列索引的“确定性”要求。

声明为 WITH SCHEMABINDING 的函数将保留有关函数中使用的对象依赖关系的附加信息(例如表中的列),并且将防止对这些列进行任何更改,除非函数本身事先被删除。

确定性函数还可以帮助 Sql Server 优化其执行计划,最值得注意的是 万圣节保护问题。

以下是使用架构绑定函数在计算列上创建索引的示例:

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

You need to declare the User Defined Function WITH SCHEMABINDING to appease the 'deterministic' requirement of an index on the computed column.

A function declared WITH SCHEMABINDING will retain additional knowledge about the object dependencies used in the function (e.g. columns in the table), and will prevent any changes to these columns, unless the function itself is dropped beforehand.

Deterministic functions can also assist Sql Server in optimizing its execution plans, most notably the Halloween Protection problem.

Here's an example of creating an index on a computed column using a schema bound function:

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
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文