【问题标题】:SQL code inside SQL Scalar-value function - want to generalize - optimizeSQL Scalar-value 函数中的 SQL 代码 - 想要泛化 - 优化
【发布时间】:2011-01-13 01:18:41
【问题描述】:

我得到了这段代码,我想优化一下。 我以后基本上可以在“Disp”表中添加新列,我不想回来修改这个函数。 我不能使用动态 SQL。正确的?在我的情况下还有什么其他方法可以解决吗?

这是函数:

ALTER FUNCTION [GetDate] 
(@hdrnumber INT, @DateColName VARCHAR(50))
RETURNS DATETIME
AS
BEGIN
    DECLARE @dt DATETIME
        SELECT  @dt = CASE
          WHEN @DateColName = 'ord_bookdate' THEN [ord_bookdate]
          WHEN @DateColName = 'ord_startdate' THEN [ord_startdate]
          WHEN @DateColName = 'ord_completiondate' THEN [ord_completiondate]
          WHEN @DateColName = 'pack_date_from' THEN [pack_date_from]
          WHEN @DateColName = 'pack_date_to' THEN [pack_date_to]
         END
        FROM    [Disp]
        WHERE   [hdrnumber] = @hdrnumber

    RETURN @dt
END

(删除了一些代码,因为它很长,但希望我在这里留下的内容对你们有意义)

如何使用此功能? 好吧,它基本上看起来像这样:

 insert into tablename (...)
 select somedate, [GetDate](somedate, somecolumn)
 from sometable
 where 1 = 1

【问题讨论】:

  • 有点题外话,但我会推荐一个不同的函数名称,以消除与内置 GETDATE() 函数的任何可能混淆

标签: sql-server optimization function dynamic


【解决方案1】:

我认为您在这里遇到了更大的设计问题。你到底是怎么用这个的?如果您需要将列指定为字符串 (??!),那么在许多关键情况下动态 SQL 将 >>SO

declare @sql NVARCHAR(MAX);
set @sql = 'SELECT ' + @DateColName + ' FROM disp WHERE hdrnumber = @hdrnumber';
EXEC (@sql, @hdrnumber);

(请注意有人无法将 SQL 注入 @DateColName)。

但更大的问题是代码中的设计气味。这个函数存在的事实让我担心你怎么可能使用它。大体上看一下,也许发布另一个更详细的关于你的设计的问题,我认为你可以得到更有帮助的答案。

【讨论】:

    【解决方案2】:

    您要么需要使用无法在用户定义函数中执行的动态 sql(因此您需要将其从函数中删除),要么就像您使用 CASE 语句(这不是t 完全通用)。

    我认为我个人会使用 CASE 方法开始并考虑动态 sql,如果证明可以提供更好的性能(可能有更多不同的可能字段)。 您需要进行一些维护工作以使 CASE 保持最新,但我无法想象会经常添加更多字段?

    【讨论】:

    • 我编辑了主帖,向您展示了我如何使用它,是的,实际上有 20 多个案例,我在这个示例中只留下了 5 个案例,以使代码看起来更小
    【解决方案3】:

    当然同意前两个答案中提供的cmets。

    无论如何,您可以编写以下函数来获取给定表的列名,然后 将列名与@DatecolumName 进行比较以从中返回值。

    创建

    function [dbo].[ftTableSchema](@TableName varchar(100))  returns table as
    return 
    --Declare @tableName varchar(30); select @TABLENAME='excelInBom'
    
    SELECT ColumnName=Column_Name
                ,DataType= case data_type
                                When  'DECIMAL' then 'DECIMAL('+convert(varchar,Numeric_precision)+','+Convert(varchar,Numeric_scale)+')'
                                When  'NUMERIC' then 'DECIMAL('+convert(varchar,Numeric_precision)+','+Convert(varchar,Numeric_scale)+')'
                                when 'VARCHAR' then 'VARCHAR('+Convert(varchar,Character_maximum_length)+')'
                                WHEN 'CHAR' THEN  'CHAR('+Convert(varchar,Character_maximum_length)+')'
                                ELSE data_type      
                              end
    
    ,ColumnOrder=Ordinal_Position,* FROM INFORMATION_SCHEMA.COLUMNS
    WHERE TABLE_NAME=@tableName
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-11-04
      • 1970-01-01
      • 1970-01-01
      • 2017-03-31
      • 1970-01-01
      相关资源
      最近更新 更多