Fünf Jahre zu spät zur Party.
Es ist in den angegebenen Links der akzeptierten Antwort erwähnt, aber ich denke, dass es eine explizite Antwort auf SO verdient - dynamische Erstellung der Abfrage basierend auf bereitgestellten Parametern. Z.B .:
Setup-
-- 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
Verfahren
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
Nutzungs
exec spDoSearch @TopCount = 3
exec spDoSearch @FirstName = 'Dick'
Pro:
- leicht
- Flexibilität zu schreiben und zu verstehen - leicht die Abfrage für trickier Filterungen erzeugen (z dynamische TOP)
Nachteile:
- mögliche Performance-Probleme auf bereitgestellt Parameter abhängig, Indizes und Datenvolumen
keine direkte Antwort, aber das Problem auch bekannt als das große Bild im Zusammenhang
Normalerweise werden diese gespeicherten Filterprozeduren nicht umherschweben, sondern von einer bestimmten Dienstschicht aufgerufen. Dadurch bleibt die Möglichkeit bestehen, die Geschäftslogik (Filterung) von SQL in die Serviceebene zu verschieben.
Ein Beispiel wird unter Verwendung von LINQ2SQL die Abfrage zu erzeugen, basierend auf bereitgestellt Filter:
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;
}
Pro:
- dynamisch generierte Abfrage basierend auf Filter vorgesehen.Keine parameter sniffing oder recompile Hinweise benötigten
- etwas leichter für die in der OOP Welt
- typischerweise -leistung freundlich, da „einfache“ Abfragen ausgegeben werden, um zu schreiben (entsprechende Indizes sind allerdings noch erforderlich)
Nachteile:
- LINQ2QL Einschränkungen erreicht werden können, und eine Herabstufung auf LINQ2Objects zwingen oder zurück zur reinen SQL-Lösung gehen, je nach Fall
- unvorsichtig Schreiben von LINQ könnte schreckliche Abfragen generieren (oder viele Abfragen, wenn Navigationseigenschaften geladen)
Werfen Sie einen Blick hier: http://stackoverflow.com/questions/11396919/building-dynamic-where-clause -in-stored-procedure/25473624 # 25473624 –
Versuchen Sie, folgende Anweisung zu folgen: 'code' ISNULL (Vorname, ') = ISNULL (@FirstName,' ') - dies wird jede NULL zu einer leeren Zeichenfolge und diese kann über Gl. Operator. Wenn Sie alle Titel erhalten möchten, wenn der Eingabeparameter null ist, versuchen Sie Folgendes: 'code'FirstName = @FirstName ODER @FirstName IS NULL. – baHI