如何 select Microsoft SQL 2008 中每个 VIEW 的单个元素

How to select a single element from each VIEW in Microsoft SQL 2008

我正在尝试 select 来自数据库中每个视图的单个元素,以检查它们是否仍在 "correct form" 中。难的是这种观点的数量太多了。当我研究这个时,我发现了这段代码,它找到了所有 table 名称及其列名称。

  GO 
    SELECT t.name AS table_name,
    SCHEMA_NAME(schema_id) AS schema_name,
    c.name AS column_name
    FROM sys.tables AS t
    INNER JOIN sys.columns c ON t.OBJECT_ID = c.OBJECT_ID
    ORDER BY schema_name, table_name;

对于第一步,我认为在我的数据库中找到所有视图的名称将是一个好的开始。这是数据库结构。

数据库: DB1、DB2、DB3…… 对于每个数据库:DatabaseDiagrams、Tables、Views...

为了在我的数据库中找到所有视图,我写了这篇文章。

SELECT t.name AS view_name
FROM sys.views AS t
ORDER BY  view_name;  

其中一些数据库的文件夹中有 0 个视图,而有些数据库有很多视图。我的目标是 select 来自每个视图的单个元素。我怎样才能做到这一点?

编辑:这是我找到的答案

SET NOCOUNT ON;
DECLARE @ViewCount   int                = 0;
DECLARE @Counter     int                = 0;
DECLARE @sql         nvarchar(max)    = '';
DECLARE @viewName    nvarchar(120)    = ''
DECLARE @Views    as TABLE (  pk int identity(1,1), 
                              viewName nvarchar(300), 
                              Primary Key clustered  (pk)
                            );

INSERT INTO  @Views (viewName)
SELECT       name
FROM         sys.views;

SET          @ViewCount = SCOPE_IDENTITY();

WHILE(@Counter < @ViewCount) BEGIN
    SET @Counter = @Counter+1;

    SELECT  @sql = 'select TOP 1 * FROM ' + viewName +';', @viewName = viewName
    FROM    @Views
    WHERE    pk = @Counter;

    BEGIN TRY
        exec(@sql); 
    END TRY BEGIN CATCH
        Print ('Cannot query the view ' + @viewname );
    END CATCH
END;    

代码对我来说 crystal 很清楚,但我可以向在某处遇到问题的任何人解释。

好的,下一个查询有点长,但我认为它可以满足您的要求:

SET NOCOUNT ON;

DECLARE @sql NVARCHAR(MAX) = '';
DECLARE @stmt NVARCHAR(MAX);
DECLARE @testViews TABLE (selectStmt NVARCHAR(MAX));

;WITH  dbs
    AS ( SELECT  name
         FROM    sys.databases
         WHERE name NOT IN ('master','msdb','tempdb','model')
       )
SELECT   @SQL = 'SELECT ''SELECT TOP 1* FROM ''' + '+' + '''' + QUOTENAME(dbs.name) + ''''  + '+ ''.'' + QUOTENAME(SCHEMA_NAME(t.schema_id)) + ''.'' + QUOTENAME(t.name) FROM '
        + QUOTENAME(name) + '.sys.views AS t;' + @sql
FROM     dbs;

INSERT INTO @testViews
  EXEC(@sql);

DECLARE EXEC_CURSOR CURSOR
 FOR SELECT * FROM @testViews 
--WHERE selectStmt NOT LIKE '%DB1%';

OPEN EXEC_CURSOR
FETCH NEXT FROM EXEC_CURSOR INTO @stmt;

WHILE (@@FETCH_STATUS = 0)
BEGIN TRY
  PRINT 'Executing: ' + @stmt;
  EXEC(@stmt);
  FETCH NEXT FROM EXEC_CURSOR INTO @stmt;
END TRY
BEGIN CATCH
  PRINT 'Execution failed: ' + @stmt;
  FETCH NEXT FROM EXEC_CURSOR INTO @stmt;
END CATCH

CLOSE EXEC_CURSOR;
DEALLOCATE EXEC_CURSOR;

那么这实际上是做什么的。首先,我从 CTE 为每个数据库构建一个 SELECT 语句(系统数据库除外,如果你愿意,你可以打开它们)它具有以下模板:

SELECT 'SELECT TOP 1* FROM '+'[database_name]'+ '.' + 
QUOTENAME(SCHEMA_NAME(t.schema_id)) + '.' + QUOTENAME(t.name) FROM  
[database_name].sys.views AS t;

所以,现在每个数据库都有一个 SELECT 语句,它为该数据库中的所有视图构造 TOP 1 * SELECT 语句。

然后我们执行我们生成的字符串并将所有SELECT TOP 1 *语句输出到一个table变量中。然后我们打开一个游标并逐行执行语句。如果需要,您甚至可以通过取消注释 --WHERE selectStmt NOT LIKE '%DB1%'; 部分来过滤游标中的数据库。

对于执行成功的视图,不会出现任何消​​息。对于失败的执行,将出现 'Execution failed:' + 查看消息。

有两点你必须要小心:

1) 如果您有很多浏览量,即使您过滤光标也需要很长时间。

2) 您或许应该考虑将结果输出到文件中。