【问题标题】:Combination Search in Stored Procedure存储过程中的组合搜索
【发布时间】:2021-10-11 20:17:13
【问题描述】:

我有几个搜索存储过程(按 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 Server。

应用程序:

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

我如何使用搜索选项:

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

问题:

假设,我首先使用 Department 对表进行排序,然后是 EmpName 和 EmpCode。当我清除 EmpName(Department 和 EmpCode 保留)时,它应该清除 EmpName 的搜索并将结果返回为仅对 Department 和 EmpCode 进行排序,但它没有。它给了我一个随机的结果。此外,当我清除/清空 3 个搜索选项时,它也会给我一个随机结果。

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

SELECT *

FROM Employee

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

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

【问题讨论】:

  • 我已经编辑了我的问题

标签: c# sql sql-server search stored-procedures


【解决方案1】:

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

为避免NULL 出现问题,您可以使用CONCAT() 函数。此函数忽略 NULL 值,而 + 返回 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;

关于您正在采取的方法的几个 cmets。首先,因为LIKE 模式的开头有通配符,所以无法优化此查询。它将进行全表扫描。为了提高性能,您可能需要查看数据库中的全文搜索功能。

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

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

【讨论】:

    【解决方案2】:

    您可以在一个存储过程中将所有 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 参数,然后发送NULL 以获得@EmpName@EmpDepartment 。为了解释这一点,当您为非搜索参数条件发送 NULL 时,or 逻辑的条件将变为 NULL is NULL,这始终为真。

    【讨论】:

    • 这是不正确的“NULL=NULL,它总是正确的。”你的意思不是NULL is NULL,正如你的代码所暗示的那样吗?
    • 是的,它应该是NULL is NULL,它在mssql 中工作正常,但我不确定Mysql。我已经编辑了我的答案。
    • 谢谢,我试过了,但对我来说效果不佳...我已经编辑了我的问题。
    【解决方案3】:

    是的,您可以在一个过程中做到这一点。如果这是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
    

    CONCAT_WS() 函数将两个或多个表达式与分隔符相加。

    W3 Schools - MySQL CONCAT_WS() Function

    【讨论】:

    • 谢谢,我试过了,但它对我不起作用......我已经编辑了我的问题
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-11-05
    • 1970-01-01
    • 2011-06-29
    • 2011-06-03
    • 1970-01-01
    • 2013-01-20
    相关资源
    最近更新 更多