CLR 集成概述

适用于: SQL Server Azure SQL 托管实例

公共语言运行时 (CLR) 是 Microsoft .NET Framework 的核心,它为所有 .NET Framework 代码提供执行环境。 在 CLR 中运行的代码称为 托管代码。 CLR 提供执行程序所需的各种函数和服务,包括实时 (JIT) 编译、分配和管理内存、强制类型安全、异常处理、线程管理和安全性。 有关详细信息,请参阅 .NET Framework 开发指南

注意

有关将新的 .NET 与 SQL Server 语言扩展配合使用的详细信息,请参阅 如何在 SQL Server 语言扩展中调用 .NET 运行时。

使用 SQL Server 中托管的 CLR(称为 CLR 集成),可以在托管代码中创作存储过程、触发器、用户定义函数、用户定义的类型和用户定义的聚合。 由于托管代码在执行前编译为本机代码,因此在某些情况下可以实现显著的性能提升。

代码访问安全性

在 SQL Server 2016(13.x)和早期版本中,代码访问安全性(CAS)阻止程序集执行某些操作。

CLR 在 .NET Framework 中使用代码访问安全性 (CAS)(不可再作为安全边界)。 使用 PERMISSION_SET = SAFE 创建的 CLR 程序集可以访问外部系统资源、调用非托管代码以及获取 sysadmin 特权。 在 SQL Server 2017 (14.x) 及更高版本中,sp_configure 选项 clr strict security 增强了 CLR 程序集的安全性。 默认启用 clr strict security,并将 SAFEEXTERNAL_ACCESS 程序集与标记为 UNSAFE 的程序集同等对待。 可禁用 clr strict security 选项以实现后向兼容性,但不建议这样做。

建议使用证书或非对称密钥对所有程序集进行签名,且该证书或非对称密钥具有已在 UNSAFE ASSEMBLY 数据库中获得 master 权限的相应登录名。 SQL Server 管理员还可以将程序集添加到数据库引擎应信任的程序集列表。 有关详细信息,请参阅 sys.sp_add_trusted_assembly

CLR 集成的优点

Transact-SQL 设计用于在数据库中直接访问和操作数据。 虽然 Transact-SQL 擅长数据访问和管理,但它不是一种全面的编程语言。 例如,Transact-SQL 不支持数组、集合、for-each 循环、位移位或类。 虽然其中一些构造可以在 Transact-SQL 中模拟,但托管代码已集成对这些构造的支持。 根据具体情况,这些功能足以为在托管代码中实现某些数据库功能提供充分理由。

Visual Basic 和 C# 提供面向对象的功能,例如封装、继承和多态性。 现在可以很容易将相关代码组织到类和命名空间中。 处理大量服务器代码时,这些功能使你能够更轻松地组织和维护代码。

托管代码比 Transact-SQL 更适合用于计算和复杂的执行逻辑,并且对许多复杂任务(包括字符串处理和正则表达式)的广泛支持。 借助 .NET Framework 库中的功能,可以访问成千上万的预生成类和例程。 可以从任何存储过程、触发器或用户定义的函数轻松访问这些类。 基类库(BCL)包括提供字符串操作、高级数学操作、文件访问、加密等功能的类。

注意

虽然其中许多类可用于 SQL Server 中的 CLR 代码,但不适合服务器端使用(例如窗口化类)的类不可用。 有关详细信息,请参阅 支持的 .NET Framework 库

托管代码的一个好处是类型安全,即确保代码仅以明确定义和许可的方式访问类型。 在执行托管代码之前,CLR 将验证该代码是否安全。 例如,检查代码以确保没有读取以前未写入的内存。 CLR 还可以帮助确保代码不会操作非托管内存。

CLR 集成为提高性能提供了可能。 有关信息,请参阅 CLR 集成体系结构的性能。

在 Transact-SQL 和托管代码之间进行选择

编写存储过程、触发器和用户定义的函数时,必须决定是否使用传统的 Transact-SQL 或 .NET Framework 语言(如 Visual Basic 或 C#)。 当代码主要执行数据访问时,使用 Transact-SQL,且过程逻辑很少或没有。 如果要编写有复杂逻辑并且 CPU 占用量大的函数和过程,或者想使用 .NET Framework 的 BCL,则使用托管代码。

在服务器中的执行与客户端中的执行之间进行选择

决定是使用 Transact-SQL 还是托管代码是希望代码驻留的位置、服务器计算机还是客户端计算机,还有另一个因素。 Transact-SQL 和托管代码都可以在服务器上运行。 这种方式可以将代码和数据靠近放在一起,并允许您利用服务器的强大处理能力。 另一方面,你可能希望避免在数据库服务器上放置处理器密集型任务。 当今大多数客户端计算机都是强大的,你可能希望通过尽可能多地将代码放在客户端上来利用这种处理能力。 托管代码可以在客户端计算机上运行,而 Transact-SQL 则无法运行。

在扩展存储过程和托管代码之间进行选择

可以生成扩展存储过程,以执行 Transact-SQL 存储过程无法实现的功能。 但是,扩展存储过程可能会损害 SQL Server 进程的完整性,而验证为类型安全的托管代码则无法。 此外,内存管理、线程和光纤计划以及同步服务在 CLR 和 SQL Server 的托管代码之间更深入地集成。 使用 CLR 集成,可以通过比扩展存储过程更安全的方式来编写在 Transact-SQL 中无法执行的任务所需的存储过程。 有关 CLR 集成和扩展存储过程的详细信息,请参阅 CLR 集成体系结构的性能。