Передача аргументов в представления в SQL Server - PullRequest
2 голосов
/ 08 января 2010

Предположим, у меня есть представление, которое сворачивает данные с помощью предложения GROUP BY:

CREATE VIEW InvoiceAmountsByCustomer AS
  SELECT
    Customer.CustomerID,
    SUM(Invoice.TotalAmount) AS TotalInvoiceAmount
  FROM
    Customer LEFT OUTER JOIN Invoice ON Customer.CustomerID = Invoice.CustomerID
  GROUP BY Customer.CustomerID

Теперь предположим, что я хочу, чтобы представление ограничивало, какие счета включаются в итоги на основе диапазона дат.Чтобы проиллюстрировать (притворяясь, что {From Date} и {To Date} содержат диапазон дат):

CREATE VIEW InvoiceAmountsByCustomer AS
  SELECT
    Customer.CustomerID,
    SUM(Invoice.TotalAmount) AS TotalInvoiceAmount
  FROM
    Customer LEFT OUTER JOIN Invoice ON Customer.CustomerID = Invoice.CustomerID
  WHERE
    Invoice.Date BETWEEN {From Date} AND {To Date}
  GROUP BY Customer.CustomerID

Чем я могу заменить {From Date} и {To Date}, чтобы я мог передавать их значения (прямо или косвенно)к мнению?Например, возможно ли связать эти значения с текущим сеансом?

CREATE VIEW InvoiceAmountsByCustomer AS
  SELECT
    Customer.CustomerID,
    SUM(Invoice.TotalAmount) AS TotalInvoiceAmount
  FROM
    Customer LEFT OUTER JOIN Invoice ON Customer.CustomerID = Invoice.CustomerID
  WHERE
    Invoice.Date BETWEEN GetUserDefinedSessionValue('From Date') AND GetUserDefinedSessionValue('To Date')
  GROUP BY Customer.CustomerID

, где GetUserDefinedSessionValue - мнимая функция, которая возвращает значения, связанные с текущим сеансом.Другая воображаемая функция, SetUserDefinedSessionValue, будет вызвана клиентом перед запросом представления:

SetUserDefinedSessionValue('From Date', ...)
SetUserDefinedSessionValue('To Date', ...)
SELECT * FROM InvoiceAmountsByCustomer

Мой воображаемый пример предназначен только для иллюстрации того, как я предполагаю, что эти значения передаются в представление.

Примечание: Это тривиальный пример, и реальная ситуация намного сложнее, мешая мне выполнить GROUP BY запрос непосредственно клиентом.

Ответы [ 3 ]

3 голосов
/ 08 января 2010

Можно вызывать Определенные пользователем функции в представлении, да, но я бы предпочел использовать Определенную пользователем табличную функцию , где вы передаете требуемые параметры, и это, в свою очередь, возвращает данные, которые вы хотите.

Пользовательские функции

2 голосов
/ 19 ноября 2012

Старая ветка, но я сам искал ответ на эту конкретную дилемму, когда мне вдруг показалось, что, возможно, самый простой способ - лучший.

Soulution 1: полностью пропустите представление и напишите полный SQL в вашем коде. Затем вы можете объявить параметры, как вы хотите. Если вы не используете индексированные представления, нет большой разницы между select * from 'view' и всем оператором select с опциями объявления.

Решение 2: Вместо того, чтобы использовать представление, почему бы просто не создать процедуру? Это менее гибко, но если вы планируете использовать select * from 'view', это сделает то же самое.

Пример:

CREATE proc dbo.ViewDates @from_date datetime, @to_date datetime AS 
SELECT
    Customer.CustomerID,
    SUM(Invoice.TotalAmount) AS TotalInvoiceAmount   FROM
    Customer LEFT OUTER JOIN Invoice ON Customer.CustomerID = Invoice.CustomerID   
WHERE
        Invoice.Date BETWEEN @from_date AND @to_date   GROUP BY Customer.CustomerID

Тогда вместо выбора *:

exec dbo.ViewDates @from_date = '20120101', @to_date = '20120930'

Возможно, вам нужно отформатировать даты, используя @from_date = convert (datetime, 'требуемая строка даты', желаемый формат даты)

т.е.

exec dbo.ViewDates @from_date = convert(datetime, '20120101',112), @to_date = convert(datetime,'20120930',112)
0 голосов
/ 08 января 2010

Вот одно из решений:

CREATE TABLE dbo.ViewDates (theDate DATETIME)

Для запроса базы данных:

TRUNCATE TABLE viewDates

INSERT INTO viewDates VALUES (@fromDate)
INSERT INTO viewDates VALUES (@toDate)

Чтобы настроить вид

JOIN (select min(thedate) as StDate,max(theDate) as EnDate ) dt 
  ON invoice.date BETWEEN dt.StDate and dt.EndDate

Обратите внимание, что это будет работать только для одного пользователя за раз, если вам нужно несколько пользователей, вам нужно добавить идентификатор пользователя в таблицу, заполнить его и немного изменить запрос ...

...