如何从 UDF 参数提供 SELECT 语句的 FROM 子句
Posted
技术标签:
【中文标题】如何从 UDF 参数提供 SELECT 语句的 FROM 子句【英文标题】:How do I supply the FROM clause of a SELECT statement from a UDF parameter 【发布时间】:2008-12-08 16:30:36 【问题描述】:在我正在移植到 Web 的应用程序中,我们目前在运行时根据指定的“模板”字符串在运行时动态访问不同的表。既然我们正在迁移到 SQL 服务器,我想将执行此操作的负担移回数据库,因此我不必弄乱动态 GridView。我想编写一个表值 UDF,其中一个参数用于表名,一个用于查询 WHERE 子句。
我为我的 UDF 输入了以下内容,但显然它不起作用。有什么方法可以获取某种类型的 varchar 或字符串并获得可以在 FROM 子句中使用的表引用?
CREATE FUNCTION TemplateSelector
(
@template varchar(40),
@code varchar(80)
)
RETURNS TABLE
AS
RETURN
(
SELECT * FROM @template WHERE ProductionCode = @code
)
或通过其他方式获得与此类似的结果集。基本上表中的所有记录都由 varchar @template 与 @code 的匹配 ProductionCode 指示。
我收到错误“必须声明表变量“@template””,因此 SQL 服务器可能是我试图从表变量中选择的东西。
编辑时:是的,我不需要在函数中执行此操作,我可以运行存储过程,我之前没有编写过任何一个。
【问题讨论】:
【参考方案1】:CREATE PROCEDURE TemplateSelector
(
@template varchar(40),
@code varchar(80)
)
AS
EXEC('SELECT * FROM ' + @template + ' WHERE ProductionCode = ' + @code)
这可行,虽然它不是 UDF。
【讨论】:
危险会鲁滨逊!检测到sql注入! :P @Chris Lively - 好久不见!无论如何,你是怎么进入这个声名狼藉的工作的? 它对我有用。并且提供的模板值是从下拉列表中选择的,所以我认为它不能被注入 它肯定很容易受到 SQL 注入的影响,特别是如果它是一个 Web 应用程序。下拉菜单没有保护作用。【参考方案2】:执行此操作的唯一方法是使用 exec 命令。
此外,您必须将其移出存储过程而不是函数。显然函数不能执行动态sql。
【讨论】:
要么,要么 sp_executesql。但是,是的,你是对的。您必须使用动态 SQL。【参考方案3】:实现这一点的唯一方法是使用动态 SQL,但是,函数中的 SqlServer 不支持动态 SQL。
很抱歉,我很确定不可能在函数中执行此操作。
如果您使用的是存储过程,那将是可能的。
【讨论】:
【参考方案4】:另外,应该注意的是,替换查询中的表名,破坏了 SQL Server 缓存查询执行计划的能力。这几乎将使用 UDF 或 SP 的优势降低到零。您不妨直接调用 SQL 查询。
【讨论】:
缓存执行计划的优势并不是 UDF 或 SP 的主要优势。【参考方案5】:我希望能够处理的表数量有限,因此我可以使用 IF 编写一些东西,测试 @template 是否与多个值匹配,并为每个匹配运行
SELECT * FROM TEMPLATENAME WHERE ProductionCode = @code
听起来这是一个更好的选择
【讨论】:
如果你打算走这条路(这比动态 SQL 好一百倍)并且如果你将它封装在一个 SP 中而不是在前端进行测试,那么一定要对存储过程使用 WITH RECOMPILE 选项。由于缓存计划将关闭,其他性能可能会受到影响。【参考方案6】:如果您有许多具有相同结构的表,这通常意味着您没有以正常形式设计数据库。您应该将这些统一到一张表中。您可能需要为该表多提供一个属性列来区分数据集。
【讨论】:
它们的结构不一样,都有ProductionCode和TestTime,但之后各有自己的数据以上是关于如何从 UDF 参数提供 SELECT 语句的 FROM 子句的主要内容,如果未能解决你的问题,请参考以下文章