🦏 第11章 视图
📄 一句话概括

ALTER VIEW 本沙箱没有,报 near "VIEW"; CREATE OR REPLACE VIEW 也没有,报 near "OR"。 MySQL 两个都支持。 本沙箱只有一条路:先 DROP VIEW 再 CREATE VIEW。 代价是中间有一小段空窗,而且权限、注释会丢。 CREATE VIEW IF NOT EXISTS 不是「替换」, 是「已存在就什么都不做」——两句话长得很像,作用正好相反。

📝 本章和前面几章的关系

建、看都讲完了,这一篇讲「改」——也就是「重新定义」。 改视图比建视图危险: 建的时候没人依赖它,改的时候可能有一堆报表在用。 所以这一篇一半讲语法,一半讲纪律。

一、alter view:MySQL 有,这里没有

ALTER VIEW v_boy AS SELECT … 报 near "VIEW": syntax error。 本沙箱没有 ALTER VIEW 这个语句。 MySQL 支持 ALTER VIEW 视图名 AS 新查询, 作用和「重新定义」一样,但保留原有的权限授予—— 这一点比「删了重建」好:重建会把授权一起弄丢。

二、create or replace view:这里也没有

CREATE OR REPLACE VIEW … 报 near "OR": syntax error,视图没变。 MySQL 支持这个写法, 这是最常用的改视图方式,一句搞定。 SQLite 只有 CREATE VIEW IF NOT EXISTS, 而那个是「已存在就什么都不做」,不是「已存在就替换」。 两句话长得很像,作用正好相反—— 这是最容易记混的一处,写错时一点报错都没有,只是改动没生效。

三、所以本沙箱只有一条路:先删再建

删了重建,效果一样。 代价有两个:一是中间有一小段时间视图不存在, 这期间查它的语句会报错;二是权限、注释这些附属信息会丢。 所以「先删再建」最好包在事务里(第 18 章), 让「删」和「建」对外是一个动作——别让别的连接在中间那一刻查到「视图不存在」。 MySQL 的 create or replace 内部就是这么做的,所以它没有那个空窗。 这也说明「用一句话做完」不只是省事,还是一种正确性保证。

四、改视图前,先想清楚谁在依赖它

视图的特点就是「藏起来」: 改定义时你看不到有多少程序在查它。 删一列、改个列名,可能有一堆报表跟着崩。 两条纪律:一是改之前先搜代码里有没有引用这个视图名; 二是改完立刻拿原有的查询跑一遍——别等业务方来报错才知道。 还有一条常被忽略: 视图套视图时,改底层那个会影响上层。 第 11.5 篇会看到,两层视图很常见,改动要顺着依赖链往下看。

五、动手 Demo:两条路都撞一次,最后只能用「先删再建」

Demo 四段:撞 ALTER VIEW、撞 CREATE OR REPLACE VIEW、确认视图没变、 最后用「先删再建」真的换掉定义。 第三段那个「查出来还是旧的两列」很关键——它证明前两条语句是真失败了,不是悄悄生效。

import _q46 as Q
c = Q.con()
c.execute("CREATE VIEW v_boy AS SELECT id, name, height "
          "FROM students WHERE gender = '男'")

# ALTER VIEW:这里没有
c.execute("ALTER VIEW v_boy AS SELECT id, name FROM students")

# CREATE OR REPLACE VIEW:这里也没有
c.execute("CREATE OR REPLACE VIEW v_boy AS SELECT id, name FROM students")

# 只能先删再建
Q.run(c, "DROP VIEW v_boy")
Q.run(c, "CREATE VIEW v_boy AS SELECT id, name FROM students "
          "WHERE gender = '女'")
Q.show(c, "SELECT id, name FROM v_boy LIMIT 3")

实跑输出:

--------------------------------------------------------------------
第六十课:修改视图——两条路,这里都走不通
--------------------------------------------------------------------

  alter view:MySQL 有,这里没有
  SQL> ALTER VIEW v_boy AS SELECT id, name FROM students WHERE gender = '女'
  报错:near "VIEW": syntax error
  **报 `near "VIEW": syntax error`。** **本沙箱没有 `ALTER VIEW` 这个语句。**
  **MySQL 支持 `ALTER VIEW 视图名 AS 新查询`**,
  **作用和「重新定义」一样,但保留原有的权限授予**——
  **这一点比「删了重建」好:重建会把授权一起弄丢。**

  create or replace view:这里也没有
  SQL> CREATE OR REPLACE VIEW v_boy AS SELECT id, name FROM students WHERE gender = '女'
  报错:near "OR": syntax error
  SQL> SELECT id, name, height FROM v_boy LIMIT 2
  id     name     height
  -----------------------
  1      张伟     172.50
  4      刘洋     178.30
  (2 行)
  **报 `near "OR": syntax error`,视图没变。** **MySQL 支持 `CREATE OR REPLACE VIEW`**,
  **这是最常用的改视图写法**——一句搞定,不用先删。
  **SQLite 只有 `CREATE VIEW IF NOT EXISTS`**,**而那个是「已存在就什么都不做」**,
  **不是「已存在就替换」**。 **两句话长得很像,作用正好相反。**

  所以本沙箱只有一条路:先删再建
  SQL> DROP VIEW v_boy
  完成
  SQL> CREATE VIEW v_boy AS SELECT id, name FROM students WHERE gender = '女'
  完成
  SQL> SELECT id, name FROM v_boy LIMIT 3
  id     name
  ------------
  2      王芳
  3      李娜
  5      陈静
  (3 行)
  **删了重建,效果一样。** **代价有两个**:**一是中间有一小段时间视图不存在**,
  **这期间查它的语句会报错;二是权限、注释这些附属信息会丢。**
  **所以「先删再建」最好包在事务里**(第 18 章),**让「删」和「建」对外是一个动作**。
  **MySQL 的 `create or replace` 内部就是这么做的,所以它没有那个空窗。**

  改视图前,先想清楚谁在依赖它
  **视图的特点就是「藏起来」**:
  **改定义时你看不到有多少程序在查它。** **删一列、改个列名,可能有一堆报表跟着崩。**
  **两条纪律**:**一是改之前先搜代码里有没有引用这个视图名**;
  **二是改完立刻拿原有的查询跑一遍**——**别等业务方来报错才知道。**
  **还有一条常被忽略**:**视图套视图时,改底层那个会影响上层**。
  **第 11.5 篇会看到,两层视图很常见,改动要顺着依赖链往下看。**

第一段 ALTER VIEW 报 near "VIEW"。 第二段 CREATE OR REPLACE VIEW 报 near "OR"。 第三段查视图,还是三列、还是男生——定义一点没变。 第四段先 DROP 再 CREATE,这回换成女生,三行:王芳、李娜、陈静。

30 秒实验

  1. CREATE VIEW IF NOT EXISTS v AS … 在 v 已存在时会做什么?
  2. 「先删再建」比 CREATE OR REPLACE 多两个什么代价?
  3. 改完视图怎么确认没把别人的查询弄坏?

常见误区

  1. 以为 IF NOT EXISTS 是「替换」。 它是「跳过」,改动根本没生效,还不报错。
  2. 直接「先删再建」不加事务。 中间那一刻视图不存在,并发查询会报错。
  3. 改视图不搜调用方。 删一列、改个名,依赖它的报表和程序全崩。
自测三问(点开对答案) 1. 本沙箱能直接改视图定义吗? —— 不能。`ALTER VIEW` 和 `CREATE OR REPLACE VIEW` 都不支持,只能 `DROP VIEW` 再 `CREATE VIEW`。 2. `CREATE VIEW IF NOT EXISTS` 和 `CREATE OR REPLACE VIEW` 差在哪? —— 前者已存在就跳过(不改动),后者已存在就替换。前者容易让人误以为改动生效了。 3. 「先删再建」的两个代价是什么? —— 中间有一小段视图不存在的空窗,并发查询会报错;权限、注释这些附属信息会丢。

改完了,还剩「删」。下一篇 11.4 删除视图——只删规则,不删数据。

相关笔记