2012-11-14 14 views
6

Czy istnieje sposób zmodyfikowania poniższej instrukcji UPDATE, aby funkcja skalarna była wywoływana tylko raz, a nie dwa razy?Unikaj wielokrotnego wywoływania funkcji skalarnej w instrukcji 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. Korzystanie z operatora BETWEEN nie pomaga - SQL Server wywołuje funkcję skalarną dwukrotnie.

Odpowiedz

5

to jest często znacznie bardziej wydajnych, ale wymaga, aby zmienić funkcję skalarną do funkcji wycenione tabeli inline.

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 

Chociaż funkcje wycenione tabela powrócić tabele, ty może wybrać retun tylko jeden wiersz z jednego pola. Następnie używasz go skutecznie jako funkcji skalarnej - Ale masz wszystkie zalety jak SQL Server może optymalizować zapytania nad ...
- Jeśli TVF jest Inline (a nie multi-rachunek)
- The TVF zostaje rozszerzona na zewnątrz w zapytaniu
- rezultatem jest lepsza niż wydajność dramatiaclly funkcji skalarnych


Przykład inline Tabela Ceniona Funkcja:

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 
) 

Celowo trywialne

Jeden przykładowy post na ten temat: scalar-functions-inlining-and-performance

Jeśli wyszukaæ w internecie INLINE CROSS APPLY SCALAR FUNCTION PERFORMANCE Jestem pewien, że masz dużo więcej.

+0

Dziękuję. Wydaje się, że nie ma innego wyjścia, jak zrezygnować z funkcji skalarnych na korzyść funkcji o wartościach tabelarycznych. – 10p

+0

@ 10p - Są * znacznie bardziej wydajne, gdy są stosowane w całym zestawie danych. – MatBailie

5

Wypróbuj operator POMIĘDZY.

WHERE functionCall(..) BETWEEN minValue AND maxValue 

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

+1

Dobra myśl. To może jednak zostać rozszerzone na '<=' and '> =' w praktyce. –

+0

Będę testować, że nie jest on wywoływany dwa razy w tym przypadku, dziękuję – 10p

+0

SQL Server wywołuje funkcję skalarną dwukrotnie, tak czy inaczej, to po prostu inna notacja, więc ta sugestia tak naprawdę nie rozwiązuje problemu – 10p

3

Można spróbować użyć między (jak poniżej), chociaż trzeba by go przetestować jak mam podejrzenia chyłkiem baza danych może podzielić ten się wykonać go jako> = i < = tak ..

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 
+0

Podniosłem stan rozwiązanie, ale user1660584 był tam pierwszy – 10p

+0

Miałeś rację - SQL Server wykonuje je dwukrotnie i tak – 10p

Powiązane problemy