避免在返回搜索结果的存储过程中进行分支?

发布于 2024-09-06 18:13:54 字数 250 浏览 5 评论 0原文

我有一个应用程序需要从 SQL Server 2008 数据库返回搜索结果。我想使用单个存储过程来返回结果,但我发现当我构建存储过程时,它充满了许多 Else .. Else If 语句,其中的查询一遍又一遍地重复,根据用户的搜索略有不同标准。

有更好的方法来解决这个问题吗?我试图避免编写动态 SQL,因为我想要执行计划的好处,但我认为必须有更好的方法。有没有人有任何建议或示例来说明如何最好地设计一个必须处理许多搜索参数(其中许多可能为 NULL)的存储过程?谢谢。

I have an application that needs to return search results from a SQL Server 2008 database. I would like to use a single stored procedure to return the results but I am finding that as I build the stored procedure it is full of many Else .. Else If statements with the query repeated over and over with slight variations depending on the users search criteria.

Is there a better way to go about this? I am trying to avoid writing dynamic SQL because I would like the benefits of an execution plan but I am thinking there must be a better way. Does anyone have any suggestions or perhaps examples of how best to design a stored procedure that has to deal with many search parameters, many of which may be NULL? Thank you.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

乄_柒ぐ汐 2024-09-13 18:13:54

并不真地。

对于具有语句级重新编译的 SQL Server 2005 及更高版本,OR 子句的损失较小,只是维护复杂性。

使用 Richard Harrison 的方法会使情况变得更糟,因为 OR 不可控制,运行缓慢,很可能不会使用索引。

动态 SQL 带来了 SQL 注入、引用和缓存问题。

这使得 sp_executesql 按照 CountZero 的答案,仍然需要构建字符串。

该解决方案可能不是基于代码的...您真的需要一次搜索所有字段吗?我会尝试将搜索分为简单搜索和高级搜索,或者找出最常见的搜索并尝试涵盖这些查询。

Not really.

With SQL Server 2005 and above with statement level recompilation then there is less of a penalty with OR clauses, just maintenance complexity.

Using Richard Harrison's approach makes it worse because OR is not-sargable, runs slowly, most likely won't use indexes.

Dynamic SQL opens up SQL injection, quoting and caching issues.

This leaves sp_executesql as per CountZero's answer which still requires building up strings.

The solution may not be code based... do you really need to search on all fields at any one time? I'd try to split into simple and advanced searches, or work out what the most common are and try to cover these queries.

梅倚清风 2024-09-13 18:13:54

我总是通过使用默认值和条件来完成此操作;例如

CREATE PROCEDURE [dbo].[searchForElement]
(
    @Town     nvarchar(100) = '',
    @County   nvarchar(100) = '',
    @postcode nvarchar(100) = ''
)
AS
BEGIN
    SET NOCOUNT ON;

    SELECT <fields> 

    FROM table 
    WHERE 
        (@Town = ''             OR Town     LIKE '%'+@Town+'%')
        AND (@County = ''       OR County   LIKE '%'+@County+'%')
        AND (@postcode = ''     OR postcode LIKE '%'+@PostCode +'%')
END

编辑:

正如 @gbn 正确建议的那样,上述内容将导致索引扫描,这对于大型表来说可能是一个问题。如果这是一个问题,解决方案是下面使用 ISNULL ,并且将 NULL 添加到任何内容都会导致 NULL ,这将允许索引查找因为优化器可以理解“%”(在 SQL2008 上测试)。这可能可读性较差,但可以更好地利用索引。

CREATE PROCEDURE [dbo].[searchForElement]
(
    @Town     nvarchar(100) = NULL,
    @County   nvarchar(100) = NULL,
    @postcode nvarchar(100) = NULL
)
AS
BEGIN
    SET NOCOUNT ON;

    SELECT <fields> 

    FROM table 
    WHERE   Town     LIKE ISNULL('%'+@Town+'%', '%')
       AND  County   LIKE ISNULL('%'+@County+'%', '%')
       AND  Postcode LIKE ISNULL('%'+@PostCode +'%', '%')
END

I've always done this by using default values and conditions; e.g.

CREATE PROCEDURE [dbo].[searchForElement]
(
    @Town     nvarchar(100) = '',
    @County   nvarchar(100) = '',
    @postcode nvarchar(100) = ''
)
AS
BEGIN
    SET NOCOUNT ON;

    SELECT <fields> 

    FROM table 
    WHERE 
        (@Town = ''             OR Town     LIKE '%'+@Town+'%')
        AND (@County = ''       OR County   LIKE '%'+@County+'%')
        AND (@postcode = ''     OR postcode LIKE '%'+@PostCode +'%')
END

Edit:

As @gbn correctly advises the above will result in an index scan which may be a problem for large tables. If this is a problem the solution is to below using ISNULL and the fact that adding NULL to anything results in NULL it will allow an index seek because the '%' is understood by the optimiser (tested on SQL2008). This may be less readable but it makes better use of the indexes.

CREATE PROCEDURE [dbo].[searchForElement]
(
    @Town     nvarchar(100) = NULL,
    @County   nvarchar(100) = NULL,
    @postcode nvarchar(100) = NULL
)
AS
BEGIN
    SET NOCOUNT ON;

    SELECT <fields> 

    FROM table 
    WHERE   Town     LIKE ISNULL('%'+@Town+'%', '%')
       AND  County   LIKE ISNULL('%'+@County+'%', '%')
       AND  Postcode LIKE ISNULL('%'+@PostCode +'%', '%')
END
思慕 2024-09-13 18:13:54

我自己也经常遇到这个问题。倾向于使用动态SQL,只要使用sp_executesql那么优化器就会尝试使用相同的执行计划。

http://ayyanar.blogspot.com/2007/ 11/执行-和之间的性能差异.html

I always run into this problem myself. Tend to use dynamic SQL, as long as you use the sp_executesql then the optimizer will try to use the same execution plan.

http://ayyanar.blogspot.com/2007/11/performance-difference-between-exec-and.html

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文