创建原生编译的存储过程

本机编译的存储过程不具备完整的 Transact-SQL 可编程性和查询范围。 某些 Transact-SQL 构造不能在原生编译的存储过程中使用。 有关详细信息,请参阅 本机编译存储过程支持的结构

但是,有几个 Transact-SQL 功能仅支持本机编译的存储过程:

  • 原子块。 有关详细信息,请参阅 原子块

  • NOT NULL 对本机编译存储过程中的参数和变量的约束。 你不能将 NULL 值分配给声明为 NOT NULL 的参数或变量。 有关详细信息,请参阅 DECLARE @local_variable (Transact-SQL)

  • 本机编译存储过程的架构绑定。

本机编译的存储过程是使用 CREATE PROCEDURE (Transact-SQL) 创建的。 下面的示例演示内存优化表和本机编译的存储过程,用于将行插入表中。

create table dbo.Ord  
(OrdNo integer not null primary key nonclustered,   
 OrdDate datetime not null,   
 CustCode nvarchar(5) not null)   
 with (memory_optimized=on)  
go  
  
create procedure dbo.OrderInsert(@OrdNo integer, @CustCode nvarchar(5))  
with native_compilation, schemabinding, execute as owner  
as   
begin atomic with  
(transaction isolation level = snapshot,  
language = N'English')  
  
  declare @OrdDate datetime = getdate();  
  insert into dbo.Ord (OrdNo, CustCode, OrdDate) values (@OrdNo, @CustCode, @OrdDate);  
end  
go  

在代码示例中, NATIVE_COMPILATION 指示此 Transact-SQL 存储过程是本机编译的存储过程。 需要以下选项:

选项 DESCRIPTION
SCHEMABINDING 本机编译的存储过程必须绑定到它引用的对象架构。 这意味着无法删除该过程所使用的表引用。 过程中引用的表必须包括其架构名称,并且不允许在查询中使用通配符 \ 。 SCHEMABINDING 此版本的 SQL Server 中仅支持本机编译的存储过程。
EXECUTE AS 本机编译的存储过程不支持 EXECUTE AS CALLER,这是默认的执行上下文。 因此,需要指定执行上下文。 选项 EXECUTE AS OWNEREXECUTE AS用户EXECUTE AS SELF 都受到支持。
BEGIN ATOMIC 本机编译的存储过程体必须仅包含一个原子块。 原子块保证存储过程的原子执行。 如果在活动事务的上下文之外调用该过程,它将启动一个新事务,该事务将在原子块的末尾提交。 在本机编译的存储过程中,原子块有两个必要选项:

TRANSACTION ISOLATION LEVEL。 有关支持的事务隔离级别,请参阅事务隔离级别

LANGUAGE。 存储过程的语言必须设置为可用语言或语言别名之一。

对于 EXECUTE AS 和 Windows 登录,由于通过 EXECUTE AS的模拟,可能会发生错误。 如果用户帐户使用 Windows 身份验证,则必须完全信任用于 SQL Server 实例的服务帐户和 Windows 登录名的域。 如果没有完全信任,则创建本机编译存储过程时返回以下错误消息:Msg 15404,无法获取有关 Windows NT 组/用户“用户名”的信息,错误代码0x5。

若要解决此错误,请使用下列方法之一:

  • 请使用与 Windows 用户相同域中的账号用于 SQL Server 服务。

  • 如果 SQL Server 使用的是网络服务或本地系统等计算机帐户,则包含 Windows 用户的域必须信任该计算机。

  • 使用 SQL Server 身份验证。

创建本机编译的存储过程时,也可能看到错误 15517。 有关详细信息,请参阅 MSSQLSERVER_15517

更新本机编译的存储过程

不支持对本机编译的存储过程执行修改操作。 修改本机编译的存储过程的一种方法是删除并重新创建存储过程:

  1. 为存储过程的权限生成脚本。

  2. 可选,为存储过程生成脚本,并另存为备份。

  3. 删除存储过程。

  4. 创建更改的存储过程。

  5. 将脚本化权限重新应用于存储过程。

此过程的缺点是应用程序将从步骤 3 开始到步骤 5 的完成处于脱机状态。 这可能需要几秒钟时间,使用应用程序的客户端可能会看到错误消息。

修改本机编译的存储过程的另一种方法是首先创建存储过程的新版本。 此处,本机编译的存储过程具有关联的版本号。 我们将调用旧版本SP_Vold和新版本SP_Vnew。

  1. 为SP_Vold的权限生成脚本。

  2. 创建SP_Vnew。

  3. 将SP_Vold的权限应用于SP_Vnew。

  4. 更新对SP_Vold的引用以指向SP_Vnew。 这可以通过不同的方式完成,例如:

    使用包装存储过程(基于磁盘),并修改该过程以指向SP_Vnew。 此方法的缺点是由于间接性导致的性能影响。

    ALTER PROCEDURE dbo.SP p1,...,pn  
    AS  
      EXEC dbo.SP_Vnew p1,...,pn  
    GO  
    
  5. 可选,删除SP_Vold。

此方法的优点是应用程序不会脱机。 但是,维护引用需要执行更多工作,并确保它们始终指向最新版本的存储过程。

另请参阅

本机编译的存储过程