5

我有一个客户,它由过去的开发人员执行过编程。他们的代码最近变得可疑,我想知道他们是否使用了参数化查询。我希望我可以通过 SQL Server 检测到非参数化请求,但我还没有找到一种方法来做到这一点。我了解并非所有查询都需要参数化,因为查询可能类似于

select count(*) from Customers

但是,如果 SQL Server 能够以编程方式告诉我哪些查询有任何字符串常量输入而不是参数输入,那就太好了。顺便说一句,记录所有 SQL 查询并删除所有带有 @ 符号的行是关闭的,但是下面的查询将被认为是合法的:

select * from Users where Username='user' and Password=@Password

所以我真的需要 SQL Server 读取命令的内容并确定所有输入是否都已参数化。谢谢你。

4

2 回答 2

2

事实上,您正在搜索即席查询(不是存储过程,也不是 sp_executesql)。

你可以先看看sys.dm_exec_cached_plansDMV:

SELECT
    CP.usecounts
    , CP.cacheobjtype
    , ST.text as sql_Statement    
    , QP.query_plan
FROM
    sys.dm_exec_cached_plans CP
    CROSS APPLY sys.dm_exec_sql_text(CP.plan_handle) ST
    CROSS APPLY sys.dm_exec_query_plan(CP.plan_handle) QP
WHERE
    ST.dbid = DB_ID()
    AND CP.objtype IN ( 'Adhoc')
ORDER BY
    CP.usecounts DESC

请注意,关系引擎可以参数化简单查询(称为简单参数化的功能),因此您可能有相同的行

如果您想通过不缓存即席查询的计划来提高性能,则有一个称为服务器选项的服务器选项optimize for ad hoc workloads,它向关系引擎发出信号,即在第一次执行查询时 => 存储计划的较轻版本(计划存根)。

计划缓存污染也可能是降低数据库性能的一个原因。检查此查询以检测是否也是您的情况。

于 2014-04-18T09:51:15.363 回答
0

Mihai 将您指向当前的系统对象,dm_exec_cached_plans. (当我查找您问题的答案时,我发现它[syscacheobjects]实际上已被弃用。)因此,我确实赞成他的回答。

但是,我仍然认为它可以节省您的时间,在WHERE. 使用dm_exec_cached_plans,这是一个类似的查询,使用WHERE我之前给你的类似查询:

SELECT usecounts, cacheobjtype, objtype, text
FROM sys.dm_exec_cached_plans 
    CROSS APPLY sys.dm_exec_sql_text(plan_handle) 
WHERE [text] LIKE '%WHERE%''%'
----AND [text] NOT LIKE '%sp_executesql%'  ----queries probably ok, with sp_executesql
----WHERE usecounts > 1   ----un-commenting this might also be interesting to check out. 
ORDER BY usecounts DESC;

或者,只需将其添加到 Mihai 的查询中:

SELECT
    CP.usecounts
    , CP.cacheobjtype
    , ST.text as sql_Statement    
    , QP.query_plan
FROM
    sys.dm_exec_cached_plans CP
    CROSS APPLY sys.dm_exec_sql_text(CP.plan_handle) ST
    CROSS APPLY sys.dm_exec_query_plan(CP.plan_handle) QP
WHERE
    CP.objtype = 'Adhoc'
    AND ST.dbid = DB_ID()
    AND ST.text LIKE '%WHERE%''%'
ORDER BY
    CP.usecounts DESC

请注意ORDER BY,基于常见查询导致频繁暴露的想法。但是您可能已经意识到……如果可疑代码自己构建查询字符串,那么唯一值(如行号或客户 ID 或订单号等)可能会产生唯一的查询,(如果它们是在不使用的情况下构建的)sp_executesql),实际上可能是重要的,即使它们有usecounts = 1.

至于您的问题的答案,(“SQL 查询何时从该表中删除?”):一旦缓存中有足够的查询导致“内存压力”,旧查询作为新查询从缓存中删除进来......当SQL重新启动时,所有这些都被清除了。(见http://www.sqlservercentral.com/Forums/Topic1375781-391-1.aspxhttp://technet.microsoft.com/en-us/library/ms181055%28v=sql.105%29.aspx

希望有帮助...

于 2014-04-18T17:18:57.217 回答