【问题标题】:How do I supply the FROM clause of a SELECT statement from a UDF parameter如何从 UDF 参数提供 SELECT 语句的 FROM 子句
【发布时间】: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 服务器可能是我试图从表变量中选择的东西。

编辑时:是的,我不需要在函数中执行此操作,我可以运行存储过程,我之前没有编写过任何一个。

【问题讨论】:

    标签: sql sql-server user-defined-functions


    【解决方案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,但之后各有自己的数据
      猜你喜欢
      • 1970-01-01
      • 2011-10-03
      • 1970-01-01
      • 2020-11-19
      • 2010-11-12
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-08-28
      相关资源
      最近更新 更多