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 秒实验
CREATE VIEW IF NOT EXISTS v AS …在 v 已存在时会做什么?- 「先删再建」比
CREATE OR REPLACE多两个什么代价? - 改完视图怎么确认没把别人的查询弄坏?
常见误区
- 以为
IF NOT EXISTS是「替换」。 它是「跳过」,改动根本没生效,还不报错。 - 直接「先删再建」不加事务。 中间那一刻视图不存在,并发查询会报错。
- 改视图不搜调用方。 删一列、改个名,依赖它的报表和程序全崩。
自测三问(点开对答案)
1. 本沙箱能直接改视图定义吗? —— 不能。`ALTER VIEW` 和 `CREATE OR REPLACE VIEW` 都不支持,只能 `DROP VIEW` 再 `CREATE VIEW`。 2. `CREATE VIEW IF NOT EXISTS` 和 `CREATE OR REPLACE VIEW` 差在哪? —— 前者已存在就跳过(不改动),后者已存在就替换。前者容易让人误以为改动生效了。 3. 「先删再建」的两个代价是什么? —— 中间有一小段视图不存在的空窗,并发查询会报错;权限、注释这些附属信息会丢。改完了,还剩「删」。下一篇 11.4 删除视图——只删规则,不删数据。
- ☐ (本篇完,下一篇 11.4 删除视图)