问题
我如何循环访问我的SQL DB中的视图列表?
背景和尝试的事情
我现在用Google搜索了大约2个小时,我找到了很多方法来循环我的数据库的不同属性。我可以遍历一个表列表,一个列列表和一个计数列表,但我还没有找到任何允许我遍历一个视图列表的内容。
代码循环遍历我试图修改的表格
link i used to obtain sample code below
--List all the tables of current database and total no rows in it
EXEC sp_MSForEachTable 'SELECT ''?'' as TableName, COUNT(1)
as TotalRows FROM ? WITH(NOLOCK)'
--List all the tables of current database and space used by it EXECUTE sp_MSforeachtable 'EXECUTE sp_spaceused [?];';
GO
我想做的sudo代码
loop through each view in list
run query here for each view
output results
请求帮助
有人可以链接到我有关如何执行此操作或提供示例代码的更多信息吗?非常感谢所有帮助!谢谢!
答案 0 :(得分:3)
执行此操作的一种方法是使用游标。你肯定需要动态SQL,所以首先转到this link。然后,您可以尝试以下方法:
DECLARE @View VARCHAR(200), @Query VARCHAR(MAX)
DECLARE YourView CURSOR LOCAL STATIC READ_ONLY FORWARD_ONLY FOR
SELECT name
FROM sys.views
OPEN YourView
FETCH NEXT FROM YourView INTO @View
WHILE @@FETCH_STATUS = 0
BEGIN
SET @Query = 'SELECT '''+@View+''' ViewName, COUNT(1) Rows
FROM '+QUOTENAME(@View) -- Your code here
PRINT(@Query)
FETCH NEXT FROM YourView INTO @View
END
CLOSE YourView
DEALLOCATE YourView
答案 1 :(得分:2)
我正在使用ROW_NUMBER()和INFORMATION_SCHEMA迭代视图。
快速查看工作清单:
SELECT TABLE_CATALOG + '.' + TABLE_SCHEMA + '.' + TABLE_NAME AS ViewName
,ROW_NUMBER() OVER (
ORDER BY TABLE_CATALOG
,TABLE_SCHEMA
,TABLE_NAME
)
FROM INFORMATION_SCHEMA.VIEWS
这是存储过程:
CREATE PROCEDURE LoopThroughViews
AS
DECLARE @sql VARCHAR(max)
,@tableCount INT
,@i INT = 0
SELECT @tableCount = COUNT(*)
FROM INFORMATION_SCHEMA.VIEWS
WHILE (@tableCount >= @i)
BEGIN
SELECT @sql = 'select * from ' + ViewName
FROM (
SELECT TABLE_CATALOG + '.' + TABLE_SCHEMA + '.' + TABLE_NAME AS ViewName
,ROW_NUMBER() OVER (
ORDER BY TABLE_CATALOG
,TABLE_SCHEMA
,TABLE_NAME
) AS ViewNum
FROM INFORMATION_SCHEMA.VIEWS
) x
WHERE @i = ViewNum
EXEC(@sql)
SET @i = @i + 1
END
最后是电话:
EXEC LoopThroughViews
答案 2 :(得分:1)
有很多方法可以做到这一点,游标,手动循环。有可能以基于集合的方式找到您想要的内容(意味着您的神秘查询的答案)。无论哪种方式,如你所说,你需要动态的SQL。
选项1 - 一个方法
SET NOCOUNT ON;
DECLARE @Views as TABLE (Object_id int, name nvarchar(200));
INSERT INTO @Views (Object_ID, name)
SELECT Object_ID, name
FROM sys.views
DECLARE @viewName nvarchar(200) = (select top 1 name from @Views);
DECLARE @sql nvarchar(max) = '';
WHILE(Exists(select 1 from @Views)) BEGIN
SET @sql = 'select count(*) FROM ' + @ViewName +';'
--exec(@sql); --careful you're not accepting user input here!
Print (@sql);
DELETE FROM @Views where name = @viewName;
SET @ViewName = (select top 1 name from @Views);
END;
选项2 - 更具弹性的方法
在我的小测试数据库中尝试这个时,我意识到我的第一个解决方案(以及所有其他解决方案)都存在潜在问题。视图可以变得过时 - 意味着底层对象更改为列重命名。所有其他解决方案都会抛出错误并停止处理。如果您正在进行大/长查询,这可能是不合需要的。所以我添加了一些错误处理来记录错误并继续处理。
SET NOCOUNT ON;
DECLARE @ViewCount int = 0;
DECLARE @Counter int = 0;
DECLARE @sql nvarchar(max) = '';
DECLARE @viewName nvarchar(200) = ''
DECLARE @Views as TABLE ( rownum int identity(1,1),
name nvarchar(200),
Primary Key clustered (rownum)
);
INSERT INTO @Views (name)
SELECT name
FROM sys.views;
SET @ViewCount = SCOPE_IDENTITY();
WHILE(@Counter < @ViewCount) BEGIN
SET @Counter = @Counter+1;
SELECT @sql = 'select count(*) FROM ' + name +';', @viewName = name
FROM @Views
WHERE rownum = @Counter;
BEGIN TRY
-- exec(@sql); --careful you're not accepting user input here!
Print (@sql);
END TRY BEGIN CATCH
Print ('ERROR querying view - ' + @viewname + ' // ' + ERROR_MESSAGE());
END CATCH
END;