【问题标题】:Passing arguments to views in SQL Server将参数传递给 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 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 查询。

【问题讨论】:

    标签: sql-server view arguments


    【解决方案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 添加到表中,填充它,并稍微调整查询...

      【讨论】:

        猜你喜欢
        • 2013-07-17
        • 2018-01-08
        • 2011-06-27
        • 1970-01-01
        • 2017-12-13
        • 2011-10-07
        • 2011-06-16
        • 1970-01-01
        • 2016-04-16
        相关资源
        最近更新 更多