如何使用数据类型nvarchar获取函数的结果

时间:2015-07-03 02:00:39

标签: sql function sql-server-2012

我有一个像这样的数据库表

  Id   Code   Amount   Formula
  -------------------------------------
   1    A01   20.00   
   2    A08   0.00    dbo.ufn_Test(40)  
   3    A03   0.00    dbo.ufn_Test(60)  

我的Formula列是一个字符串,其名称作为我的数据库中的函数,如何将结果返回到Amount列?

我的表有大约100000行,所以当我使用while()时,需要花费很多时间。 我正在使用SQL Server 2012

我使用了这样的动态SQL:

DECLARE @_j INT = 1

WHILE (@_j<=(SELECT MAX(Id) FROM #Ct_Lv))
BEGIN
    SET @_CtLv = (SELECT Formula FROM #Ct_Lv WHERE Id = @_j)

    DECLARE @sql NVARCHAR(MAX)
    DECLARE @result NUMERIC(18, 2) = 0

    SET @sql = N'set @result = N''''SELECT''' + @_CtLv

    EXEC sp_executesql @sql, N'@result float output', @result out

    UPDATE #Ct_Lv
    SET Amount = @result
    WHERE Id = @_j

    SET @_j = @_j + 1
END

但是我的最大@_j = 100000,我运行了3个小时的代码并且它仍在运行

2 个答案:

答案 0 :(得分:0)

有一件事,我想知道的是,id属性是标识列吗?

第二个最重要的部分是,您为每一行声明变量@sql和@result,并且您在每行迭代时获取最大值,这可能会降低性能。我不确定,我在这里给出的解决方案速度有多快,但你可以尝试一次。

Set Nocount On;

Declare  @_count        Int
        ,@_j            Int
        ,@_cnt          Int
        ,@_dynamicSql   Varchar(Max)
        ,@_formula      Varchar(Max)
        ,@_row25Cnt     Int

Select   @_count    = Count(1)
        ,@_j = 0
        ,@_cnt = 0
        ,@_dynamicSql = ''
        ,@_formula = ''
        ,@_row25Cnt = 1
From    #Ct_Lv As ct With (Nolock)

While (@_cnt < @_count)
Begin
    Select  Top 1
             @_j = ct.Id
            ,@_formula = ct.Formula
    From    #Ct_Lv As ct With (Nolock)
    Where   ct.Id > @_j
    Order By ct.Id Asc

    Select  @_dynamicSql = 'Update ct Set ct.Amount = f.result From #Ct_Lv As ct Join ( Select ' + Cast(@_j As Varchar(20)) + ' As Id, [fuctionResultAttribute] As result From ' + @_formula + ' ) As f On ct.Id = f.Id; '

    If (@_row25Cnt = 25)
    Begin
        Exec (@_dynamicSql)

        Select   @_dynamicSql = ''
                ,@_row25Cnt = 0
    End
    Else If ((@_cnt + 1) = @_count)
    Begin
        Exec (@_dynamicSql)

        Select   @_dynamicSql = ''
                ,@_row25Cnt = 0
    End

    Select   @_cnt = @_cnt + 1
            ,@_row25Cnt = @_row25Cnt + 1
End

在这里,我到目前为止所做的是,我通过Id循环Id并为每25行生成动态sql,一旦count达到25,将执行动态sql将更新你的金额。然后再次开始为接下来的25行生成动态sql,当count即将结束并且没有25行作为结束时,动态sql将在循环即将结束时执行,否则如果&#39;条件。

只有在每一行的公式列中只有一个公式时,我的解决方案上面的

才会起作用。

答案 1 :(得分:0)

我只是建议如果Formula字段每次调用相同的函数,那么最好只存储要传递给函数的参数,然后就可以轻松处理大量数据。

其他循环遍历大数据并不是执行任何操作的首选方法。因此,建议在表结构中使用其他技巧并存储数据。