不熟悉的语法 - 在开始时使用大括号中的参数进行查询

SEa*_*986 6 sql-server syntax parameter sql-server-2016 sp-whoisactive

我已使用以下语法在我们的一台服务器上运行sp_WhoIsActive

sp_whoisactive @get_plans = 1, @show_sleeping_spids = 0, @get_outer_command = 1, @get_locks = 1
Run Code Online (Sandbox Code Playgroud)

并用sql_command(显示的列@get_outer_command设置为1)找到了一个spid,如下所示

(@p1 int,@p2 int)
Exec MyDatabase.MyProc @p1 @p2
Run Code Online (Sandbox Code Playgroud)

当我尝试在我的测试 Adventureworks 数据库上使用此语法运行查询时:

(@be int)
SELECT  *
FROM    Person.Person
WHERE   BusinessEntityID = @be
Run Code Online (Sandbox Code Playgroud)

我收到错误

消息 1050,级别 15,状态 1,第 1 行 此语法仅适用于参数化查询。消息 137,级别 15,状态 2,第 4 行 必须声明标量变量“@FN”。

所以这似乎与参数化查询有关。这是有道理的,因为变量 @be 永远不会被设置为一个值

这里发生了什么?

Ran*_*gen 6

你是对的,显示的 (@be int) 适用于参数化查询。应用程序通常使用 参数化查询sp_executesql,然后将它们发送到 sql 服务器。

查询将被缓存为(variables)QueryText 。当然,这些值不会缓存在文本中,因为查询是参数化的。

参数化查询示例

测试数据

CREATE SCHEMA PERSON;

CREATE TABLE Person.Person( BusinessEntityID int );

INSERT INTO Person.Person(BusinessEntityID)
VALUES(1),(2),(3);
Run Code Online (Sandbox Code Playgroud)

询问

exec sp_executesql N'SELECT  * FROM    Person.Person WHERE   BusinessEntityID = @be',N'@be int',@be=2
Run Code Online (Sandbox Code Playgroud)

使用此查询查看缓存中的结果

select text from sys.dm_exec_query_stats
cross apply sys.dm_exec_sql_text(sql_handle)
where text like '%Person%';
Run Code Online (Sandbox Code Playgroud)

在此处输入图片说明

或者

(@be int)SELECT  * FROM    Person.Person WHERE   BusinessEntityID = @be
Run Code Online (Sandbox Code Playgroud)

使用一个程序,缓存会有所不同

创建程序

use test 
go
create procedure dbo.myproc @dbname varchar(255)
as
select * from sys.databases where name = @dbname 
Run Code Online (Sandbox Code Playgroud)

运行过程

exec dbo.myproc @dbname= 'master';
Run Code Online (Sandbox Code Playgroud)

缓存中的结果

select text from sys.dm_exec_query_stats
cross apply sys.dm_exec_sql_text(sql_handle)
where text like '%myproc%';
Run Code Online (Sandbox Code Playgroud)

在此处输入图片说明

或者

create procedure dbo.myproc @dbname varchar(255)  as  select * from sys.databases where name = @dbname 
Run Code Online (Sandbox Code Playgroud)

启用强制参数化时也会发生这种情况

启用强制参数化

ALTER DATABASE test SET PARAMETERIZATION FORCED
Run Code Online (Sandbox Code Playgroud)

相同的查询,不带参数

SELECT  *
FROM    Person.Person
WHERE   BusinessEntityID = 5
Run Code Online (Sandbox Code Playgroud)

缓存中的结果

select text from sys.dm_exec_query_stats
cross apply sys.dm_exec_sql_text(sql_handle)
where text like '%Person%'
Run Code Online (Sandbox Code Playgroud)

在此处输入图片说明 或者

(@0 int)select * from Person . Person where BusinessEntityID = @0
Run Code Online (Sandbox Code Playgroud)