有没有办法修改以下UPDATE
语句,以便只调用一次标量函数,而不是两次?
UPDATE a
SET SomeField = b.SomeField
FROM TableA AS a
JOIN TableB b ON b.Link = a.Link
WHERE b.CostMin <= @Cost * dbo.OneScalarFunction(@CurrencyFrom, b.Currency)
AND b.CostMax >= @Cost * dbo.OneScalarFunction(@CurrencyFrom, b.Currency)
P.S。使用BETWEEN
运算符无济于事 - 无论如何,SQL Server都会调用标量函数两次。
答案 0 :(得分:5)
尝试 BETWEEN 运算符。
WHERE functionCall(..) BETWEEN minValue AND maxValue
答案 1 :(得分:5)
这通常性能更高,但要求您将标量函数更改为内联表值函数。
UPDATE
a
SET
SomeField = b.SomeField
FROM
TableA AS a
CROSS APPLY
dbo.oneInlineTableValuedFunction(@CurrencyFrom, e.Currency) AS ITVF
INNER JOIN
TableB b
ON b.Link = a.Link
WHERE
b.CostMin <= @Cost * ITVF.exchangeRate
AND b.CostMax >= @Cost * ITVF.exchangeRate
虽然表值函数返回表,但 可以 选择仅使用一个字段重新调整一行。然后,您将其有效地用作标量函数 - 但是,您可以获得SQL Server如何优化上述查询的所有好处...
- 如果TVF是内联(而不是多语句)
- TVF扩展到查询中
- 结果是性能戏剧性地优于标量函数
示例内联表值函数:
CREATE FUNCTION dbo.oneInlineTableValuedFunction (
@currencyFrom VARCHAR(32),
@currencyTo VARCHAR(32)
)
RETURNS TABLE
AS
RETURN (
SELECT
exchangeRate
FROM
dbo.someTable
WHERE
currencyFrom = @currencyFrom
AND currencyTo = @currencyTo
)
故意琐碎
关于此问题的一个示例帖子:scalar-functions-inlining-and-performance
如果你为INLINE CROSS APPLY SCALAR FUNCTION PERFORMANCE
搜索网页,我相信你会得到更多。
答案 2 :(得分:3)
你可以尝试使用BETWEEN(如下所示),虽然你需要测试它,因为我有一个潜行的怀疑,数据库可能将其拆分出来执行它&gt; =和&lt; =无论如何.. < / p>
UPDATE a
SET SomeField = b.SomeField
FROM TableA AS a
JOIN TableB b ON b.Link = a.Link
WHERE @Cost * dbo.OneScalarFunction(@CurrencyFrom, e.Currency) BETWEEN b.CostMin AND b.CostMax