如何构建一个Select存储过程来处理来自表的任何请求?

时间:2009-09-24 18:52:50

标签: sql-server-2005 stored-procedures

我想为SQL 2005构建一个单独的选择存储过程,该过程对于该表上的任何选择查询都是通用的。

**Columns**
LocationServiceID
LocationID
LocationServiceTypeID
ServiceName
ServiceCode
FlagActive

对于此表,我可能需要通过LocationServiceID,LocationID,或LocationServiceTypeID或ServiceName或上述的组合进行选择。

我宁愿每个人都没有单独的存储过程。

我认为最好的方法是在NOT NULL上构建'WHERE'语句。像

这样的东西
SELECT * FROM LocationServiceType WHERE

  IF @LocationID IS NOT NULL (LocationID = @LocationID)
  IF @LocationServiceID IS NOT NULL (LocationServiceID = @LocationServiceID)
  IF @LocationServiceTypeID IS NOT NULL (LocationServiceTypeID = @LocationServiceTypeID)
  IF @ServiceName IS NOT NULL (ServiceName = @ServiceName)
  IF @ServiceCode IS NOT NULL (ServiceCode = @ServiceCode)
  IF @FlagActive IS NOT NULL (FlagActive = @FlagActive)

这有意义吗?

4 个答案:

答案 0 :(得分:3)

这是我见过的关于这个主题的最广泛的文章:

Dynamic Search Conditions in T-SQL by Erland Sommarskog

这是文章的大纲:

 Introduction
      The Case Study: Searching Orders
      The Northgale Database
   Dynamic SQL
      Introduction
      Using sp_executesql
      Using the CLR
      Using EXEC()
      When Caching Is Not Really What You Want
   Static SQL
      Introduction
      x = @x OR @x IS NULL
      Using IF statements
      Umachandar's Bag of Tricks
      Using Temp Tables
      x = @x AND @x IS NOT NULL
      Handling Complex Conditions
   Hybrid Solutions – Using both Static and Dynamic SQL
      Using Views
      Using Inline Table Functions
   Conclusion
   Feedback and Acknowledgements
   Revision History

答案 1 :(得分:3)

首先,您的代码无效。它应该是这样的:

SELECT * FROM LocationServiceType WHERE
(@LocationID IS NULL OR (LocationID = @LocationID)
... -- all other fields here

这完全有效,称为“一体化查询”。但是从性能的角度来看,只要您不允许SQL Server选择最佳计划,这就不是一个完美的解决方案。您可以查看更多详细信息here

底线:如果您的首要任务是“单个SP”,那么请使用此方法。如果您关心性能,请寻找其他解决方案。

答案 2 :(得分:1)

SELECT * 
FROM LocationServiceType
WHERE LocationServiceID = ISNULL(@LocationServiceID,LocationServiceID)
  AND LocationID = ISNULL(@LocationID,LocationID)
  AND LocationServiceTypeID = ISNULL(@LocationServiceTypeID,LocationServiceTypeID)
  AND ServiceName = ISNULL(@ServiceName,ServiceName)
  AND ServiceCode = ISNULL(@ServiceCode,ServiceCode)
  AND FlagActive = ISNULL(@FlagActive,FlagActive)

如果在其中发送空值将取消where子句的那一行,否则它将返回与发送的值匹配的行。

答案 3 :(得分:0)

我一直在做的是将传入参数设置为null,如果在查询中应该忽略 然后首先检查变量是否为null,因此如果变量为null,则不应用短路和过滤器。如果变量有值,那么'或'会导致使用过滤器。到目前为止对我有用。

SET @LocationID = NULLIF(@LocationID, 0)
SET @LocationServiceID = NULLIF(@LocationServiceID, 0)
SET @LocationServiceTypeID = NULLIF(@LocationServiceTypeID, 0)


    SELECT * FROM LocationServiceType WHERE

      (@LocationID IS NULL OR LocationID = @LocationID)
     AND (@LocationServiceID IS NULL OR LocationServiceID = @LocationServiceID)
     AND (@LocationServiceTypeID IS NULL OR @LocationServiceTypeID = @LocationServiceTypeID)

等...