我们有一个像这样定义的视图
CREATE VIEW aView as
SELECT * from aTable Where <bunch of conditions>;
视图的“值”在where-condition中,因此在这种情况下可以使用Select *
。
当新列添加到基础表时,我们必须使用
重新定义视图CREATE OR REPLACE FORCE VIEW aView as
SELECT * from aTable Where <bunch of conditions>;
因为Select *
似乎被“翻译”到视图(重新)定义时出现的所有列。
我的问题:我们怎样才能避免这一额外的步骤? (如果答案取决于RDBMS,我们使用的是Oracle。)
答案 0 :(得分:4)
我知道您指定了Oracle,但SQL Server中的行为是相同的。
使用新列更新视图的一种方法是使用:
exec sp_refreshview MyViewName
go
当然,我也同意其他关于在视图定义中不使用SELECT *的评论。
答案 1 :(得分:3)
Oracle中必须执行此额外步骤:您必须手动重新编译视图。
正如您所注意到的,创建视图后会丢失“*”:
SQL> create table t (id number);
Table created
SQL> create view v as select * from t;
View created
SQL> select text from user_views where view_name = 'V';
TEXT
-------------------------------------------------------
select "ID" from t
答案 2 :(得分:1)
您不应在视图中使用*
。 明确指定列。
通过这种方式,您只需检索所需的数据,从而避免潜在的问题,即有人向您不希望该视图返回的表添加列(例如,会产生负面影响的大型二进制列性能)。
是的,您需要重新编译视图以添加另一列,但这是正确的过程。这样就可以避免其他编译问题,例如,如果视图引用了两个表,并且有人在其中一个表中添加了重复的列名。如果您没有使用表别名为该列的引用添加前缀,则编译器将确定引用哪些列的问题,或者如果结果中存在重复的列名称,则可能会抱怨。
答案 3 :(得分:0)
扩展模型时会自动更新视图以添加列,例如
SELECT a.*, std_name_format(a.first_name, a.middle_names, a.last_name) long_name
甚至
SELECT a.*, b.* from table_a a join table_b b....
如果您只有 SELECT * FROM table 的视图,那么您可能应该使用同义词或直接寻址表。
如果视图隐藏行( SELECT * FROM table WHERE ... ),那么您可以查看各种称为细粒度访问控制(FGAC),行级安全性(RLS)的功能)或虚拟专用数据库(VPD)。
您可以使用DDL触发器执行某些操作,但这会变得复杂。