存储过程中的组合搜索
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.
根据您的语法,您似乎正在使用 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_”(用户存储过程)。但不清楚前缀有多大用处,除非你特别喜欢输入这些字母。
我有几个搜索存储过程(按 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
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.
根据您的语法,您似乎正在使用 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_”(用户存储过程)。但不清楚前缀有多大用处,除非你特别喜欢输入这些字母。