2009-02-10 107 views
1

我有一个Visual Basic .NET应用程序的搜索屏幕具有文本框:多参数搜索2000

  1. 名VARCHAR(50)
  2. 姓VARCHAR(50)
  3. 中间名VARCHAR(50)
  4. DOB的DateTime
  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' 

回答

3

我使用这个模式很多:

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来实现它。

0

快速的方法来做到这一点会是这样的

凡(姓氏LIKE @LastName + '%' 或@LastName IS NULL)和 (如同将First_Name + @firstName '%' OR @名字IS NULL)和 等等

厄兰Sommarskog有不同的方法来做到这一点,一些伟大的文章其性能影响here

+0

您可能想要翻转您的ORs的顺序,或者在测试存在之前最终执行查找。充其量只会是狗慢。更可能的是,它会简单地抛出。 – 2009-02-10 22:45:34

+0

@Jason:对于@LastName为null表达式变为(Last_Name为Null或Null Is Null),重新排序OR操作数(甚至假定SQL 2000的捷径)几乎是不可能的(忽略语法错误)会有所作为。 – AnthonyWJones 2009-02-10 22:54:58

+0

我不认为SQL真的让我们决定在这种情况下的评估顺序。由于评估变量的成本非常小,因此优化程序会在决定是否将其与列进行比较之前自行评估(将其视为常量)。 – KenJ 2009-02-10 22:55:48

0

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

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

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

0

快速肮脏的解决方案。

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。

0

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

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

Work_Phone Like '%@WorkPhone'

应该写成

Work_Phone Like '%' + @WorkPhone

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

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

0

如何使用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默认值。