6

有没有办法修改下面的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)

PS使用BETWEEN运算符无济于事 - SQL Server 无论如何都会调用标量函数两次。

4

3 回答 3

5

试试BETWEEN运算符。

WHERE functionCall(..) BETWEEN minValue AND maxValue

http://www.w3schools.com/sql/sql_between.asp

于 2012-11-14T12:48:29.430 回答
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
)

故意微不足道

关于此的一个示例帖子: 标量函数内联和性能

如果你在网上搜索,INLINE CROSS APPLY SCALAR FUNCTION PERFORMANCE我相信你会得到更多。

于 2012-11-14T13:02:07.623 回答
3

您可以尝试使用 BETWEEN (如下所示),尽管您需要对其进行测试,因为我有一个偷偷摸摸的怀疑数据库可能会将其拆分为 >= 和 <= 无论如何执行它..

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
于 2012-11-14T12:49:35.010 回答