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

Is it bad practice to use local variables as switches in sql queries

我在存储过程中有一个动态 sql 查询,我应该将其转换为 Table 值函数 (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 中,您不能 运行 插入语句,因此您不能 return 将此 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 字符串组合创建一个条件。

抛开这个限制,以这种方式编写查询是否存在安全 and/or 性能风险?有没有更简单的方法来为 TVF 编写这样的查询?

将动态 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;

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

根据我下面的补充评论更新:

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