Skip to content

sql-update-view

SQL 没有专门的 ALTER VIEW 或 UPDATE VIEW 命令来更改其显示的数据。相反,您使用标准的 UPDATE 语句。当您更新一个视图时,您实际上是在修改底层基础表中的数据。这只有在该视图是“可更新的”(updatable)情况下才可能实现。

重要提示:对视图执行 UPDATE 操作会修改源表的数据。视图是数据的“窗口”,而不是数据的“副本”。

语法与更新表相同:

UPDATE view_name
SET column1 = value1, column2 = value2, ...
WHERE [condition];

要使视图上的 UPDATE 操作成功,数据库必须能够将更改追溯到单个基础表中的特定行和列。如果视图包含以下内容,则通常不可更新:

  • 多个表上的连接(Joins)
  • 聚合函数(SUM、AVG 等)或 GROUP BY / HAVING 子句
  • DISTINCT
  • 窗口函数(Window Functions)
  • 集合运算符(UNION 等)
  • 您试图更新的计算列(Calculated columns)

让我们创建一个表和一个简单的、可更新的特定城市客户视图。

CREATE TABLE customers (
customer_id INT PRIMARY KEY,
name VARCHAR(255) NOT NULL,
email VARCHAR(255) UNIQUE,
city VARCHAR(100),
last_contacted_on DATE
);
INSERT INTO customers VALUES
(1, 'John Doe', 'john.d@example.com', 'New York', '2023-01-10'),
(2, 'Jane Smith', 'jane.s@example.com', 'London', '2023-02-15'),
(3, 'Peter Jones', 'peter.j@example.com', 'New York', '2023-03-20');
-- 为纽约客户创建视图
CREATE VIEW v_ny_customers AS
SELECT customer_id, name, email, last_contacted_on
FROM customers
WHERE city = 'New York';

此视图是可更新的,因为它引用了单个表,并且不包含任何复杂操作。让我们通过视图更新 Peter Jones 的邮箱。

UPDATE v_ny_customers
SET email = 'p.jones.new@example.com'
WHERE customer_id = 3;

更改会同时反映在视图和底层的 customers 表中。

-- 查询基础表以确认更改
SELECT * FROM customers WHERE customer_id = 3;
客户ID姓名邮箱城市上次联系日期
3Peter Jonesp.jones.new@example.comNew York2023-03-20

示例:尝试更新不可更新的视图

Section titled “示例:尝试更新不可更新的视图”

现在,让我们创建一个包含计算列的视图。这样的视图是不可更新的。

CREATE VIEW v_customer_summary AS
SELECT
customer_id,
name,
UPPER(city) AS city_uppercase
FROM customers;
-- 这将失败,因为 `city_uppercase` 是一个计算列。
UPDATE v_customer_summary
SET city_uppercase = 'LONDON'
WHERE customer_id = 2;

数据库将返回错误,因为它无法逆转 UPPER() 函数来更新 customers 表中的原始 city 列。

您可以一次更新多个列并影响多行,前提是视图是可更新的。请务必小心使用 WHERE 子句。

严重警告:在 UPDATE 语句中省略 WHERE 子句将修改通过视图可见的底层表中的所有行。在执行之前务必仔细检查您的 WHERE 子句。

让我们更新纽约视图中所有客户的联系日期。

-- 更新视图中所有客户的上次联系日期
UPDATE v_ny_customers
SET last_contacted_on = '2024-01-01';

此查询将更改 customers 表中 John Doe 和 Peter Jones 的 last_contacted_on 日期,因为他们是唯一满足视图条件的记录。