Вы можете создать встроенную табличную функцию , например,
CREATE FUNCTION dbo.GetCustomerOrders(@Country VARCHAR(255), @DateFrom DATE, @DateTo DATE)
RETURNS TABLE
AS
RETURN
( SELECT c.CustomerID,
o.OrderDate,
c.Country,
<Other Fields>
FROM dbo.Customers AS c
INNER JOIN dbo.Orders AS o
ON o.CustomerID = c.CustomerID
WHERE o.OrderDate >= @DateFrom
AND o.OrderDate <= @DateTo
AND c.Country = @Country
);
. Затем вы можете использовать это как:
SELECT <columns>
FROM dbo.GetCustomerOrders('Germany', '19000101', '20170101') AS co;
Или, если вам нужноиспользуйте другую таблицу в качестве источника параметров, который вы бы использовали:
SELECT <columns>
FROM dbo.SomeOtherTable AS t
CROSS APPLY dbo.GetCustomerOrders(t.Country, t.StartDate, t.EndDate) AS co;
Последнее использование является хорошей демонстрацией того, почему табличная функция является лучшей идеей, чем хранимая процедура, если вы хотите инкапсулировать простой выбор.Это так же многоразово, но более универсально.Они также имеют тенденцию работать лучше, так как определение запроса функции расширяется во внешний запрос, так что вы, скорее всего, получите оптимальный план выполнения в зависимости от вашего варианта использования.
Я изменил BETWEEN
на >= AND <=
- хотя это семантически то же самое, я считаю, что между ними могут возникнуть проблемы, особенно если вы запрашиваете столбец datetime.Далее: Что общего между МЕЖДУ и дьяволом? .Если OrderDate
является столбцом даты и времени, вы можете найти более подходящим следующее:
WHERE o.OrderDate >= @DateFrom
AND o.OrderDate < DATEADD(DAY, 1, @DateTo)
Я также явно перечислил ваши столбцы (где я могу), так как вы никогда не должны использовать SELECT *
в рабочем коде.Дальнейшее чтение: Вредные привычки: использовать SELECT * / пропустить список столбцов .Я также включаю префикс схемы dbo.
, так как это , как правило, хорошая идея для этого (если только вы не намеренно оставляете это так, чтобы ссылки на таблицы изменялись в зависимости от входа в систему, что, я подозреваю, не является)
Наконец, я изменил LIKE
на =
, так как вы не используете подстановочный знак или сопоставление с образцом.
Если вы хотите хранимую процедуру, синтаксис будет
CREATE PROCEDURE dbo.GetCustomerOrders (@Country VARCHAR(255), @DateFrom DATE, @DateTo DATE)
AS
BEGIN
SELECT c.CustomerID,
o.OrderDate,
c.Country,
<Other Fields>
FROM dbo.Customers AS c
INNER JOIN dbo.Orders AS o
ON o.CustomerID = c.CustomerID
WHERE o.OrderDate >= @DateFrom
AND o.OrderDate <= @DateTo
AND c.Country = @Country;
END
И это будет называться с помощью:
EXECUTE dbo.GetCustomerOrders('Germany', '19000101', '20170101');
Но, как и выше, для простого выбора я не думаю, что это дает какие-либо преимущества перед TVF, только недостатки.
В заключение я не имею никакого отношения к блогу SQL или Аарону Бертрану, я не намеренно подключаю к нему множество блогов, просто они все очень актуальны.