2009-02-17 7 views
1

J'ai un écran de recherche sur lequel l'utilisateur peut spécifier n'importe quelle combinaison de prénom, nom, semestre ou cours. Je ne sais pas comment coder de façon optimale la procédure stockée SQL Server 2005 pour gérer ces paramètres potentiellement facultatifs. Quel est le moyen le plus efficace? Procédures distinctes pour chaque combinaison? Prendre les éléments comme des valeurs nulles et construire un SQL dynamique?Codage de la procédure stockée pour l'écran de recherche avec plusieurs critères optionnels

Répondre

3

La meilleure solution consiste à utiliser sp_execute_sql. Par exemple:

--BEGIN SQL 
declare @sql nvarchar(4000) 

set @sql = 
'select * from weblogs.dbo.vwlogs 
where Log_time between @BeginDate and @EndDate' 
+ case when @UserName is null then '' else 'and client_user = @UserName' end 

sp_execute_sql 
@sql 
, @params = '@UserName varchar(50)' 
, @UserName = @UserName 
--END SQL 

Comme mentionné muerte, cela aura un avantage de performance par rapport à exec() 'ing une déclaration similaire.

+0

Comment ce changement si j'avais les paramètres suivants: 1. Lastname (opérateur LIKE) 2. Cours (pas ETC.) 3. L'article (pas ETC.) Avec tous intacts, ce serait: SELECT * FROM courseEnrollment où Nom de famille comme 'Bob%' et cours = '100' et section = '001' – Caveatrob

+0

Modifiez la partie "client_user = @UserName" pour indiquer la condition réelle que vous souhaitez ajouter à votre requête. –

0

Je le ferais avec sp_executesql parce que le plan sera mis en cache juste pour le premier modèle, ou le premier ensemble de conditions.

Jetez un oeil à ce TechNet article:

sp_executesql peut être utilisé à la place des procédures stockées pour exécuter une instruction Transact-SQL à plusieurs reprises lorsque le changement des valeurs de paramètre à l'instruction est la seule variation. Étant donné que l'instruction Transact-SQL elle-même reste constante et que seules les valeurs de paramètre changent, l'optimiseur de requête SQL Server est susceptible de réutiliser le plan d'exécution qu'il génère pour la première exécution.

+0

Si vous utilisez sp_executesql, vous devez vous assurer que vous n'introduisez aucun problème d'injection SQL. –

+0

Donc, votre réponse est "dynamique SQL" alors. –

+0

Pas nécessairement - la question était pour la solution de procédure stockée, et il pourrait y avoir une logique supplémentaire avant sp_executesql. Bottom line, la vraie réponse est que l'on devrait essayer d'éviter de vérifier les valeurs NULL pour chaque paramètre, au moins pour des raisons de performance. – muerte

7

Je mets chaque paramètre à option (valeur par défaut étant null)

puis la Abordez la OU ....

FirstName=ISNULL(@FirstName,FirstName) 
AND 
LastName=ISNULL(@LastName,LastName) 
AND 
SemesterID=ISNULL(@SemesterID,SemesterID) 

Ça va gérer uniquement le prénom Il est également beaucoup plus joli/manageable/robuste que la construction dynamique de la chaîne SQL et l'exécution de celle-ci.

+0

Je suis d'accord, c'est plus lisible, mais le plan sera mis en cache juste pour le premier modèle, donc si les performances sont problématiques, l'exécution de SQL dynamique pourrait être une meilleure solution. – muerte

+0

+ 1 Je ferais de même, mais utilisez la syntaxe (@Paremeter est nulle ou Column = @Paremeter) – cmsjr

+0

Jusqu'à ce que vous commenciez à aller vers la direction des paramètres déterminant les jointures que vous utilisez, cette méthode est encore assez bonne sur les performances, @ muerte Et, en règle générale, les performances sont consomptibles - la maintenabilité/la lisibilité ne l'est pas;) –

0

Je publiais juste le même concept que Kevin Fairchild, c'est ainsi que nous le traitons généralement.

Vous pouvez faire dynamique SQL dans votre code pour créer l'instruction si nécessaire, mais si c'est le cas, vous devez surveiller l'injection de SQL.

0

Comme le souligne muerte, le plan sera mis en cache pour le premier ensemble de paramètres. Cela peut entraîner de mauvaises performances lors de son exécution à chaque fois en utilisant d'autres paramètres. Pour résoudre cela, utilisez l'option WITH RECOMPILE de la procédure.

Questions connexes