44

当我创建一个视图时,我基本上是在创建一个新表,当它连接的其中一个表中的数据发生变化时,它将自动进行事务处理;那是对的吗?

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

4

3 回答 3

58

视图像表格一样工作,但它不是表格。它永远不存在;它只是在您引用视图名称时运行的准备好的 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 IIRC 中开始,游戏非常晚,MySQL不支持这一点并不奇怪) )。

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

于 2010-05-20T22:22:26.293 回答
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”更改为“ASC”,我什至会得到相同的结果(令人惊讶)。

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

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

我要把我的数据库更新到 5.6,然后再试一次!

于 2011-08-11T05:54:47.290 回答
2

区别在于:

对于视图,您只能在 where - 部分有子查询,而不是在 from - 部分所以

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

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

于 2013-08-08T08:46:35.220 回答