sp_executesql vs用户定义的标量函数

时间:2013-08-21 12:27:25

标签: tsql sql-server-2012 user-defined-functions cross-apply sp-executesql

在下表中,我存储了一些这样的条件:

enter image description here

然后,一般来说,在第二张表中,我有以下记录:

enter image description here

我需要的是使用正确的条件比较这些值并存储结果(假设'0'表示false,'1'表示true表示附加列。)

我将在商店程序中执行此操作,基本上我将从几个记录到数百个记录进行比较。

可能的解决方案是为每个行构建动态语句使用sp_executesql,另一个是创建我自己的标量函数并使用交叉应用为eacy行调用它。

有谁能说出哪种方式更有效?

注意:我知道回答这个问题的最佳方法是制作两个解决方案并进行测试,但我希望可以根据其他内容(如缓存和SQL内部优化等)来解决这个问题。为我节省了很多时间,因为这只是一个更大问题的一部分。

1 个答案:

答案 0 :(得分:2)

在这种情况下,我认为没有必要使用sp_executesql。您可以在一个语句中一次获得所有记录的结果:

select Result = case
    when ct.Abbreviation='=' and t.ValueOne=t.ValueTwo then 1
    when ct.Abbreviation='>' and t.ValueOne>t.ValueTwo then 1
    when ct.Abbreviation='>=' and t.ValueOne>=t.ValueTwo then 1
    when ct.Abbreviation='<=' and t.ValueOne<=t.ValueTwo then 1
    when ct.Abbreviation='<>' and t.ValueOne<>t.ValueTwo then 1
    when ct.Abbreviation='<' and t.ValueOne<t.ValueTwo then 1
    else 0 end
from YourTable t
    join ConditionType ct on ct.ID = t.ConditionTypeID

并使用以下内容更新其他列:

;with cte as (
    select t.AdditionalColumn, Result = case
        when ct.Abbreviation='=' and t.ValueOne=t.ValueTwo then 1
        when ct.Abbreviation='>' and t.ValueOne>t.ValueTwo then 1
        when ct.Abbreviation='>=' and t.ValueOne>=t.ValueTwo then 1
        when ct.Abbreviation='<=' and t.ValueOne<=t.ValueTwo then 1
        when ct.Abbreviation='<>' and t.ValueOne<>t.ValueTwo then 1
        when ct.Abbreviation='<' and t.ValueOne<t.ValueTwo then 1
        else 0 end
    from YourTable t
        join ConditionType ct on ct.ID = t.ConditionTypeID
)
update cte
set AdditionalColumn = Result

如果应该在许多地方应用上述逻辑,而不仅仅是在一个表上,那么是的,您可以考虑功能。虽然我会使用内联表值函数(而不是标量),因为使用用户定义的标量函数会产生开销(调用和返回,以及要处理的行越多,浪费的时间越多。)

create function ftComparison
(
    @v1 float,
    @v2 float,
    @cType int
)
returns table
as return
    select
        Result = case
            when ct.Abbreviation='=' and @v1=@v2 then 1
            when ct.Abbreviation='>' and @v1>@v2 then 1
            when ct.Abbreviation='>=' and @v1>=@v2 then 1
            when ct.Abbreviation='<=' and @v1<=@v2 then 1
            when ct.Abbreviation='<>' and @v1<>@v2 then 1
            when ct.Abbreviation='<' and @v1<@v2 then 1
            else 0
        end
    from ConditionType ct
    where ct.ID = @cType

然后可以应用:

select f.Result
from YourTable t
    cross apply ftComparison(ValueOne, ValueTwo, t.ConditionTypeID) f

select f.Result
from YourAnotherTable t
    cross apply ftComparison(SomeValueColumn, SomeOtherValueColumn, @someConditionType) f