首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >如何从Microsoft SQL 2008中的每个视图中选择单个元素

如何从Microsoft SQL 2008中的每个视图中选择单个元素
EN

Stack Overflow用户
提问于 2016-08-23 15:21:32
回答 1查看 168关注 0票数 1

我正在尝试从db中的每个视图中选择一个元素,以检查它们是否仍处于“正确的形式”。困难的是,这个视图的数量太多了。当我研究这一点时,我发现了这段代码,它查找所有的表名及其列名。

代码语言:javascript
运行
复制
  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;

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

数据库: DB1,DB2,DB3.......对于每个数据库: DatabaseDiagrams、表、视图...

所以为了在我的数据库中找到所有的视图,我写了这段代码。

代码语言:javascript
运行
复制
SELECT t.name AS view_name
FROM sys.views AS t
ORDER BY  view_name;  

其中一些数据库在其文件夹中有0个视图,而另一些则有很多视图。我的目标是从每个视图中选择一个元素。我如何才能做到这一点呢?

编辑:这是我找到的答案

代码语言:javascript
运行
复制
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;    

代码对我来说非常清楚,但我可以向任何在某处有问题的人解释它。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2016-08-23 21:13:25

好的,下一个查询有点长,但我认为它做了您想要的:

代码语言:javascript
运行
复制
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语句,该语句具有以下模板:

代码语言:javascript
运行
复制
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 *语句输出到一个表变量中。然后,我们打开一个游标并逐行执行语句。如果需要,您甚至可以通过取消注释--WHERE selectStmt NOT LIKE '%DB1%';部件来过滤游标中的数据库。

对于视图the execution succeeded,不会显示消息。对于失败的执行,将出现“Execution failed:”+视图消息。

有两件事你必须小心:

1)如果你有很多视图,即使你过滤了光标,这也需要很长时间。

2)您可能应该考虑将结果输出到一个文件中。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/39094768

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档