Оператор APPLY
Иногда, при написании сложных процедур для работы с данными, удобно использовать функции, возвращающие не скалярное значение, а таблицу. В предыдущих версиях SQL Server не было возможности в конструкциях JOIN использовать в качестве аргументов вызываемой функции параметры из внешнего запроса. Например, создадим процедуру GetProductDetails: CREATE FUNCTION GetProductDetails (@ProductID int) RETURNS TABLE AS
RETURN SELECT P.Model, P.Configuration, P.Price FROM Products P WHERE P.ProductID = @ProductID
Следующий код, использующий GetProductDetails приведет к ошибке: -- Внимание! Этот код не работает SELECT O.[Date], P.Model, P.Configuration, P.Price FROM Orders O OUTER JOIN GetProductDetails(O.ProductID) AS P ON P.ProductID = O.ProductID
В SQL Server 2005 для подобного использования функций предназначен оператор APPLY. Используя его вместо JOIN можно достичь желаемого результата: SELECT O.[Date], P.Model, P.Configuration, P.Price FROM Orders O OUTER APPLY GetProductDetails(O.ProductID) AS P
Оператор APPLY используется в комбинации с двумя ключевыми словами: CROSS и OUTER. Функциональность CROSS APPLY аналогична INNER JOIN – в случае, если процедура не возвращает результат, то строка не попадает в результирующий набор данных, OUTER APPLY работает аналогично OUTER JOIN – если процедура не возвращает результат, то строка все-таки попадает в результирующий набор, а в колонках, соответствующих получаемым из процедуры данным будут находиться значения NULL.
Исходя из плана выполнения запроса, функция GetProductDetails выполняется для каждого параметра, получаемого из внешнего запроса, что приводит к драматическим последствиям с точки зрения производительности. Таким образом, использование APPLY для значительных объемов данных может являться далеко не самым лучшим решением. Поэтому, необходимо тщательно проверять производительность запросов, использующих APPLY на реальных объемах данных и, в соответствии с этим, делать вывод о разумности применения этого оператора при построении запроса.