晚了五年。
在提供的接受答案的链接中提到了它,但我认为它应该在SO上得到明确的答案 - 根据提供的参数动态构建查询。例如: -
设置
-- drop table Person
create table Person
(
PersonId INT NOT NULL IDENTITY(1, 1) CONSTRAINT PK_Person PRIMARY KEY,
FirstName NVARCHAR(64) NOT NULL,
LastName NVARCHAR(64) NOT NULL,
Title NVARCHAR(64) NULL
)
GO
INSERT INTO Person (FirstName, LastName, Title)
VALUES ('Dick', 'Ormsby', 'Mr'), ('Serena', 'Kroeger', 'Ms'),
('Marina', 'Losoya', 'Mrs'), ('Shakita', 'Grate', 'Ms'),
('Bethann', 'Zellner', 'Ms'), ('Dexter', 'Shaw', 'Mr'),
('Zona', 'Halligan', 'Ms'), ('Fiona', 'Cassity', 'Ms'),
('Sherron', 'Janowski', 'Ms'), ('Melinda', 'Cormier', 'Ms')
GO
程序
ALTER PROCEDURE spDoSearch
@FirstName varchar(64) = null,
@LastName varchar(64) = null,
@Title varchar(64) = null,
@TopCount INT = 100
AS
BEGIN
DECLARE @SQL NVARCHAR(4000) = '
SELECT TOP ' + CAST(@TopCount AS VARCHAR) + ' *
FROM Person
WHERE 1 = 1'
PRINT @SQL
IF (@FirstName IS NOT NULL) SET @SQL = @SQL + ' AND FirstName = @FirstName'
IF (@LastName IS NOT NULL) SET @SQL = @SQL + ' AND FirstName = @LastName'
IF (@Title IS NOT NULL) SET @SQL = @SQL + ' AND Title = @Title'
EXEC sp_executesql @SQL, N'@TopCount INT, @FirstName varchar(25), @LastName varchar(25), @Title varchar(64)',
@TopCount, @FirstName, @LastName, @Title
END
GO
使用
exec spDoSearch @TopCount = 3
exec spDoSearch @FirstName = 'Dick'
优点:
- 容易编写和理解
- 弹性 - 易于产生用于棘手的滤波查询(例如动态TOP)
缺点:
没有直接回答问题,而是涉及到问题又名大画面
通常,这些过滤存储过程不会浮动,而是从某个服务层调用。这留下了将业务逻辑(过滤)从SQL移到服务层的选项。基于所提供的过滤器
- 动态生成的查询:
一个实例是使用LINQ2SQL成基于提供的滤光器的查询:
public IList<SomeServiceModel> GetServiceModels(CustomFilter filters)
{
var query = DataAccess.SomeRepository.AllNoTracking;
// partial and insensitive search
if (!string.IsNullOrWhiteSpace(filters.SomeName))
query = query.Where(item => item.SomeName.IndexOf(filters.SomeName, StringComparison.OrdinalIgnoreCase) != -1);
// filter by multiple selection
if ((filters.CreatedByList?.Count ?? 0) > 0)
query = query.Where(item => filters.CreatedByList.Contains(item.CreatedById));
if (filters.EnabledOnly)
query = query.Where(item => item.IsEnabled);
var modelList = query.ToList();
var serviceModelList = MappingService.MapEx<SomeDataModel, SomeServiceModel>(modelList);
return serviceModelList;
}
优点。没有parameter sniffing或recompile提示需要
- 比较容易写那些在OOP世界
- 通常表现友好,因为“简单”的查询将发行(适当的索引仍需要虽然)
缺点:
- LINQ2QL限制可能达到并强制降级到LINQ2Objects或根据情况要回纯SQL解决方案
- LINQ的粗心写作可能会产生可怕的查询(或许多查询,如果导航属性加载)
看一看这里: http://stackoverflow.com/questions/11396919/building-dynamic-where-clause在存储过程/ 25473624#25473624 – 2014-09-03 12:24:54
请尝试以下语句: 'code' ISNULL(FirstName,')= ISNULL(@FirstName,'') - 这将使每个NULL 为空字符串,可以通过等式进行比较。运营商。 如果你想获得所有标题如果输入参数为空,然后尝试这样的事情: 'code'FirstName = @FirstName或@FirstName IS NULL。 – baHI 2016-01-13 10:58:18