存储过程中的组合搜索

Combination Search in Stored Procedure

我有几个搜索存储过程(按 EmpName、按 EmpCode、按部门),

按名称搜索:

ALTER  PROCEDURE [dbo].[spEmployee_SearchByName]
    @EmpName nvarchar(100)
AS
BEGIN

    SELECT *
    
    FROM Employee

    WHERE EmployeeName like '%'+ @EmpName +'%'

END

按 EmpID 搜索:

ALTER   PROCEDURE [dbo].[spEmployee_SearchByID]
    @EmpID nvarchar(200)
AS
BEGIN

    SELECT *
    
    FROM Employee

    WHERE EmployeeID like '%'+ @EmpID +'%'

END

按部门搜索(我在 C# 中使用组合框来获取此值):

ALTER   PROCEDURE [dbo].[spEmployee_SearchByName]
    @EmpDepartment nvarchar(100)
AS
BEGIN

    SELECT *
    
    FROM Employee

    WHERE EmployeeDepartment like '%'+ @EmpDepartment +'%'

END

我正在使用 Microsoft SQL 服务器。

应用程序:

我的 C# 应用程序有 3 个搜索选项、2 个文本框(EmpName 和 EmpCode)和 1 个组合框(部门)。

我如何使用搜索选项:

首先,我将table按部门排序,然后输入一些EmpCode,如16xxxx。它将显示插入部门和 EmpCode 的大约 200 个结果,然后我将通过 EmpName 缩小范围。此外,我可以通过首先使用 EmpName 对 table 进行排序,然后是 Department,然后是 EmpCode。

问题:

比方说,我先按 Department 对 table 进行排序,然后是 EmpName 和 EmpCode。当我清除 EmpName(保留 Department 和 EmpCode)时,它应该清除 EmpName 的搜索并将结果返回为仅对 Department 和 EmpCode 进行排序,但事实并非如此。它给了我一个随机结果。此外,当我有 3 个搜索选项时 cleared/empty,它也会给我一个随机结果。

当我尝试使用 AND 将所有这些搜索 SP 组合成一个 SP 时出现问题,例如:

SELECT *

FROM Employee

WHERE EmployeeDepartment like '%'+ @EmpDepartment +'%' AND EmployeeName like '%'+ @EmpName +'%' AND EmployeeID like '%'+ @EmpID +'%'

将所有这些搜索 SP 组合到一个存储过程的正确方法是什么?

您可以将所有 3 个搜索组合在一个存储过程中,使用 3 个参数并在 where 条件 or 中使用

ALTER PROCEDURE [dbo].[spEmployee_SearchByName] 
@EmpName nvarchar(100),
@EmpID nvarchar(200),
@EmpDepartment nvarchar(100)
AS BEGIN

SELECT *
FROM Employee
WHERE (EmployeeName like '%'+ @EmpName +'%' or @EmpName is NULL) AND
(EmployeeID like '%'+ @EmpID +'%' or @EmpID is NULL) AND
(EmployeeDepartment like '%'+ @EmpDepartment +'%' or @EmpDepartment is NULL)
END

这里的技巧是,如果您想使用 EmployeeName 进行搜索,请将 value 传递给 @EmpName,然后将 NULL 发送给 @EmpId@EmpDepartment.如果您想使用 EmpId 进行搜索,请为 @EmpID 参数传递该值,并为 @EmpName@EmpDepartment 发送 NULL。为了解释这一点,当您为非搜索参数条件发送 NULL 时,or 逻辑的条件将变为 NULL is NULL,这始终为真。

是的,您可以在一个过程中完成。如果这是 mysql,请尝试将 like '%'+ @EmpName +'%' 更改为 LIKE CONCAT('%', @EmpName, '%')

ALTER  PROCEDURE [dbo].[spEmployee_Search]
    @EmpName nvarchar(100),
    @EmpID nvarchar(200),
    @EmpDepartment nvarchar(100)
AS
BEGIN
    SELECT * FROM Employee
    WHERE (EmployeeName like CONCAT('%', @EmpName, '%')) or
    (EmployeeID like CONCAT('%', @EmpID, '%')) or
    (EmployeeDepartment like CONCAT('%', @EmpDepartment, '%'))
END

或者像这样通过使用 CONCAT_WS

对 WHERE 块进行分组
ALTER  PROCEDURE [dbo].[spEmployee_Search]
    @SearchValue nvarchar(100)
AS
BEGIN
    SELECT * FROM Employee
    WHERE CONCAT_WS(' ', EmployeeName, EmployeeID, EmployeeDepartment) 
    LIKE CONCAT('%', @SearchValue, '%')
END

The CONCAT_WS() function adds two or more expressions together with a separator.

W3 Schools - MySQL CONCAT_WS() Function

根据您的语法,您似乎正在使用 SQL 服务器。此外,如果需要,您还没有指定如何仅在一列上进行搜索。一个典型的解决方案是对其他搜索值使用 NULL,表明它们将被忽略。

为避免 NULL 出现问题,您可以使用 CONCAT() 函数。此函数忽略 NULL 值,而 + returns NULL 如果任何值是 NULL:

ALTER PROCEDURE [dbo].[spEmployee_SearchByName] (
    @EmpName nvarchar(100),
    @EmpID nvarchar(200),
    @EmpDepartment nvarchar(100)
) AS
BEGIN
    SELECT e.*
    FROM Employee e
WHERE e.EmployeeName LIKE CONCAT('%', @EmpName ,'%') AND
      e.EmployeeID LIKE CONCAT('%', @EmpID, '%') AND
      e.EmployeeDepartment LIKE CONCAT('%', @EmpDepartment, '%');
END;

关于您所采用的方法的一些评论。首先,因为 LIKE 模式开头有通配符,所以无法优化此查询。它将进行完整的 table 扫描。为了提高性能,您可能需要查看数据库中的全文搜索功能。

其次,我发现 table 值函数比“参数化视图”的存储过程方便得多。然后您可以在其他查​​询中使用结果。

第三,不要在存储过程中使用“sp”前缀。这与sp_非常接近,SQL服务器使用它来区分系统存储过程。如果您必须有前缀,请使用不同的东西,例如“usp_”(用户存储过程)。但不清楚前缀有多大用处,除非你特别喜欢输入这些字母。