为什么要刷新视图
目录
1.问题描述
有时候会出现这样的情况:从视图中select 出的数据和直接用创建视图的语句选出的数据有差异。
很多人第一次遇到此情况时,会非常惊讶,是不是SQL Server有Bug,其实其他数据库管理系统照样需要刷新,这可能涉及到数据库的底层实现逻辑,我们End User就不用太关心了,只要知道视图只是存储定义的Select语句和所依赖表的MegaData就可以了。
2.问题再现
-- 创建基础表
IF OBJECT_ID('Mytable','U') IS NOT NULL
DROP TABLE MyTable
GO
CREATE TABLE MyTable
(
colA CHAR(3),
colB CHAR(4),
colC CHAR(5),
colD CHAR(6)
)
GO
-- 插入测试数据
INSERT INTO MyTable
SELECT '1','2','3','4' UNION ALL
SELECT 'a','b','c','d' UNION ALL
SELECT 'w','x','y','z' UNION ALL
SELECT 'one','two','three','four'
GO
-- 创建视图
IF OBJECT_ID('MyView','V') IS NOT NULL
DROP VIEW MyVIew
GO
CREATE VIEW MyVIew AS SELECT * FROM MyTable
GO
运行 SELECT * FROM MyVIew ,一切正常:
更改MyTable的结构信息:
ALTER TABLE MyTable ALTER COLUMN colA varchar(3)
ALTER TABLE MyTable ADD ColE varchar(10)
再运行 SELECT *FROM MyVIew ,结果居然还是老样子!
而运行视图的定义:SELECT * FROM MyTable ,结果是预期中的:
对比一下MyTable 和 MyView的结构信息(sp_help ‘MyTable’ 、 sp_help ‘MyView’),会发现MyViews仍保持原样:
而Table已更新:
3.问题解决
用原来的定义重新ALTER一下,或刷新视图
ALTER VIEW MyVIew AS SELECT * FROM MyTable
或
sp_refreshview 'MyView'
4.小结
-
当更改视图所依赖的对象时,应刷新视图,否则查询视图时,可能会生成意外的结果;
-
不要在视图中用 SELECT *,这样可以一定程度上避免产生意外结果;
-
根据实情情况,如果基础表确定不会修改结构或修改结构是非法的,可以创建绑定到架构的视图。
附:刷新所有视图的代码:
DECLARE @sql VARCHAR( max),@quote VARCHAR( 10)
SET @quote = '''';
SELECT @sql = ISNULL(@sql ,'') + 'exec sp_refreshview ' + @quote + [name] + @quote + CHAR(13)
FROM sys .views
EXEC (@sql )