Skip to content

sql-drop-view

SQL - 删除视图和从视图中删除数据

Section titled “SQL - 删除视图和从视图中删除数据”

在 SQL 中,区分完全移除视图的定义和通过视图移除数据非常重要。DROP VIEW 语句删除视图对象本身,而 DELETE 语句从视图的底层基表中删除行。

关键区别:DROP VIEW 删除保存的查询对象。DELETE FROM my_view 从视图所基于的表中删除行。视图的定义保持不变。

DROP VIEW 语句用于从数据库中完全删除现有视图。当视图被删除时,其定义和所有相关权限都将被永久删除。

要删除视图,您通常需要对该视图拥有适当的权限,例如 DROP 或 ALTER 权限。

基本语法非常直接:

DROP VIEW view_name;

首先,让我们设置一个基表和几个视图。

CREATE TABLE employees (
employee_id INT PRIMARY KEY,
first_name VARCHAR(100) NOT NULL,
last_name VARCHAR(100) NOT NULL,
department VARCHAR(50),
salary DECIMAL(10, 2)
);
INSERT INTO employees VALUES
(1, 'Alice', 'Smith', 'Engineering', 90000),
(2, 'Bob', 'Johnson', 'Engineering', 85000),
(3, 'Charlie', 'Brown', 'HR', 65000);
-- 创建一些视图
CREATE VIEW v_engineers AS SELECT * FROM employees WHERE department = 'Engineering';
CREATE VIEW v_hr_staff AS SELECT * FROM employees WHERE department = 'HR';
CREATE VIEW v_all_staff AS SELECT employee_id, first_name, last_name FROM employees;

现在,让我们删除 v_hr_staff 视图。

DROP VIEW v_hr_staff;

此命令执行后,任何尝试查询 v_hr_staff 都将导致错误,因为该视图已不存在。底层 employees 表不受影响。

如果您尝试删除一个不存在的视图,数据库将返回错误。这在自动化脚本中可能会造成问题。IF EXISTS 子句(大多数现代 RDBMS 都支持)通过仅在视图存在时才尝试删除它来优雅地解决此问题。

DROP VIEW IF EXISTS view_name;
-- 这将因为视图不存在而失败并报错。
DROP VIEW v_non_existent_view;
-- 错误:视图“v_non_existent_view”不存在
-- 这将成功执行(带有通知/警告)并无任何操作。
DROP VIEW IF EXISTS v_non_existent_view;
-- 查询正常,0 行受影响,1 个警告

您可以在视图上使用 DELETE 语句,从其底层的基表中删除行。但是,这只有在视图被认为是“可更新的”情况下才可能实现。

DELETE FROM view_name WHERE condition;

示例:通过可更新视图删除数据

Section titled “示例:通过可更新视图删除数据”

我们之前创建的 v_engineers 视图是可更新的。让我们通过它删除一名员工。

-- 此语句将从底层的 `employees` 表中删除 Bob Johnson 的行。
DELETE FROM v_engineers WHERE employee_id = 2;
-- 验证基表中的更改
SELECT * FROM employees;

DELETE 命令执行后,employees 表将不再包含 Bob Johnson 的记录。

理解可更新视图和不可更新视图

Section titled “理解可更新视图和不可更新视图”

视图并非总是可更新(或可删除)的。通常,只有当数据库能够明确确定基表中需要修改的行时,视图才被认为是可更新的。规则很复杂,并且可能因数据库系统而异,但通常,如果视图包含以下内容,则它不可更新:

  • 联接(FROM 子句中有多个表)
  • 聚合函数(SUM()、COUNT()、AVG() 等)
  • 窗口函数(ROW_NUMBER()、RANK() 等)
  • GROUP BY 或 HAVING 子句
  • DISTINCT
  • 集合运算符,如 UNION、INTERSECT 或 EXCEPT
  • 计算列(例如,SELECT salary * 1.1 AS increased_salary)

让我们创建一个计算每个部门平均薪资的视图。此视图不可更新。

CREATE VIEW v_avg_salary_by_dept AS
SELECT department, AVG(salary) as average_salary
FROM employees
GROUP BY department;
-- 此命令将失败,因为视图不可更新。
DELETE FROM v_avg_salary_by_dept WHERE department = 'Engineering';
-- 错误:无法从视图“v_avg_salary_by_dept”中删除