【问题标题】:Returning a count of records in a view from a T-SQL function从 T-SQL 函数返回视图中的记录计数
【发布时间】:2016-12-21 20:39:36
【问题描述】:

我在 SQL Server 中有一个表格,其中列出了报告中的部分。共有三个字段,SectionID(数字自动编号主键)、SectionTitle(报告中部分的标题)和 SourceView(返回报告记录的本地数据库中的视图名称)。

我需要的是一个视图,它包含这三列加上第四列,它显示“SourceView”返回的记录数。 比如:

CREATE myView AS

SELECT
  SectionID,
  SectionTitle,
  SourceView,
  myFunction(SourceView) AS RowsInView
FROM
  tblBaseData

我认为这很容易通过编写一个函数来接收视图名称并返回行数来实现。我最初的计划是在函数体中构建一些动态 SQL。

CREATE FUNCTION myFunction(@ViewName VARCHAR) RETURNS INT AS

BEGIN

  DECLARE @RowCount INT
  DECLARE @SQL VARCHAR(200)
  SET @SQL = 'SET @RowCount = (SELECT COUNT(*) FROM ' + @ViewName + ')'
  EXEC sp_executesql @SQL
  RETURN ISNULL(@RowCount, 0)

END

但是,不能在函数中使用 EXEC,因此不能运行动态 SQL,不能使用 EXEC 来运行返回值的过程,也不能查询系统对象,因为 - 虽然这适用于表格 - 不适用于视图。

我尝试了以下方法但没有成功:

How to get the row count for views from a database?

Execute function inside view SQL server

https://msdn.microsoft.com/en-GB/library/ms188655.aspx

Create a function for counting rows from any table

我正在尝试让视图正常工作,因为我需要在网页上显示具有当前记录数的结果,否则我会构建一个表格并定期刷新数据,

我认为我只是使用了错误的方法来解决这个问题。谁能指出我正确的方向?谢谢。

【问题讨论】:

  • 对此的基本答案 - 由下面的 strict01 提供,是您可以用返回表变量的过程替换视图。这适用于报告服务和 Web 方法 - 因此,问题解决了。感谢大家的帮助和时间。

标签: sql-server tsql


【解决方案1】:

这相当笨拙,但是使用过程而不是视图可以解决您在问题中解决的问题:

CREATE PROCEDURE GetViewRowCounts
AS
BEGIN
    DECLARE @sectionId int, @title varchar(50), @view varchar(50)
    DECLARE @tbl_view_counts TABLE (section_id int not null,
                                    title varchar(50) not null,
                                    view_name  varchar(50) not null,
                                    view_count int not null)
    DECLARE @RowCount INT
    DECLARE @SQL NVARCHAR(200), @ParmDefinition NVARCHAR(100)

    DECLARE c_vws CURSOR FAST_FORWARD FOR
     SELECT
    SectionID,
    SectionTitle,
    SourceView
    FROM
    tblBaseData

    OPEN c_vws 

    FETCH NEXT FROM c_vws INTO @sectionId, @title, @view

    WHILE @@FETCH_STATUS = 0
    BEGIN
         SET @ParmDefinition = N'@RowCountOUT int OUTPUT';
         SET @SQL = N'SELECT @RowCountOUT = COUNT(*) FROM ' + @view

         EXEC sp_executesql @SQL, @ParmDefinition, @RowCountOUT=@RowCount OUTPUT;

         INSERT @tbl_view_counts
         VALUES (@sectionId, @title, @view, @RowCount)

         FETCH NEXT FROM c_vws INTO @sectionId, @title, @view
    END

    CLOSE c_vws
    DEALLOCATE c_vws

    SELECT * FROM @tbl_view_counts
END

【讨论】:

  • 这给了我一个表变量,但我看不到一种方法可以使变量的内容可用于视图....我需要报告服务报告和网络提供网页的方法。除非我遗漏了一些明显的东西(这是完全可能的),否则我仍然无法获取 table 变量的内容?
  • 存储过程返回一个表。您可以选择存储过程(而不是视图)作为 Reporting Services 报表的数据源。同样,您可以在 Web 方法中执行存储过程,而不是从视图中选择 - 它们都返回相同的内容(即表格)。
  • 这看起来像是正确的解决方案,但是当我尝试该过程并执行它时 - 期待记录列表 - 我得到:Msg 214, Level 16, State 2, Procedure sp_executesql, Line 1过程需要“ntext/nchar/nvarchar”类型的参数“@statement”。
  • sp_executesql 需要 nvarchar 而不是 varchar。我已经相应地修改了我的答案。
  • 谢谢。这解决了这个问题,但是现在当程序运行时,出现关于未声明标量变量 @RowCount 的重复错误。我们是否允许使用 sp_executesql 运行“设置”命令?
【解决方案2】:

这将使您无需使用函数或知道视图名称即可返回计数:

CREATE myView AS

SELECT
  SectionID,
  SectionTitle,
  SourceView,
  COUNT(*) OVER() AS RowsInView
FROM
  tblBaseData

编辑:抱歉,我误读了您最初的帖子。我同意存储过程可能是最好的方法,但如果您想继续使用视图方法,您可以使用“查找”视图,如下所示:

CREATE VIEW dbo.ViewCounts
AS

SELECT  'SourceView1' AS SourceViewName, 
        COUNT(*) OVER () AS RowsInView
FROM SourceView1
UNION
SELECT  'SourceView2' AS SourceViewName, 
        COUNT(*) OVER () AS RowsInView
FROM SourceView2

-- etc...

然后在原始视图中重新加入它以通过这种方式获得计数:

CREATE myView AS

SELECT
  t.SectionID,
  t.SectionTitle,
  t.SourceView,
  vc.RowsInView
FROM
  tblBaseData t
JOIN dbo.ViewCounts vc ON vc.SourceViewName = t.SourceView

这是一种非常肮脏的方法(如果您添加新视图,ViewCounts 视图将需要手动更新),但如果您绝对需要保留视图,则可以解决您的问题。

【讨论】:

  • 这给了我在 Management Studio 中使用“ORDER BY”子句的错误,要清楚虽然我没有尝试计算“myView”中的行数,但我正在尝试返回行数在“SourceView”字段中命名的视图中 - 如果我的原始问题不清楚,请道歉。
  • 抱歉,我的错。我想我已经修复了原始错误(它适用于 SQL Server 2014),并且我添加了一种新的方法来考虑。虽然有点脏:)
  • 谢谢你,我同意它会提供记录计数,但我无法实现每次将视图添加到 tblBaseData 时都需要编辑的解决方案 - 任何解决方案都必须工作,无论tblBaseData 中记录的更改。
猜你喜欢
  • 2020-01-01
  • 1970-01-01
  • 2012-02-07
  • 1970-01-01
  • 2010-10-02
  • 1970-01-01
  • 2017-10-14
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多