Как создать функцию, которая позволяет передавать параметры - PullRequest
0 голосов
/ 04 июля 2019

У меня есть запрос, который включает в себя дату и название страны, и я хотел знать, как это можно сделать в функции, чтобы частота дат, то есть между 2000-01-01 и 2001-12-31, и название страны например, «Германия» может быть передана как переменная.

Я создал запрос, но не функцию.

SELECT * 
FROM Customers c
Join Orders o
On c.CustomerID = o.CustomerID
WHERE o.OrderDate BETWEEN '1990-01-01' AND '2017-01-01'
AND c.Country LIKE 'Germany'

возможно ли иметь параметры для диапазона дат и для страны, чтобы их можно было передать в функцию?

Ответы [ 2 ]

3 голосов
/ 04 июля 2019

Вы можете создать встроенную табличную функцию , например,

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 или Аарону Бертрану, я не намеренно подключаю к нему множество блогов, просто они все очень актуальны.

0 голосов
/ 04 июля 2019

Это создает встроенную табличную функцию:

CREATE FUNCTION dbo.CustomerOrders (
    @FromDate DATE,
    @ToDate DATE,
    @CountryLike VARCHAR(50))
RETURNS TABLE AS 
RETURN
    SELECT
        *
    FROM
        Customers c
        inner Join Orders o On c.CustomerID = o.CustomerID
    WHERE 
        o.OrderDate BETWEEN @FromDate AND @ToDate AND 
        c.Country LIKE '%' + @CountryLike + '%'

Пожалуйста, избегайте использования *, замените фактические столбцы, которые вы планируете использовать.Также обратите внимание, что я добавил оба символа подстановки непосредственно внутри функции, поэтому вам не нужно писать % в названии страны (вы можете изменить его в соответствии со своими потребностями).

Вы используете его следующим образом:

SELECT
    C.*
FROM
    dbo.CustomerOrders('2019-05-01', '2019-06-15', 'German') AS C
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...