1

我有一个存储过程,它采用相同的列但具有不同的WHERE子句。

像这样的东西。

SELECT
     alarms.startt, alarms.endt, clients.code, clients.Plant,
     alarms.controller, alarmtype.atype, alarmstatus.[text]
FROM alarms
INNER JOIN clients ON alarms.clientid = clients.C_id 
INNER JOIN alarmstatus ON alarms.statusid = alarmstatus.AS_id
INNER JOIN alarmtype ON alarms.typeid = alarmtype.AT_id

我将相同的查询放在 3 个 if(条件)中,其中WHERE子句根据传递给变量的参数而变化。

我是否必须为每个 if 中的每个条件一遍又一遍地写整个字符串?

或者我可以将它优化为一次,唯一会改变的是 WHERE 子句?

4

6 回答 6

2

如果您执行以下操作,则可以避免重复代码:

WHERE (col1 = @var1 AND @var1 IS NOT NULL)
OR ...
OPTION RECOMPILE;

您还可以通过数据库的参数化设置(简单与强制)对这种行为产生一些影响。

避免重复代码并避免由于参数嗅探而导致次优计划的方法是使用动态 SQL:

DECLARE @sql NVARCHAR(MAX) = N'SELECT ...';
IF @var1 IS NOT NULL
  SET @sql = @sql + ' WHERE ...';

如果您启用了服务器设置“针对临时查询进行优化”,这可能会更好。

于 2012-06-20T17:18:55.663 回答
2

你不必这样做,你可以通过做类似的事情来解决它

SELECT  *
FROM    [Query]
WHERE   (@Parameter = 1 AND Column1 = 8)
OR      (@Parameter = 2 AND Column2 = 8)
OR      (@Parameter = 3 AND Column3 = 8)

但是,仅仅因为您可以做某事,并不意味着您应该做某事。不太冗长的 SQL 并不意味着更好的性能,所以使用类似的东西:

IF @Parameter = 1
    BEGIN
        SELECT  *
        FROM    [Query]
        WHERE   Column1 = 8
    END
ELSE IF @Parameter = 2
    BEGIN
        SELECT  *
        FROM    [Query]
        WHERE   Column2 = 8
    END
ELSE IF @Parameter = 3
    BEGIN
        SELECT  *
        FROM    [Query]
        WHERE   Column3 = 8
    END

虽然等效于第一个查询应该会产生更好的性能,因为它将被更好地优化。

于 2012-06-20T16:57:00.400 回答
1

因为没有人提出这个建议。您可以将原始查询放在一个视图中,然后使用不同的 WHERE 子句访问该视图。

为了提高性能,如果您知道 WHERE 子句中常​​用的列,您甚至可以向视图添加索引(查看http://msdn.microsoft.com/en-us/library/dd171921(v=sql. 100).aspx )。

于 2012-06-20T18:05:58.537 回答
1

我可能会坚持重复整个 SQL 语句,但过去曾诉诸于此……

WHERE (@whichwhere=1 AND mytable.field1=@id)
  OR (@whichwhere=2 AND mytable.field2=@id)
  OR (@whichwhere=3 AND mytable.field3=@id)

不是特别可读,如果它很慢,您将不得不检查执行计划,但它可以防止您重复代码。

于 2012-06-20T16:57:14.233 回答
0

就像 SQL 中的大多数东西一样:这取决于。这里有一些考虑。

  • 不同的 WHERE 是否会导致执行的查询计划大不相同,例如索引的列之一而不是其他两个
  • 查询是否可能随时间而改变:即需要其他列的客户需求
  • WHERE 是否可能变成 4,然后是 8,然后是 16 等选项。

一种方法是将不同的过程执行到临时表中。然后每个 proc 将有自己的查询计划。

另一种方法是使用动态 SQL,再次为每个“查询”分配自己的计划。

第三种方法是编写一个为每个选项生成 SQL 的应用程序,这可以是存储的过程或 sql 字符串。

然后拥有一个数据集并针对它进行测试驱动开发(每种方法都是如此)。

最后,最好的学习解决方案可能是 a) 阅读 SQL Kalen Delaney Inside SQL 是一位公认的专家。b) 根据您自己的数据测试您自己的解决方案

于 2012-06-20T17:17:25.693 回答
0

我会这样: WHERE 8 = CASE @parameter WHEN 1 THEN Column1 WHEN 2 THEN Column2 。. .

于 2015-11-20T18:02:47.567 回答