原文:
你是否也忘了刷新視圖?
得到結果:
然后再來執行一下視圖:
得到結果:
然后再執行查詢視圖的語句:
眼前一亮,得到結果:
再執行:
會得到以下的錯誤:
下面語句中時竟然能查出來,證明定義的時候有問題,所以這一步也同時可以檢查一下會不會存在問題對象。順帶說一句,上面的腳本是把需要刷新的視圖拼接出來,然后一次性執行。
起因:
? ? ? ? ?由于工作原因,我隔幾天就要執行一批開發人員提供過來的腳本,部分是新需求的開發,部分是修復bug。往往包含有幾百個。我用工具批量執行之后,系統繼續運行,后來反反復復會有這樣那樣的錯誤,其中一個,經過開發人員的檢查,是因為視圖沒刷新。
? ? ? ? ?對此我納悶了很久,視圖不就是一堆select語句嗎?怎么還要刷新?難道表改了不會跟著改?為此,我首先自己做一個實驗,發現的確不會馬上改過來,至于啥時候才更改,也不清楚,聽說從2000的時候,這個問題已經存在,看來我孤陋寡聞了。
測試:
?步驟一:首先執行下面語句
USE tempdb GO --創建表 IF OBJECT_ID('testTB') IS NOT NULL DROP TABLE testTB GO CREATE TABLE testTB ( id INT, NAME VARCHAR(10) ) --插入測試數據 INSERT INTO testTB SELECT 1,'a' UNION ALL SELECT 2,'b' UNION ALL SELECT 3,'c' IF OBJECT_ID('V_testTB') IS NOT NULL DROP VIEW V_testTB GO CREATE VIEW V_testTB AS SELECT * FROM testTB go SELECT * FROM V_testTB

步驟二:更改表結構
--添加一列 ALTER TABLE testTB ADD age INT
然后再來執行一下視圖:
SELECT * FROM V_testTB
得到結果:

反復執行了10次,結果還是沒變。
步驟三:使用存儲過程刷新視圖
sp_refreshview V_testTB
然后再執行查詢視圖的語句:
SELECT * FROM V_testTB
眼前一亮,得到結果:

可以看出,結構已經刷新,證明有效果了。
分析:
? ? ? ? 細心的人應該發現,其實視圖里面我用了*號。可以通過實驗來證明,如果不用星號,是沒問題的。而如果指定了列名,那么在新加一列的時候,管它有沒有刷新,都不會有問題,因為你壓根就不會用到這列,那么如果是刪除呢?現在來試試,建表的代碼依舊,把原有的添加列的代碼改成刪除列,另外*號依舊保留:
--刪除一列 ALTER TABLE testTB DROP COLUMN id
再執行:
SELECT * FROM V_testTB
會得到以下的錯誤:

證明刪除是會報錯的,不需要刷新,那么估計大家也猜到,就算指定列,也會報錯,現在來證實一下:

這次報錯是這個,部分代碼我就不寫了。
總結:
根據上面的實驗,可以得出:
?1、視圖里面盡可能不要出現*號。*號不僅對性能有影響,也不便于結構的更新。
? ? ? ?
?2、無論視圖所涉及的表結構有無修改,每次執行腳本后,刷新一下,總是好的。并且我遇到過這樣的情景,一個名字是存儲過程的名字,但是在使用:
SELECT DISTINCT 'EXEC sp_refreshview ''' + name + '''' FROM sys.objects AS so INNER JOIN sys.sql_expression_dependencies AS sed ON so.object_id = sed.referencing_id WHERE so.type = 'V' AND sed.referenced_id = OBJECT_ID('testTB') ;
下面語句中時竟然能查出來,證明定義的時候有問題,所以這一步也同時可以檢查一下會不會存在問題對象。順帶說一句,上面的腳本是把需要刷新的視圖拼接出來,然后一次性執行。
更多文章、技術交流、商務合作、聯系博主
微信掃碼或搜索:z360901061

微信掃一掃加我為好友
QQ號聯系: 360901061
您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點擊下面給點支持吧,站長非常感激您!手機微信長按不能支付解決辦法:請將微信支付二維碼保存到相冊,切換到微信,然后點擊微信右上角掃一掃功能,選擇支付二維碼完成支付。
【本文對您有幫助就好】元
