将参数传递给 SQL Server 中的视图

Posted

技术标签:

【中文标题】将参数传递给 SQL Server 中的视图【英文标题】:Passing arguments to views in SQL Server 【发布时间】:2010-01-08 13:16:01 【问题描述】:

假设我有一个通过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 DateTo 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 DateTo 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 查询。

【问题讨论】:

【参考方案1】:

可以在视图中调用用户定义的函数,是的,但我更愿意使用用户定义的表函数,您可以在其中传入所需的参数,然后这又会返回您想要的数据。

User Defined Functions

【讨论】:

内联表值函数与参数化视图完全一样,但多语句表值函数是另一种生物。如果可能的话,您想使用 INLINE TVF。【参考方案2】:

一个旧线程,但我正在浏览我自己的这个特殊困境的答案,当我突然想到,也许最简单的方法是最好的。

解决方案 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)

【讨论】:

【参考方案3】:

这是一种解决方案:

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

请注意,这一次仅适用于一个用户,如果您需要多个用户,则需要将用户 ID 添加到表中,填充它,并稍微调整查询...

【讨论】:

以上是关于将参数传递给 SQL Server 中的视图的主要内容,如果未能解决你的问题,请参考以下文章

使用引号将参数传递给 SQL Server SP

拆分逗号分隔参数传递给SQL Server 2008 R2中的存储过程

将 xml 字符串参数传递给 SQL Server 存储过程

将列作为参数传递给 SQL Server 中的 dateadd

通过 url 将参数传递给 sql server 报告服务

VBA 将日期参数传递给 SQL Server 存储过程