CREATE ASSEMBLY (Transact-SQL)

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

创建包含类元数据和托管代码的托管应用程序模块,将其作为 SQL Server 实例中的对象。 通过引用此模块,可在数据库中创建公共语言运行时 (CLR) 函数、存储过程、触发器、用户定义聚合以及用户定义类型。

Transact-SQL 语法约定

语法

CREATE ASSEMBLY assembly_name
[ AUTHORIZATION owner_name ]
FROM { <client_assembly_specifier> | <assembly_bits> [ , ...n ] }
[ WITH PERMISSION_SET = { SAFE | EXTERNAL_ACCESS | UNSAFE } ]
[ ; ]
<client_assembly_specifier> ::=
    '[ \\computer_name\ ] share_name\ [ path\ ] manifest_file_name'
    | '[ local_path\ ] manifest_file_name'

<assembly_bits> ::=
{ varbinary_literal | varbinary_expression }

参数

assembly_name

程序集的名称。 此名称必须在数据库中唯一,并且是有效的标识符

AUTHORIZATION owner_name

指定作为程序集所有者的用户或角色的名称。 owner_name必须是当前用户所属角色的名称,或者当前用户必须具有IMPERSONATE对owner_name的权限。 如果未指定,则所有权授予当前用户。

<client_assembly_specifier>

指定正在上载的程序集所在的本地路径或网络位置,以及与程序集对应的清单文件名。 <client_assembly_specifier> 可表示为固定字符串或其值等于固定字符串的、带有变量的表达式。 CREATE ASSEMBLY 不支持加载多模块程序集。 SQL Server 还将在同一位置查找此程序集的所有相关程序集,并使用与根级别程序集相同的所有者将其上载。 如果未找到这些依赖程序集,并且它们尚未加载到当前数据库中, CREATE ASSEMBLY 则失败。 如果相关程序集已加载到当前数据库中,则这些程序集的所有者必须与新创建的程序集的所有者相同。

重要

Azure SQL 数据库 & Azure SQL 托管实例不支持从文件创建程序集。

<client_assembly_specifier> 如果正在模拟已登录的用户,则无法指定。

<assembly_bits>

构成程序集及其依赖程序集的二进制值的列表。 列表中的第一个值将视为根级程序集。 与相关程序集对应的值可以按任意顺序提供。 将忽略与根程序集依赖项不对应的任何值。

注意

此选项在包含的数据库中不可用。

varbinary_literal

varbinary 文本。

varbinary_expression

varbinary 类型的表达式。

PERMISSION_SET { SAFE | EXTERNAL_ACCESS | UNSAFE }

指定 SQL Server 访问时授予程序集的一组代码访问权限。 如果未指定, SAFE 则应用为默认值。

PERMISSION_SET 选项受 服务器配置的影响:clr 严格安全 选项。 如果启用 clr strict security,所有程序集被视为 UNSAFE

我们建议使用 SAFESAFE 是最具限制性的权限集。 具有 SAFE 权限的程序集执行的代码无法访问外部系统资源,如文件、网络、环境变量或注册表。

EXTERNAL_ACCESS 使程序集能够访问某些外部系统资源,例如文件、网络、环境变量和注册表。

UNSAFE 允许程序集不受限制地访问 SQL Server 实例内外的资源。 从程序集内 UNSAFE 运行的代码可以调用非托管代码。

SAFE 是针对执行计算和数据管理任务的程序集的建议权限设置,无需访问 SQL Server 实例外部的资源。

注意

UNSAFE包含EXTERNAL_ACCESS的数据库和选项不可用。

建议用于 EXTERNAL_ACCESS 访问 SQL Server 实例外部资源的程序集。 EXTERNAL_ACCESS 程序集包括程序集的可靠性与可伸缩性保护 SAFE ,但从安全角度来看,它们与 UNSAFE 程序集类似。 默认情况下,程序集中的 EXTERNAL_ACCESS 代码在 SQL Server 服务帐户下运行,并访问该帐户下的外部资源,除非代码显式模拟调用方。 因此,应仅向受信任的登录名授予创建 EXTERNAL_ACCESS 程序集的权限,以在 SQL Server 服务帐户下运行代码。 有关模拟的详细信息,请参阅 CLR 集成安全性

指定 UNSAFE 允许程序集中的代码完全自由地在 SQL Server 进程空间中执行操作,这可能会损害 SQL Server 的稳定性。 UNSAFE 程序集还可能会颠覆 SQL Server 或公共语言运行时的安全系统。 UNSAFE 权限应仅授予高度信任的程序集。 只有 sysadmin 固定服务器角色的成员才能创建和更改UNSAFE程序集。

有关程序集权限集的详细信息,请参阅 设计程序集

不再支持代码访问安全性

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

注解

CREATE ASSEMBLY 上传以前从托管代码编译为.dll文件的程序集,以便在 SQL Server 实例中使用。

启用时,CREATE ASSEMBLYALTER ASSEMBLY 语句中的 PERMISSION_SET 选项在运行时将被忽略,但元数据中将保留 PERMISSION_SET 选项。 忽略该选项可最大程度地减少中断现有代码语句。

SQL Server 不允许使用同一名称、区域性和公钥注册不同版本的程序集。

尝试访问在 中指定的 <client_assembly_specifier>程序集时,SQL Server 模拟当前 Windows 登录名的安全上下文。 如果 <client_assembly_specifier> 指定网络位置(UNC 路径),则由于委派限制,当前登录名的模拟不会转发到网络位置。 在这种情况下,将使用 SQL Server 服务帐户的安全上下文进行访问。 有关详细信息,请参阅凭据(数据库引擎)

除了 assembly_name 指定的根程序集外,SQL Server 还试图上传正在上传的根程序集所引用的所有程序集。 如果由于早期 CREATE ASSEMBLY 语句而已将引用的程序集上传到数据库,则不会上传此程序集,但可用于根程序集。 如果以前未上传依赖程序集,但 SQL Server 无法在源目录中找到其清单文件, CREATE ASSEMBLY 则返回错误。

如果根程序集引用的任何依赖程序集尚未存在于数据库中,并且与根程序集一起隐式加载,则它们具有与根级别程序集相同的权限集。 如果必须使用不同于根级别程序集的权限设置创建相关程序集,则它们必须在具有相应权限设置的根级别程序集之前显式上载。

程序集验证

SQL Server 扫描语句上传 CREATE ASSEMBLY 的程序集二进制文件,以确保进行以下检查:

  • 程序集二进制文件具有格式正确的有效元数据和代码段,并且代码段包含有效的 Microsoft 中间语言 (MSIL) 指令。

  • 它引用的系统程序集集是 SQL Server 中以下支持的程序集之一:Microsoft.VisualBasic.dll、、System.dllSystem.Xml.dllCustomMarshallers.dllMicrosoft.VisualC.dllSystem.Security.dllmscorlib.dllSystem.Web.Services.dllSystem.Data.dllSystem.Data.SqlXml.dllSystem.Core.dll和。System.Xml.Linq.dll 还可引用其他系统程序集,但这些程序集必须在数据库中显式注册。

  • 对于使用 SAFEEXTERNAL ACCESS 权限集创建的程序集:

    • 程序集代码应是类型安全的。 通过对程序集运行公共语言运行时验证工具可建立类型安全。

    • 程序集不应在其类中包含任何静态数据成员,除非它们被标记为只读。

    • 程序集中的类不能包含终结器方法。

    • 程序集的类或方法只能使用允许的代码属性进行注释。 有关详细信息,请参阅 CLR 集成:CLR 例程的自定义属性。

除了执行时 CREATE ASSEMBLY 执行的先前检查外,在程序集中的代码执行时还执行了额外的检查:

  • 如果程序集的权限集不包含该权限,则调用需要特定代码访问权限的某些 .NET Framework API 可能会失败。

  • 对于 SAFEEXTERNAL_ACCESS 程序集,任何调用使用某些 HostProtectionAttributes 注释的 .NET Framework API 尝试都失败。

有关详细信息,请参阅 设计程序集

权限

需要 CREATE ASSEMBLY 权限。

如果 PERMISSION_SET = EXTERNAL_ACCESS 指定,则需要 EXTERNAL ACCESS ASSEMBLY 对服务器具有权限。 如果 PERMISSION_SET = UNSAFE 指定,则需要 UNSAFE ASSEMBLY 对服务器具有权限。

如果程序集已经存在于数据库中,则用户必须是将上载的程序集所引用的所有程序集的所有者。 若要使用文件路径上传程序集,则当前用户必须是经过 Windows 身份验证的登录名或 sysadmin 固定服务器角色的成员。 执行 CREATE ASSEMBLY 的用户的 Windows 登录名必须具有对共享和在语句中加载的文件的读取权限。

CLR 严格安全性的权限

启用 CLR strict security 时,创建 CLR 程序集需要以下权限:

  • 用户必须具有 CREATE ASSEMBLY 权限
  • 并且,还必须满足以下条件之一:
    • 使用具有相应登录名(该登录名对应于服务器上的 UNSAFE ASSEMBLY 权限)的证书或非对称密钥对程序集进行签名。 建议对程序集进行签名。
    • 数据库的 TRUSTWORTHY 属性设置为 ON,且数据库由在服务器上具有 UNSAFE ASSEMBLY 权限的登录名所有。 不建议使用此选项。

有关程序集权限集的详细信息,请参阅 设计程序集

示例

A. 从 DLL 创建程序集

以下示例假定 SQL Server 数据库引擎示例安装在本地计算机的默认位置,并HelloWorld.csproj编译示例应用程序。 有关详细信息,请参阅 Hello World 示例

CREATE ASSEMBLY HelloWorld
FROM '<system_drive>:\Program Files\Microsoft SQL Server\100\Samples\HelloWorld\CS\HelloWorld\bin\debug\HelloWorld.dll'
WITH PERMISSION_SET = SAFE;

重要

Azure SQL 数据库不支持从文件创建程序集。

B. 从程序集位创建程序集

将示例位(未完成或有效)替换为程序集位。

CREATE ASSEMBLY HelloWorld
    FROM 0x4D5A900000000000
WITH PERMISSION_SET = SAFE;