刷新視圖


問題:


 

當我們創建這樣一個視圖(myView):

create view myView As select * from myTable

 

:myTable的結構:myTable(id int)

后來,我們改變了myTable的結構,增加一個字段(newCol):

alter table myTable add newCol nvarchar(50)

當我們執行查詢視圖操作,發現返回的是未修改myTable表結構前的字段ID,即少了newCol字段:

 

 

 

            圖1.

 

分析:


 

 開始的時候,我們創建的視圖myView,

‘create view myView As select * from myTable’

sql server 會把中myTable的所有字段(即修改結構前的ID字段)存儲在系統表中,形成一個持久元數據。針對視圖對象,我們可以通過系統視圖查詢sys.objects & sys.columns來查詢:

select b.*
    from sys.objects a
        inner join sys.columns b on b.object_id=a.object_id
    where a.name='myView'

 

                                                                                              圖2.

在圖2.我們可以看到視圖返回的字段,包含字段名,數據類型,長度,精度,是否為null等信息,如果我們查回myTable中的ID字段信息,會發現與視圖的描述一致:

select b.*
    from sys.objects a
        inner join sys.columns b on b.object_id=a.object_id
    where a.name='myTable'

 

 

                                                                                            圖3

如果,我們修改了myTable表結構,會發現sys.columns沒有同時更新,查詢的結果與圖2一致。也是說視圖對象myView的持久元數據沒有更新到,我們查詢視圖的結構還是修改前的。

 

解決:


 

 

針對問題,sql server 專門一個系統存儲過程來更新視圖對象的元數據sp_refreshview   :

sp_refreshview [ @viewname = ] 'viewname' 

 或使用系統存儲過程:sp_refreshsqlmodule   

sys.sp_refreshsqlmodule [ @name = ] 'module_name' 
    [ , [ @namespace = ] ' <class> ' ]

 

擴展


 這里我寫了一個通用的存儲過程來更新類似的問題,實現功能是:

更新當前數據庫中指定的非綁定到架構的存儲過程、用戶定義函數、視圖、DML 觸發器的元數據

use master
go
if object_id('sp_RefreshSqlModule_All') Is not null
    Drop proc sp_RefreshSqlModule_All
go
create proc sp_RefreshSqlModule_All
As
/*更新當前數據庫中指定的非綁定到架構的存儲過程、用戶定義函數、視圖、DML 觸發器的元數據*/

declare @sql nvarchar(max)

select @sql=isnull(@sql+Char(13)+char(10),'')+'exec sys.sp_refreshsqlmodule '''+quotename(b.name)+'.'+quotename(a.name)+''';'
    from sys.objects a 
        inner join sys.schemas b on b.schema_id=a.schema_id
    where a.type in ('P','V','TR','FN','IF','TF')
        and a.is_ms_shipped=0
        and a.name <>'sp_RefreshSqlModule_All'
        and not exists(select 1 
                            from sys.extended_properties x
                            where x.major_id=a.object_id
                                and x.minor_id=0
                                and x.class=1
                                and x.name='microsoft_database_tools_support'
                        )

exec(@sql)
print '已更新存儲過程,用戶定義函數,視圖,DML觸發器的元數據!'    
go

exec sp_ms_marksystemobject 'sp_RefreshSqlModule_All'
go

 

‘exec sp_ms_marksystemobject 'sp_RefreshSqlModule_All'’ 注冊為系統對象,這樣在每一個數據庫下都可以靈活調用。

調用方法:

該存儲過程已在下面環境測試通過:

SQL Server 2005/2005/2008R2/2012

注:不支持SQL Server 2000

 

 

 

 

 

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM