我在存储过程中有一个动态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中,您无法运行insert语句,因此您无法将此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编写这样的查询?
答案 0 :(得分: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子句,这是一个稍微简单的任务