EXECUTE (Transact-SQL)

适用于:SQL ServerAzure SQL 数据库Azure SQL 托管实例Azure Synapse Analytics分析平台系统 (PDW)Microsoft Fabric 中的 SQL 分析终结点Microsoft Fabric 中的仓库Microsoft Fabric 预览版中的 SQL 数据库

执行 Transact-SQL 批处理中的命令字符串、字符串或执行下列模块之一:系统存储过程、用户定义存储过程、CLR 存储过程、标量值用户定义函数或扩展存储过程。 EXECEXECUTE 语句可用于将直通命令发送到链接服务器。 此外,还可以显式设置执行字符串或命令的上下文。 可以使用 WITH RESULT SETS 选项定义结果集的元数据。

Important

在使用字符串调用 EXECUTE 之前,请验证字符串。 从不执行从尚未验证的用户输入构造的命令。

Transact-SQL 语法约定

Syntax

以下代码块显示了 SQL Server 2019(15.x)及更高版本中的语法。 或者,可以参阅 SQL Server 2017 及更早版本中的语法

SQL Server 2019 及更高版本的语法。

-- Execute a stored procedure or function
[ { EXEC | EXECUTE } ]
    {
      [ @return_status = ]
      { module_name [ ;number ] | @module_name_var }
        [ [ @parameter = ] { value
                           | @variable [ OUTPUT ]
                           | [ DEFAULT ]
                           }
        ]
      [ ,...n ]
      [ WITH <execute_option> [ ,...n ] ]
    }
[ ; ]

-- Execute a character string
{ EXEC | EXECUTE }
    ( { @string_variable | [ N ]'tsql_string' } [ + ...n ] )
    [ AS { LOGIN | USER } = ' name ' ]
[ ; ]

-- Execute a pass-through command against a linked server
{ EXEC | EXECUTE }
    ( { @string_variable | [ N ] 'command_string [ ? ]' } [ + ...n ]
        [ { , { value | @variable [ OUTPUT ] } } [ ...n ] ]
    )
    [ AS { LOGIN | USER } = ' name ' ]
    [ AT linked_server_name ]
    [ AT DATA_SOURCE data_source_name ]
[ ; ]

<execute_option>::=
{
        RECOMPILE
    | { RESULT SETS UNDEFINED }
    | { RESULT SETS NONE }
    | { RESULT SETS ( <result_sets_definition> [,...n ] ) }
}

<result_sets_definition> ::=
{
    (
         { column_name
           data_type
         [ COLLATE collation_name ]
         [ NULL | NOT NULL ] }
         [,...n ]
    )
    | AS OBJECT
        [ db_name . [ schema_name ] . | schema_name . ]
        {table_name | view_name | table_valued_function_name }
    | AS TYPE [ schema_name.]table_type_name
    | AS FOR XML
}

以下代码块显示了 SQL Server 2017(14.x)和早期版本中的语法。 或者,可以参阅 SQL Server 2019 中的语法

SQL Server 2017 及更低版本的语法。

-- Execute a stored procedure or function
[ { EXEC | EXECUTE } ]
    {
      [ @return_status = ]
      { module_name [ ;number ] | @module_name_var }
        [ [ @parameter = ] { value
                           | @variable [ OUTPUT ]
                           | [ DEFAULT ]
                           }
        ]
      [ ,...n ]
      [ WITH <execute_option> [ ,...n ] ]
    }
[ ; ]

-- Execute a character string
{ EXEC | EXECUTE }
    ( { @string_variable | [ N ]'tsql_string' } [ + ...n ] )
    [ AS { LOGIN | USER } = ' name ' ]
[ ; ]

-- Execute a pass-through command against a linked server
{ EXEC | EXECUTE }
    ( { @string_variable | [ N ] 'command_string [ ? ]' } [ + ...n ]
        [ { , { value | @variable [ OUTPUT ] } } [ ...n ] ]
    )
    [ AS { LOGIN | USER } = ' name ' ]
    [ AT linked_server_name ]
[ ; ]

<execute_option>::=
{
        RECOMPILE
    | { RESULT SETS UNDEFINED }
    | { RESULT SETS NONE }
    | { RESULT SETS ( <result_sets_definition> [,...n ] ) }
}

<result_sets_definition> ::=
{
    (
         { column_name
           data_type
         [ COLLATE collation_name ]
         [ NULL | NOT NULL ] }
         [,...n ]
    )
    | AS OBJECT
        [ db_name . [ schema_name ] . | schema_name . ]
        {table_name | view_name | table_valued_function_name }
    | AS TYPE [ schema_name.]table_type_name
    | AS FOR XML
}

In-Memory OLTP 的语法。

-- Execute a natively compiled, scalar user-defined function
[ { EXEC | EXECUTE } ]
    {
      [ @return_status = ]
      { module_name | @module_name_var }
        [ [ @parameter = ] { value
                           | @variable
                           | [ DEFAULT ]
                           }
        ]
      [ ,...n ]
      [ WITH <execute_option> [ ,...n ] ]
    }
<execute_option>::=
{
    | { RESULT SETS UNDEFINED }
    | { RESULT SETS NONE }
    | { RESULT SETS ( <result_sets_definition> [,...n ] ) }
}

Azure SQL 数据库的语法。

-- Execute a stored procedure or function
[ { EXEC | EXECUTE } ]
    {
      [ @return_status = ]
      { module_name  | @module_name_var }
        [ [ @parameter = ] { value
                           | @variable [ OUTPUT ]
                           | [ DEFAULT ]
                           }
        ]
      [ ,...n ]
      [ WITH RECOMPILE ]
    }
[ ; ]

-- Execute a character string
{ EXEC | EXECUTE }
    ( { @string_variable | [ N ]'tsql_string' } [ + ...n ] )
    [ AS {  USER } = ' name ' ]
[ ; ]

<execute_option>::=
{
        RECOMPILE
    | { RESULT SETS UNDEFINED }
    | { RESULT SETS NONE }
    | { RESULT SETS ( <result_sets_definition> [,...n ] ) }
}

<result_sets_definition> ::=
{
    (
         { column_name
           data_type
         [ COLLATE collation_name ]
         [ NULL | NOT NULL ] }
         [,...n ]
    )
    | AS OBJECT
        [ db_name . [ schema_name ] . | schema_name . ]
        {table_name | view_name | table_valued_function_name }
    | AS TYPE [ schema_name.]table_type_name
    | AS FOR XML
}

Azure Synapse Analytics 和并行数据仓库的语法。

-- Execute a stored procedure
[ { EXEC | EXECUTE } ]
    procedure_name
        [ { value | @variable [ OUT | OUTPUT ] } ] [ ,...n ]
[ ; ]

-- Execute a SQL string
{ EXEC | EXECUTE }
    ( { @string_variable | [ N ] 'tsql_string' } [ +...n ] )
[ ; ]

Microsoft Fabric 的语法。

-- Execute a stored procedure
[ { EXEC | EXECUTE } ]
    procedure_name
        [ { value | @variable [ OUT | OUTPUT ] } ] [ ,...n ]
        [ WITH <execute_option> [ ,...n ] ]  }
[ ; ]

-- Execute a SQL string
{ EXEC | EXECUTE }
    ( { @string_variable | [ N ] 'tsql_string' } [ +...n ] )
[ ; ]

<execute_option>::=
{
        RECOMPILE
    | { RESULT SETS UNDEFINED }
    | { RESULT SETS NONE }
    | { RESULT SETS ( <result_sets_definition> [,...n ] ) }
}

Arguments

@return_status

一个可选的整数变量,用于存储模块的返回状态。 在 EXECUTE 语句中使用该变量之前,必须在批处理、存储过程或函数中声明此变量。

用于调用标量值用户定义函数时,@return_status 变量可以是任何标量数据类型。

module_name

要调用的存储过程或标量值用户定义函数的完全限定或非限定名称。 模块名称必须符合标识符规则。 无论服务器的排序规则如何,扩展存储过程的名称总是区分大小写。

如果运行该模块的用户拥有该模块,或者具有在该数据库中执行该模块的适当权限,则可以执行在另一个数据库中创建的模块。 用户可以在另一台运行 SQL Server 的服务器中执行模块,只要该用户有相应的权限使用该服务器(远程访问),并能在数据库中执行该模块。 如果指定了服务器名称但没有指定数据库名称,则 SQL Server 数据库引擎会在用户的默认数据库中查找该模块。

;number

用于对相同名称的过程进行分组的可选整数。 此参数不用于扩展存储过程。

Note

在 SQL Server的未来版本中将删除此功能。 请避免在新的开发工作中使用该功能,并着手修改当前还在使用该功能的应用程序。

有关过程组的详细信息,请参阅 CREATE PROCEDURE

@module_name_var

表示模块名称的本地定义的变量的名称。

该变量可以包含本机编译的标量用户定义函数的名称。

@parameter

模块中定义的 module_name参数。 参数名称前面必须有 at 符号(@)。 与 @parameter_name = 值一起使用时 窗体,参数名称和常量不必按模块中定义的顺序提供。 但是,如果 @parameter_name = 窗体用于任何参数,则必须将其用于所有后续参数。

默认情况下,参数可为空值。

value

要传递给模块或传递命令的参数的值。 如果未指定参数名称,则必须按照模块中定义的顺序提供参数值。

对链接服务器执行传递命令时,参数值的顺序取决于链接服务器的 OLE DB 访问接口。 大多数 OLE DB 访问接口按从左到右的顺序将值绑定到参数。

如果参数值是一个对象名、字符串或由数据库名称或架构名称限定,则整个名称必须用单引号括起来。 如果参数值是一个关键字,则该关键字必须用双引号括起来。

如果传递的单词不以 @开头,则不括在引号中(例如,如果忘记参数名称上的 @),该单词将被视为 nvarchar 字符串,尽管缺少引号。

如果在模块中定义了默认值,用户执行该模块时可以不必指定参数。

默认值也可以 NULL。 通常,模块定义指定在参数值 NULL时应执行的操作。

@variable

存储参数或返回参数的变量。

OUTPUT

指定模块或命令字符串返回一个参数。 模块或命令字符串中的匹配参数也必须使用关键字 OUTPUT创建。 使用游标变量作为参数时使用该关键字。

如果 定义为对链接服务器执行的模块的 OUTPUT,则对 OLE DB 访问接口执行的相应 @parameter 所做的任何更改将复制回模块执行结束时的变量。

如果使用 OUTPUT 参数,并且意图是在调用批处理或模块中的其他语句中使用返回值,则必须将参数的值作为变量传递,例如 @parameter = @variable。 不能通过为模块中未定义为 OUTPUT 参数的参数指定 OUTPUT 来执行模块。 无法使用 OUTPUT; 将常量传递给模块;返回参数需要变量名称。 在执行过程之前,必须声明变量的数据类型并赋值。

当对远程存储过程使用 EXECUTE,或对链接服务器执行传递命令时,OUTPUT 参数不能是大型对象(LOB)数据类型之一。

返回参数可以是 LOB 数据类型之外的任意数据类型。

DEFAULT

根据模块的定义,提供参数的默认值。 当模块需要一个没有定义默认值且缺少参数或指定 DEFAULT 关键字的参数的值时,将发生错误。

@string_variable

局部变量的名称。 @string_variable 可以是任何 charvarcharncharnvarchar 数据类型。 其中包括 (max) 数据类型。

[N]'tsql_string'

常量字符串。 tsql_string 可以为任何 nvarcharvarchar 数据类型。 如果包含 N,字符串将解释为 nvarchar 数据类型。

AS context_specification

指定执行语句的上下文。

LOGIN

指定要模拟的上下文是登录名。 模拟范围为服务器。

USER

指定要模拟的上下文是当前数据库中的用户。 模拟范围只限于当前数据库。 上下文切换到数据库用户不会继承该用户的服务器级权限。

Important

当上下文切换到数据库用户时,任何尝试访问数据库外部的资源都会导致语句失败。 这包括 USE <database> 语句、分布式查询和使用三部分或四部分标识符引用另一个数据库的查询。

'name'

有效的用户或登录名。 名称 参数必须是 sysadmin 固定服务器角色的成员,或者分别作为 sys.database_principalssys.server_principals中的主体存在。

此参数不能是内置帐户,例如 NT AUTHORITY\LocalServiceNT AUTHORITY\NetworkServiceNT AUTHORITY\LocalSystem

有关详细信息,请参阅本文后面的 指定用户或登录名

[N]'command_string'

包含要传递到链接服务器的命令的常量字符串。 如果包含 N,字符串将解释为 nvarchar 数据类型。

[?]

指示在 <arg-list> 语句中使用的传递命令 EXECUTE ('...', <arg-list>) AT <linkedsrv> 中提供哪些值的参数。

AT linked_server_name

指定对 linked_server_name 执行 command_string,并将结果(如果有)返回到客户端。 linked_server_name 必须引用本地服务器中的现有链接服务器定义。 链接服务器是使用 sp_addlinkedserver 定义的。

  • WITH <execute_option>

    可能的执行选项。 无法在 RESULT SETS 语句中指定 INSERT...EXECUTE 选项。

AT DATA_SOURCE data_source_name

适用于:SQL Server 2019 (15.x) 及更高版本。

指定对 _name 执行 command_string,并将结果(如果有)返回到客户端。 data_source_name 必须引用数据库中的现有 EXTERNAL DATA SOURCE 定义。 仅支持指向 SQL Server 的数据源。 此外,对于指向计算池的 SQL Server 大数据群集数据源,支持数据池或存储池。 使用 CREATE EXTERNAL DATA SOURCE 定义数据源。

  • WITH <execute_option>

    可能的执行选项。 无法在 RESULT SETS 语句中指定 INSERT...EXECUTE 选项。

    Term Definition
    RECOMPILE 执行模块后,强制编译、使用和放弃新计划。 如果模块存在现有查询计划,此计划将保留在缓存中。

    如果提供的参数不典型或数据已显著更改,请使用此选项。 此选项不用于扩展存储过程。 建议谨慎使用此选项,因为它成本高昂。

    注意: 调用使用 WITH RECOMPILE 语法的存储过程时无法使用 OPENDATASOURCE。 指定四部分对象名称时,将忽略 WITH RECOMPILE 选项。

    注意:本机编译的标量用户定义函数不支持RECOMPILE。 如果需要重新编译,请使用 sp_recompile
    RESULT SETS UNDEFINED 此选项不保证返回结果(如果有)且未提供定义。 如果返回任何结果,则说明语句正常执行而没有发生错误,否则,不会返回任何结果。 如果未提供result_sets_option,则 RESULT SETS UNDEFINED 是默认行为。

    对于解释的标量用户定义函数和本机编译的标量用户定义函数,此选项不可运行,因为函数永远不会返回结果集。

    适用于:SQL Server 2012(11.x)及更高版本以及 Azure SQL 数据库。
    RESULT SETS NONE 保证 EXECUTE 语句不返回任何结果。 如果返回任何结果,则会中止批处理。

    对于解释的标量用户定义函数和本机编译的标量用户定义函数,此选项不可运行,因为函数永远不会返回结果集。

    适用于:SQL Server 2012(11.x)及更高版本以及 Azure SQL 数据库。
    <result_sets_definition> 保证结果按 result_sets_definition中指定的结果返回。 对于返回多个结果集的语句,请提供多个 result_sets_definition 部分。 将每个 result_sets_definition 用括号括上,并以逗号隔开。 有关详细信息,请参阅本文后面的 <result_sets_definition>

    对于本机编译的标量用户定义函数,此选项总是会导致错误,因为这些函数永远不会返回结果集。

    适用于:SQL Server 2012(11.x)及更高版本以及 Azure SQL 数据库。

    <result_sets_definition> 描述执行语句返回的结果集。 result_sets_definition 的子句具有以下含义:

    Term Definition
    { column_name data_type
    [ COLLATE collation_name ]
    [NULL |NOT NULL] }
    请参阅下表。
    db_name 包含表、视图或表值函数的数据库的名称。
    schema_name 拥有表、视图或表值函数的架构的名称。
    table_name |view_name |table_valued_function_name 指定返回的列是在命名的表、视图或表值函数中指定的列。 AS 对象语法不支持表变量、临时表和同义词。
    AS TYPE [ schema_name. ]table_type_name 指定返回的列是在表类型中指定的列。
    AS FOR XML 指定由 EXECUTE 语句调用的语句或存储过程的 XML 结果转换为格式,就像 SELECT ... FOR XML ... 语句生成一样。 删除原始语句中类型指令的所有格式,返回的结果与未指定类型指令一样。 AS FOR XML 不会将执行语句或存储过程中的非 XML 表格结果转换为 XML。
    Term Definition
    column_name 每个列的名称。 如果列数不同于结果集,则会发生错误并中止批处理。 如果列名不同于结果集,则将返回的列名设置为定义的名称。
    data_type 每个列的数据类型。 如果数据类型不同,则对定义的数据类型执行隐式转换。 如果转换失败,则中止批处理。
    COLLATE collation_name 每个列的排序规则。 如果排序规则不匹配,则尝试隐式排序规则。 如果该操作失败,则中止批处理。
    NULL |NOT NULL 每个列的为 Null 性。 如果定义的可为空性 NOT NULL 且返回的数据包含 null,则会发生错误,并且批处理中止。 如果未指定,则默认值符合 ANSI_NULL_DFLT_ONANSI_NULL_DFLT_OFF 选项的设置。

    在执行期间返回的实际结果集可能与使用以下方法之一使用 WITH RESULT SETS 子句定义的结果不同:结果集数、列数、列名、可为 null 性和数据类型。 如果结果集数不同,则会发生错误并中止批处理。

Remarks

可以使用 或使用 @parameter_name = 来提供参数。 参数不是事务的一部分;因此,如果在以后回滚的事务中更改了参数,则参数的值不会还原到其以前的值。 返回给调用方的值总是模块返回时的值。

当一个模块调用其他模块或通过引用公共语言运行时 (CLR) 模块、用户定义类型或聚合执行托管代码时,将出现嵌套。 当调用的模块或托管代码引用开始执行时,嵌套级别会递增,并在调用的模块或托管代码引用完成时递减。 嵌套级别最高为 32 级,超过 32 级时,会导致整个调用链失败。 当前嵌套级别存储在 @@NESTLEVEL 系统函数中。

由于远程存储过程和扩展存储过程不在事务范围内(除非在 BEGIN DISTRIBUTED TRANSACTION 语句中发出或与各种配置选项一起使用),因此无法回滚通过调用执行这些存储过程的命令。 有关详细信息,请参阅 系统存储过程BEGIN 分布式事务

使用游标变量时,如果执行一个过程,该过程传入的游标变量中分配了游标,则会发生错误。

如果语句是批处理中的第一个模块,则无需指定 EXECUTE 关键字。

有关特定于 CLR 存储过程的详细信息,请参阅 CLR 存储过程

将 EXECUTE 与存储过程配合使用

当语句是批处理中的第一个存储过程时,无需指定 EXECUTE 关键字。

SQL Server 系统存储过程以字符 sp_开头。 它们以物理方式存储在 资源数据库中,但在逻辑上显示在每个系统和用户定义的数据库的 sys 架构中。 在批处理或模块(如用户定义存储过程或函数)中执行系统存储过程时,建议使用 sys 架构名称限定存储过程名称。

SQL Server 系统扩展存储过程以字符 xp_开头,这些存储过程包含在 master 数据库的 dbo 架构中。 执行系统扩展存储过程时,无论是在批处理中还是在模块(如用户定义的存储过程或函数)中,我们建议你使用 master.dbo限定存储过程名称。

在批处理或模块(如用户定义存储过程或函数)内执行用户定义存储过程时,建议使用架构名限定存储过程名称。 建议不要将用户定义存储过程命名为与系统存储过程同名。 有关执行存储过程的详细信息,请参阅 执行存储过程

将 EXECUTE 与字符串配合使用

在 SQL Server 中,可以指定 varchar(max)nvarchar(max) 数据类型,它们允许字符串使用多达 2 GB 数据。

数据库上下文中的更改仅持续到 EXECUTE 语句的末尾。 例如,运行以下语句中的 EXECUTE 后,数据库上下文 master

USE master;

EXECUTE ('USE AdventureWorks2022; SELECT BusinessEntityID, JobTitle FROM HumanResources.Employee;');

上下文切换

可以使用 AS { LOGIN | USER } = '<name>' 子句切换动态语句的执行上下文。 当将上下文切换指定为 EXECUTE ('string') AS <context_specification> 时,上下文切换的持续时间限制为执行查询的范围。

指定用户或登录名

AS { LOGIN | USER } = '<name>' 中指定的用户或登录名必须分别作为 sys.database_principalssys.server_principals 中的主体存在,否则该语句将失败。 此外,必须向主体授予 IMPERSONATE 权限。 除非调用方是数据库所有者,或者是 sysadmin 固定服务器角色的成员,否则即使用户通过 Windows 组成员身份访问 SQL Server 的数据库或实例,主体也必须存在。 例如,假设条件如下:

  • CompanyDomain\SQLUsers 组有权访问 Sales 数据库。

  • CompanyDomain\SqlUser1SQLUsers 的成员,因此对 Sales 数据库具有隐式访问权限。

尽管 CompanyDomain\SqlUser1 通过 SQLUsers 组中的成员身份访问数据库,但语句 EXECUTE @string_variable AS USER = 'CompanyDomain\SqlUser1' 失败,因为数据库中不存在 CompanyDomain\SqlUser1 作为主体。

最佳做法

指定具有执行语句或模块中定义的操作所需的最低权限的登录名或用户。 例如,如果只需要数据库级权限,则不要指定具有服务器级权限的登录名。 或者,除非需要这些权限,否则不要指定数据库所有者帐户。

Permissions

运行 EXECUTE 语句不需要权限。 但是,在 EXECUTE 字符串中引用的安全对象上需要权限。 例如,如果字符串包含 INSERT 语句,则 EXECUTE 语句的调用方必须对目标表具有 INSERT 权限。 即使模块中包含 EXECUTE 语句,也会在遇到 EXECUTE 语句时检查权限。

数据库引擎如何评估模块中引用的对象的权限取决于调用对象和引用对象之间存在的 所有权链

EXECUTE 模块的权限默认为模块的所有者,他们可以将其转移到其他用户。 当运行一个执行字符串的模块时,系统会在执行该模块的用户上下文中而不是在创建该模块的用户上下文中检查权限。 但是,如果同一用户拥有调用模块和要调用的模块,则不会对第二个模块执行 EXECUTE 权限检查。

如果模块访问其他数据库对象,则当对模块具有 EXECUTE 权限并且满足以下条件之一时,执行会成功:

  • 模块标记为 EXECUTE AS USEREXECUTE AS SELF,模块所有者对引用的对象具有相应的权限。 有关模块中模拟的详细信息,请参阅 EXECUTE AS 子句

  • 模块标记为 EXECUTE AS CALLER,并且你对对象具有相应的权限。

  • 模块标记为 EXECUTE AS <user_name><user_name> 对对象具有相应的权限。

上下文切换权限

若要在登录名上指定 EXECUTE AS,调用方必须对指定的登录名具有 IMPERSONATE 权限。 若要对数据库用户指定 EXECUTE AS,调用方必须对指定的用户名具有 IMPERSONATE 权限。 如果未指定执行上下文或指定 EXECUTE AS CALLER,则不需要 IMPERSONATE 权限。

示例:SQL Server

本文中的代码示例使用 AdventureWorks2022AdventureWorksDW2022 示例数据库,可以从 Microsoft SQL Server 示例和社区项目 主页下载该数据库。

A. 使用 EXECUTE 传递单个参数

AdventureWorks2022 数据库中的 uspGetEmployeeManagers 存储过程需要一个参数 (@EmployeeID)。 以下示例执行uspGetEmployeeManagers 存储过程,以 Employee ID 6 作为参数值。

EXECUTE dbo.uspGetEmployeeManagers 6;
GO

在执行过程中变量可以显式命名:

EXECUTE dbo.uspGetEmployeeManagers @EmployeeID = 6;
GO

如果下面是批处理或 sqlcmd 脚本中的第一个语句,则不需要 EXECUTE

EXECUTE dbo.uspGetEmployeeManagers 6;
GO

--Or
EXECUTE dbo.uspGetEmployeeManagers @EmployeeID = 6;
GO

B. 使用多个参数

下面的示例执行 AdventureWorks2022 数据库中的 spGetWhereUsedProductID 存储过程。 它传递两个参数:第一个参数是产品 ID(819),第二个参数 @CheckDate日期/时间 值。

DECLARE @CheckDate AS DATETIME;
SET @CheckDate = GETDATE();

EXECUTE dbo.uspGetWhereUsedProductID 819, @CheckDate;
GO

C. 将 EXECUTE“tsql_string”与变量配合使用

下面的示例说明了 EXECUTE 如何处理动态生成的包含变量的字符串。 该示例创建 tables_cursor 游标以保存 AdventureWorks2022 数据库中所有用户定义表的列表,然后使用该列表重新生成对表的全部索引。

DECLARE tables_cursor CURSOR
    FOR SELECT s.name, t.name FROM sys.objects AS t
    INNER JOIN sys.schemas AS s ON s.schema_id = t.schema_id
    WHERE t.type = 'U';

OPEN tables_cursor;

DECLARE @schemaname AS sysname;
DECLARE @tablename AS sysname;

FETCH NEXT FROM tables_cursor INTO @schemaname, @tablename;

WHILE (@@FETCH_STATUS <> -1)
    BEGIN
        EXECUTE ('ALTER INDEX ALL ON ' +
            @schemaname + '.' +
            @tablename + ' REBUILD;');
        FETCH NEXT FROM tables_cursor INTO @schemaname, @tablename;
    END

PRINT 'The indexes on all tables have been rebuilt.';

CLOSE tables_cursor;

DEALLOCATE tables_cursor;

D. 将 EXECUTE 与远程存储过程配合使用

以下示例在远程服务器 uspGetEmployeeManagers 上执行 SQLSERVER1 存储过程,然后在 @retstat 中存储指示成功或失败的返回状态。

DECLARE @retstat AS INT;

EXECUTE
    @retstat = SQLSERVER1.AdventureWorks2022.dbo.uspGetEmployeeManagers
    @BusinessEntityID = 6;

E. 将 EXECUTE 与存储过程变量配合使用

以下示例创建一个代表存储过程名称的变量。

DECLARE @proc_name AS VARCHAR (30);
SET @proc_name = 'sys.sp_who';

EXECUTE @proc_name;

F. 将 EXECUTE 与 DEFAULT 配合使用

以下示例创建了一个存储过程,第一个和第三个参数具有默认值。 当运行该过程时,如果调用时没有传递值或者指定了默认值,这些默认值就会赋给第一个和第三个参数。 请注意,DEFAULT 关键字有多种使用方法。

IF OBJECT_ID(N'dbo.ProcTestDefaults', N'P') IS NOT NULL
    DROP PROCEDURE dbo.ProcTestDefaults;
GO

-- Create the stored procedure.
CREATE PROCEDURE dbo.ProcTestDefaults (
    @p1 SMALLINT = 42,
    @p2 CHAR (1),
    @p3 VARCHAR (8) = 'CAR'
)
AS
SET NOCOUNT ON;
SELECT @p1, @p2, @p3;
GO

Proc_Test_Defaults 存储过程可使用多种组合执行。

-- Specifying a value only for one parameter (@p2).
EXECUTE dbo.ProcTestDefaults @p2 = 'A';

-- Specifying a value for the first two parameters.
EXECUTE dbo.ProcTestDefaults 68, 'B';

-- Specifying a value for all three parameters.
EXECUTE dbo.ProcTestDefaults 68, 'C', 'House';

-- Using the DEFAULT keyword for the first parameter.
EXECUTE dbo.ProcTestDefaults
    @p1 = DEFAULT,
    @p2 = 'D';

-- Specifying the parameters in an order different from the order defined in the procedure.
EXECUTE dbo.ProcTestDefaults DEFAULT,
    @p3 = 'Local',
    @p2 = 'E';

-- Using the DEFAULT keyword for the first and third parameters.
EXECUTE dbo.ProcTestDefaults DEFAULT, 'H', DEFAULT;
EXECUTE dbo.ProcTestDefaults DEFAULT, 'I', @p3 = DEFAULT;

G. 将 EXECUTE 与 AT linked_server_name 配合使用

以下示例将一个命令字符串传递给远程服务器。 先创建一个链接服务器 SeattleSales,它指向 SQL Server 的另一个实例,然后对该链接服务器执行 DDL 语句 (CREATE TABLE)。

EXECUTE sp_addlinkedserver 'SeattleSales', 'SQL Server';
GO

EXECUTE ('CREATE TABLE AdventureWorks2022.dbo.SalesTbl
(SalesID INT, SalesName VARCHAR(10)); ') AT SeattleSales;
GO

H. 使用 EXECUTE WITH RECOMPILE

以下示例执行 Proc_Test_Defaults 存储过程,并在执行模块后强制编译、使用和放弃一个新查询计划。

EXECUTE dbo.Proc_Test_Defaults @p2 = 'A'
WITH RECOMPILE;
GO

I. 将 EXECUTE 与用户定义的函数配合使用

下面的示例在 AdventureWorks2022 数据库中执行 ufnGetSalesOrderStatusText 标量用户定义函数。 该语句使用 @returnstatus 变量存储函数的返回值。 函数需要一个输入参数 @Status。 该参数定义为 tinyint 数据类型。

DECLARE @returnstatus AS NVARCHAR (15);
SET @returnstatus = NULL;

EXECUTE
    @returnstatus = dbo.ufnGetSalesOrderStatusText
    @Status = 2;

PRINT @returnstatus;
GO

J. 使用 EXECUTE 查询链接服务器上的 Oracle 数据库

以下示例在远程 Oracle 服务器上执行几个 SELECT 语句。 示例开始时添加 Oracle 服务器作为链接服务器,并创建链接服务器登录。

-- Setup the linked server.
EXECUTE sp_addlinkedserver
    @server = 'ORACLE',
    @srvproduct = 'Oracle',
    @provider = 'OraOLEDB.Oracle',
    @datasrc = 'ORACLE10';

EXECUTE sp_addlinkedsrvlogin
    @rmtsrvname = 'ORACLE',
    @useself = 'false',
    @locallogin = NULL,
    @rmtuser = 'scott',
    @rmtpassword = 'tiger';

EXECUTE sp_serveroption 'ORACLE', 'rpc out', true;
GO

-- Execute several statements on the linked Oracle server.
EXECUTE ('SELECT * FROM scott.emp') AT ORACLE;
GO

EXECUTE ('SELECT * FROM scott.emp WHERE MGR = ?', 7902) AT ORACLE;
GO

DECLARE @v AS INT;
SET @v = 7902;

EXECUTE ('SELECT * FROM scott.emp WHERE MGR = ?', @v) AT ORACLE;
GO

K. 使用 EXECUTE AS USER 将上下文切换到其他用户

以下示例执行用于创建表的 Transact-SQL 字符串并指定 AS USER 子句将语句的执行上下文从调用方切换为 User1。 数据库引擎在运行语句时检查 User1 的权限。 User1 必须为数据库中的用户,必须具有在 Sales 架构中创建表的权限,否则语句将失败。

EXECUTE ('CREATE TABLE Sales.SalesTable (SalesID INT, SalesName VARCHAR(10));')
AS USER = 'User1';
GO

L. 将参数用于 EXECUTE 和 AT linked_server_name

以下示例使用问号 (?) 占位符作为参数向远程服务器传递命令字符串。 该示例先创建一个链接服务器 SeattleSales,它指向另一个 SQL Server 实例,然后对该链接服务器执行 SELECT 语句。 SELECT 语句使用问号作为 ProductID 参数 (952)(该参数在语句后提供)的占位符。

-- Setup the linked server.
EXECUTE sp_addlinkedserver 'SeattleSales', 'SQL Server';
GO

-- Execute the SELECT statement.
EXECUTE ('SELECT ProductID, Name
    FROM AdventureWorks2022.Production.Product
    WHERE ProductID = ? ', 952) AT SeattleSales;
GO

M. 使用 EXECUTE 重新定义单个结果集

适用于:SQL Server 2012(11.x)及更高版本以及 Azure SQL 数据库。

前面的一些示例执行了 EXECUTE dbo.uspGetEmployeeManagers 6; 返回七列。 以下示例说明如何使用 WITH RESULT SET 语法更改返回的结果集的名称和数据类型。

EXECUTE uspGetEmployeeManagers 16 WITH RESULT SETS
((
    [Reporting Level] INT NOT NULL,
    [ID of Employee] INT NOT NULL,
    [Employee First Name] NVARCHAR (50) NOT NULL,
    [Employee Last Name] NVARCHAR (50) NOT NULL,
    [Employee ID of Manager] NVARCHAR (MAX) NOT NULL,
    [Manager First Name] NVARCHAR (50) NOT NULL,
    [Manager Last Name] NVARCHAR (50) NOT NULL
));

N. 使用 EXECUTE 重新定义两个结果集

适用于:SQL Server 2012(11.x)及更高版本以及 Azure SQL 数据库。

在执行返回多个结果集的语句时,请定义每个预期结果集。 以下示例在 AdventureWorks2022 中创建一个返回两个结果集的过程。 然后使用 WITH RESULT SETS 子句执行该过程,并指定两个结果集定义。

--Create the procedure
CREATE PROCEDURE Production.ProductList
@ProdName NVARCHAR (50)
AS
-- First result set
SELECT ProductID,
       Name,
       ListPrice
FROM Production.Product
WHERE Name LIKE @ProdName;
-- Second result set
SELECT Name,
       COUNT(S.ProductID) AS NumberOfOrders
FROM Production.Product AS P
     INNER JOIN Sales.SalesOrderDetail AS S
         ON P.ProductID = S.ProductID
WHERE Name LIKE @ProdName
GROUP BY Name;
GO

-- Execute the procedure
EXECUTE Production.ProductList '%tire%' WITH RESULT SETS
(
    -- first result set definition starts here
    (ProductID INT, [Name] NAME, ListPrice MONEY)
    -- comma separates result set definitions
    ,
    -- second result set definition starts here
    ([Name] NAME, NumberOfOrders INT)
);

O. 将 EXECUTE 与 AT DATA_SOURCE data_source_name配合使用以查询远程 SQL Server

适用于:SQL Server 2019 (15.x) 及更高版本。

以下示例将命令字符串传递给指向 SQL Server 实例的外部数据源。

EXECUTE ( 'SELECT @@SERVERNAME' ) AT DATA_SOURCE my_sql_server;
GO

P. 在 AT DATA_SOURCE data_source_name中使用 EXECUTE 查询 SQL Server 大数据群集中的计算池

适用于:SQL Server 2019 (15.x)。

以下示例将命令字符串传递给指向 SQL Server 大数据群集中计算池的外部数据源。 该示例针对 SQL Server 大数据群集中的计算池创建数据源 SqlComputePool,并对该数据源执行 SELECT 语句。

CREATE EXTERNAL DATA SOURCE SqlComputePool
WITH (LOCATION = 'sqlcomputepool://controller-svc/default');

EXECUTE ('SELECT @@SERVERNAME') AT DATA_SOURCE SqlComputePool;
GO

Q. 在 AT DATA_SOURCE data_source_name中使用 EXECUTE 查询 SQL Server 大数据群集中的数据池

适用于:SQL Server 2019 (15.x)。

以下示例将命令字符串传递给指向 SQL Server 大数据群集(BDC)中的计算池的外部数据源。 该示例针对 BDC 中的数据池创建数据源 SqlDataPool,并针对数据源执行 SELECT 语句。

CREATE EXTERNAL DATA SOURCE SqlDataPool
WITH (LOCATION = 'sqldatapool://controller-svc/default');

EXECUTE ('SELECT @@SERVERNAME') AT DATA_SOURCE SqlDataPool;
GO

R. 在 AT DATA_SOURCE data_source_name中使用 EXECUTE 查询 SQL Server 大数据群集中的存储池

适用于:SQL Server 2019 (15.x)。

以下示例将命令字符串传递给指向 SQL Server 大数据群集中计算池的外部数据源。 该示例针对 SQL Server 大数据群集中的数据池创建数据源 SqlStoragePool,并对该数据源执行 SELECT 语句。

CREATE EXTERNAL DATA SOURCE SqlStoragePool
WITH (LOCATION = 'sqlhdfs://controller-svc/default');

EXECUTE ('SELECT @@SERVERNAME') AT DATA_SOURCE SqlStoragePool;
GO

示例:Azure Synapse Analytics

本文中的代码示例使用 AdventureWorks2022AdventureWorksDW2022 示例数据库,可以从 Microsoft SQL Server 示例和社区项目 主页下载该数据库。

答:基本过程执行

执行存储过程:

EXECUTE proc1;

调用在运行时确定名称的存储过程:

EXECUTE ('EXECUTE ' + @var);

从存储过程内调用存储过程:

CREATE sp_first AS EXECUTE sp_second; EXECUTE sp_third;

B:执行字符串

执行 SQL 字符串:

EXECUTE ('SELECT * FROM sys.types');

执行嵌套字符串:

EXECUTE ('EXECUTE (''SELECT * FROM sys.types'')');

执行字符串变量:

DECLARE @stringVar AS NVARCHAR (100);
SET @stringVar = N'SELECT name FROM' + ' sys.sql_logins';

EXECUTE (@stringVar);

C:带参数的过程

以下示例使用参数创建一个过程,并演示了执行该过程的三种方法:

CREATE PROCEDURE ProcWithParameters (
    @name NVARCHAR (50),
    @color NVARCHAR (15)
)
AS
SELECT ProductKey,
       EnglishProductName,
       Color
FROM [dbo].[DimProduct]
WHERE EnglishProductName LIKE @namef
      AND Color = @color;
GO

使用位置参数执行:

EXECUTE ProcWithParameters N'%arm%', N'Black';

按顺序使用命名参数执行:

EXECUTE ProcWithParameters
    @name = N'%arm%',
    @color = N'Black';

按顺序使用命名参数执行:

EXECUTE ProcWithParameters
    @color = N'Black',
    @name = N'%arm%';
GO