在sql查询中使用局部变量作为开关是不好的做法

Posted

技术标签:

【中文标题】在sql查询中使用局部变量作为开关是不好的做法【英文标题】:Is it bad practice to use local variables as switches in sql queries 【发布时间】:2016-02-23 21:30:58 【问题描述】:

我在存储过程中有一个动态 sql 查询,我应该将其转换为表值函数 (TVF)。 正在使用如下代码构建字符串:

 Declare @str = 'select * from tableName where table = ''words'''
 If @flag = 'ONE'
      set @str = @str + 'AND year_id = '+@year_id
 ELSE
 If @flag = 'TWO'
      set @str = @str + 'AND record_id = '+@record_id

 set @str = @str + 'order by year_id, record_id'
 exec (@str)

在 TVF 中,您无法运行插入语句,因此您无法将此 exec 查询的结果返回给用户(至少据我所知,请随时纠正我)。

为了绕过这个限制,我创建了一个过滤器,该过滤器仅在局部变量具有给定值时应用。

select * 
from tableName 
where table = 'words'
AND (
     (@flag = 'ONE' and year_id = @year_id)
    OR (@flag = 'TWO' and record_id = @record_id)
    )
Order by year_id, record_id

现在,这似乎适用于更简单的查询,但对于更复杂的查询,您需要为每个可能的动态 sql 字符串组合创建一个条件。

除此限制外,以这种方式编写查询是否存在任何安全和/或性能风险?有没有更简单的方法来为 TVF 编写这样的查询?

【问题讨论】:

为什么不创建两个函数,每个标志一个?这可能会让您获得最佳性能。 我的查询实际上有 8 种不同的可能性。对于大致相同的查询有 8 个不同的函数对我来说似乎很笨重(并且维护容易出错)。现有报表也将使用此查询(最好不要重新设计整个报表以使用多个功能)。本来以为Table-valued-function的性能可能有问题,但经过测试,似乎和存储过程差不多。 在我看来,查询看起来应该很笨重。而且“闻起来”对我来说有点好笑,但到目前为止,我不知道为什么我不应该这样编码(因此提出了问题)。 好吧,OR 可能不允许在您要比较的任何字段上使用索引。您可以在其中添加OPTION(RECOMPILE) 以强制执行仅针对一个条件的执行计划,该条件可以使用任何索引,但重新编译也需要一些时间。无论如何都要检查执行计划。 【参考方案1】:

将动态 SQL 转换为 ITVF 的目的是消除这种废话。只需将 ITVF 写为

create function schemaNme.funcName() returns table return
  select * from tableName where table = 'words';

并让客户端直接添加任何所需的过滤条件,如下所示:

select *
from schemaNme.funcName()  t
where t.year_id = @year_id;

这隐藏了数据如何从物理表中组装到逻辑视图中的详细信息,同时仍使客户端能够根据需要进行过滤。

更新我的以下补充评论

ITVF 是一个参数化视图,可能带有缓存的查询计划。像任何其他视图(或表)一样,如果您希望动态修改访问机制,就像这里一样,您将不得不使用动态 SQL。但是,由于查询的内部结构已经为您封装在 ITVF 中,在这种情况下,您可以简单地动态修改 WHERE 子句,这是一项更简单的任务

【讨论】:

你能指出一个地方,ITVF 的这个意图得到了扩展吗? ITVF 是一个参数化视图,可能带有缓存的查询计划。像任何其他视图(或表)一样,如果您希望动态修改访问机制,就像这里一样,您将不得不使用动态 SQL。但是,由于查询的内部结构已经为您封装在 ITVF 中,在这种情况下,您可以简单地动态修改 WHERE 子句,这是一项更简单的任务。 感谢您的帮助彼得!

以上是关于在sql查询中使用局部变量作为开关是不好的做法的主要内容,如果未能解决你的问题,请参考以下文章

动态设置局部变量[重复]

要同步哪些对象?为啥局部变量不好? [复制]

为啥在 Django 中使用线程局部变量不好?

我们如何在子查询 SQL Server 中分配局部变量

SQL 视图 局部变量 全局变量 条件语句 事务 触发器

转载 SQL Server中常用全局变量介绍