MySQL视图如何工作?

时间:2010-05-20 22:13:26

标签: sql mysql sql-view

当我创建一个视图时,我基本上创建了一个新表,当它加入的一个表中的数据发生变化时,它将自动被处理;那是对的吗?

为什么我不能在视图中使用子查询?

3 个答案:

答案 0 :(得分:51)

视图就像表一样,但它不是表。它永远不存在;它只是在引用视图名称时运行的准备好的SQL语句。 IE:

CREATE VIEW foo AS
  SELECT * FROM bar

SELECT * FROM foo

......相当于跑步:

SELECT x.* 
  FROM (SELECT * FROM bar) x

MySQLDump永远不会包含要插入视图的行...

  

为什么我不能在我的视图中使用子查询????

遗憾的是,这是(尽管有问题的)设计。 MySQL视图有许多限制,记录在案:http://dev.mysql.com/doc/refman/5.0/en/create-view.html

因此,如果它只是一个虚构的表/预处理语句,那么它在理论上与普通表/查询具有相同的性能(甚至更低)吗?


没有。
表可以关联索引,这可以使数据检索更快(插入/更新需要一些成本)。一些数据库支持“物化”视图,这些视图可以应用索引 - 鉴于视图功能有限(仅在v5中开始),MySQL 不支持这不应该是一个惊喜IIRC,比赛很晚)。

因为视图是派生表,所以视图的性能仅与构建它的查询一样好。如果该查询很糟糕,那么性能问题就会滚雪球...也就是说,在查询视图时 - 如果WHERE子句中的视图列引用未包含在函数中(IE:WHERE v.column LIKE ... WHERE LOWER(t.column) LIKE ...),优化器可以将标准(称为谓词)推送到原始查询上 - 使其更快。

答案 1 :(得分:2)

我也遇到了同样的问题(令我惊讶的是,因为我的搜索似乎表明Oracle和MS都支持它)。

我通过为我的最终视图创建两个额外的视图来解决这个限制(至少现在,直到证明不可用)。

示例:

CREATE VIEW Foo1 AS
    SELECT * FROM t ORDER BY ID, InsertDate DESC

CREATE VIEW Foo2 AS
    SELECT * FROM Foo1 GROUP BY ID

CREATE VIEW Foo AS
    SELECT * FROM Foo2 ORDER BY ID

上面的示例基本上有一个表't',它是一个包含所有修订的时态表。我的'Foo'(视图)基本上只是我对每条记录的最新版本的简单视图。现在似乎工作正常!

更新

我不知道这是否是MySQL 5.1中的另一个错误,但上面的例子实际上并不起作用! 'Foo1'按预期工作,但'Foo2'似乎忽略了分组前的顺序,所以我的最终结果不是预期的。如果我为'ASC'改变'DESC'(令人惊讶的话),我甚至得到相同的结果。

另外,如果您阅读 17.5.1。查看语法部分,它明确指出:

  

“可以从多种SELECT语句创建视图。它可以引用基表或其他视图。它可以使用连接,UNION和子查询。”

我要将我的数据库更新为5.6并再试一次!

答案 2 :(得分:2)

区别在于:

对于视图,你只能在where - part中有子查询,而不是在from - part中这样一个

CREATE VIEW v AS SELECT * FROM foo WHERE id IN (SELECT id FROM bar) 

可以工作 - 但同时你得到一个只读视图......单个表上的简单视图将允许通过视图更新到基础表