Sql server 从T-SQL函数返回视图中的记录计数

Sql server 从T-SQL函数返回视图中的记录计数,sql-server,tsql,Sql Server,Tsql,我在SQLServer中有一个表,其中列出了报表中的部分。有三个字段,一个是SectionID(数字自动编号主键)、SectionTitle(报告上的节的标题)和SourceView(返回报告记录的本地数据库中的视图名称) 我需要的是一个视图,它有这三列,再加上第四列,显示“SourceView”返回的记录数。 比如: CREATE myView AS SELECT SectionID, SectionTitle, SourceView, myFunction(SourceVi

我在SQLServer中有一个表,其中列出了报表中的部分。有三个字段,一个是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运行返回值的过程,也不能查询系统对象,因为虽然这对表有效,但对视图无效

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

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


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

这将使您无需使用函数或知道视图的名称即可进行倒计时:

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视图),但如果您确实需要保留视图,则可以解决您的问题。

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

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

这使我在Management Studio中的“ORDER BY”子句中出现了一个错误,尽管我没有尝试计算“myView”中的行数,但我尝试返回“SourceView”字段中命名的视图中的行数-如果我的原始问题不清楚,请道歉。抱歉,我的错。我想我已经修复了原来的错误(它在SQL Server 2014上对我起作用),并且我增加了一个新的方法来考虑。不过有点脏:)谢谢你,我也同意它会提供记录,但我无法实现一个每次将视图添加到tblBaseData时都需要编辑的解决方案-任何解决方案都必须工作,而不管tblBaseData中的记录如何更改。这给了我一个表变量,但我看不到一种使变量的内容可供视图使用的方法。。。。我需要一个reporting services报告和一个为网页提供信息的web方法。除非我遗漏了一些明显的内容(这是完全可能的),否则我仍然无法获取表变量的内容??存储过程返回一个表。您可以选择存储过程(与视图相反)作为reporting services报表的数据源。类似地,您可以在web方法中执行存储过程,而不是从视图中进行选择-它们都返回相同的内容(即表)。这看起来是正确的解决方案,但当我尝试该过程并执行它时-需要记录列表-我得到:Msg 214,Level 16,State 2,procedure sp_executesql,第1行过程需要类型为“ntext/nchar/nvarchar”的参数“@statement”。
sp_executesql
需要的是nvarchar而不是varchar。我已经相应地修改了我的答案。谢谢。这解决了这个问题,但现在当过程运行时,出现了一个关于标量变量@RowCount未声明的重复错误。允许我们使用sp_executesql运行“set”命令吗?下面strickt01给出了基本答案,您可以用返回表变量的过程替换视图。这在ReportingServices和web方法中都有效——所以,问题解决了。谢谢大家的帮助和时间。