【问题标题】:Multiple Parameter Search in SQL Server 2000SQL Server 2000 中的多参数搜索
【发布时间】:2009-02-10 22:34:31
【问题描述】:

我在 Visual Basic .Net 应用程序中有一个搜索屏幕,其中包含以下文本框:

  1. 名字 Varchar(50)
  2. 姓氏 Varchar(50)
  3. 中间名 Varchar(50)
  4. 出生日期时间
  5. 家庭电话 Varchar(10)
  6. 工作电话 Varchar(10)

如何在 SQL Server 2000 中创建一个存储过程,使我能够搜索所有/某些/一个字段。如果用户只输入名字和家庭电话号码的数据,我需要为未输入数据的其余参数做什么。我尝试了下面的 select 语句,但它不能正常工作。

    Select Last_Name, First_Name, Mid_Name, DOB, Home_Phone, Work_Phone from dbo.tblClient
Where Last_Name Like '%@LastName' and
    First_Name Like '%@FirstName' and
    Mid_Name Like '%@MiddleName' and
    DOB Like '%DOB' and
    Home_Phone Like '%@HomePhone' and
    Work_Phone Like '%@WorkPhone'

【问题讨论】:

    标签: sql sql-server vb.net


    【解决方案1】:

    我经常使用这种模式:

    Select Last_Name, First_Name, Mid_Name, DOB, Home_Phone, Work_Phone from dbo.tblClient
    Where (@LastName is null or Last_Name Like '%'+ @LastName)
    and (@FirstName is null or First_Name Like '%'+ @FirstName)
    and (@HomePhone is null or Home_Phone Like '%'+ @HomePhone)
    -- etc...
    

    它将忽略任何未提供的内容,同时仍提供良好的性能。更好的是,它不需要借助动态 SQL 来实现。

    【讨论】:

    • 多年来我一直在做同样的事情。另一件事是在 order by 子句中使用 CASE 语句进行动态排序,无需动态 sql。
    【解决方案2】:

    快速而肮脏的解决方案。

    Select Last_Name, First_Name, Mid_Name, DOB, Home_Phone, Work_Phone from dbo.tblClient
    Where (Last_Name Like '%' + @LastName OR @LastName Is Null) and
    (First_Name Like '%' + @FirstName OR @FirstName Is Null) and
    (Mid_Name Like '%' + @MiddleName OR @MiddleName Is Null) and
    (DOB Like '%' + @DOB OR @DOB Is Null) and
    (Home_Phone Like '%' + @HomePhone OR @HomePhone Is Null and
    (Work_Phone Like '%' + @WorkPhone OR @WorkPhone Is Null)
    

    注意我已经更正了参数的使用。难道你不想在参数的另一边也有一个通配符吗?此外,您真的会使用 Like to a Date of Birth 字段吗?

    这在大桌子上表现不佳。一个性能更高的解决方案是使用 Where 子句中的必填字段来构造 SQL。

    【讨论】:

      【解决方案3】:

      快速的方法是这样的

      在哪里(Last_Name Like @LastName + '%' OR @LastName IS NULL)和 (First_Name Like @FirstName + '%' OR @FirstName IS NULL)和 等等……

      Erland Sommarskog 有一些很棒的文章,介绍了执行此操作的不同方法及其对性能的影响here

      【讨论】:

      • 您可能希望在此处翻转 OR 的顺序,否则您最终会在测试是否存在之前执行查找。充其量它会很慢。更有可能的是,它会简单地抛出。
      • @Jason:我怀疑这很重要(忽略语法错误),@LastName 为空,表达式变为(Last_Name Like Null OR Null Is Null),重新排序 OR 的操作数(即使假设SQL 2000 捷径)几乎不会产生任何影响。
      • 我不认为 SQL 真的让我们在这种情况下决定评估的顺序。由于评估变量的成本非常小,优化器会在决定是否将其与列进行比较之前自行评估它(将其视为常量)。
      【解决方案4】:

      在您的存储过程或 VB 中,您将不得不决定如何处理无输入。例如我使用:

      IF ltrim(rtrim(@FirstName)) = ''
      SET @FirstName = null
      

      ...在我的存储过程中。您可能必须尝试使用​​ OR 而不是 AND。您基本上是在告诉您的查询,您必须使用 AND 满足所有这些条件,无论没有任何输入可通过。

      【讨论】:

        【解决方案5】:

        如何使用 ISNULL() 函数来确定一个值是否已传递到存储过程中,如果没有,设置 WHERE 子句字段值以在每种情况下搜索等于自身(如果有人能想到一个更好的描述这个词的选择,我会更新答案)。

         SELECT 
             Last_Name, 
             First_Name, 
             Mid_Name, 
             DOB, 
             Home_Phone, 
             Work_Phone 
         FROM 
             dbo.tblClient
         WHERE 
            Last_Name LIKE '%' + ISNULL(@LastName, Last_Name) AND
            First_Name LIKE '%' + ISNULL(@FirstName, First_Name) AND
            Mid_Name LIKE '%' ISNULL(@MiddleName, Mid_Name) AND
            DOB LIKE '%' + ISNULL(@DOB, DOB) AND
            Home_Phone LIKE '%' + ISNULL(@HomePhone, Home_Phone) AND
            Work_Phone LIKE '%' + ISNULL(@WorkPhone, Work_Phone) 
        

        您还可以为每个存储过程参数设置 NULL 默认值。

        【讨论】:

        • 我希望有人能解决此建议的性能问题。这很聪明,但我敢打赌 Jason 的答案要快得多,因为没有进行记录比较。
        • 我会看看我是否可以对大量数据进行一些测试。我怀疑你对 Jason 的表现可能是正确的
        • 在这里简单地阅读 Erland Sommarskog 的文章 - sommarskog.se/dyn-search-2005.html 并且似乎这种技术产生了好坏参半的结果(他使用了 coalesce 而不是 isnull)。这种技术在 SQL Server 2005 中比 Jason 的慢,但在 SQL Server 2000 中更快!
        【解决方案6】:

        只是为了澄清为什么您的原始 SQL 不起作用;

        您需要将 % 通配符连接到参数值,但您编写的是创建一个包含通配符和参数名称的文字字符串,例如

        Work_Phone Like '%@WorkPhone'

        应该写成

        Work_Phone Like '%' + @WorkPhone

        如果您为没有输入值的参数返回一个空字符串(即您返回“”,而不是 NULL),您拥有的 SQL 应该可以工作 - 这些字段的 Like 比较将只包含% 通配符(即匹配任何值)。但是,这不是很有效,因为理想情况下您只想对用户输入值的字段进行比较。这可能需要一些动态生成的 SQL,如 kenj 链接的文章所示。

        如果您的 tblClient 表不是那么大,那么您所做的可能就足够了。

        【讨论】:

          猜你喜欢
          • 2011-04-12
          • 2011-03-28
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2017-03-20
          • 1970-01-01
          • 1970-01-01
          • 2012-09-14
          相关资源
          最近更新 更多