用规则在PostgreSQL中创建可查询插入修改删除的表视图

本文介绍了如何使用规则在PostgreSQL数据库中创建一个不仅可查询,还能进行插入、修改和删除操作的表视图。通过这种方式,可以方便地管理和操作数据。

用规则在PostgreSQL中创建可查询插入修改删除的表视图

具体内容如下:
要注意 new.attribute和old.attribute 与源表、视图属性之间的关系
[root@me root]# su postgres
bash-2.05b$ psql -E -h me.linux.edu.cn mydb1
********* QUERY **********
BEGIN; SELECT usesuper FROM pg_catalog.pg_user WHERE usename = 'postgres'; COMMIT
**************************

欢迎来到 psql 7.3.2, PostgreSQL 的交互终端.

键入:  /copyright 获取发布信息
       /h 获取 SQL 命令的帮助
       /? 获取内部反斜扛命令的帮助
       /g 或者以分号结尾执行查询
       /q 退出

mydb1=# /help
Available help:
  ABORT                     CREATE TABLE              EXECUTE
  ALTER DATABASE            CREATE TABLE AS           EXPLAIN
  ALTER GROUP               CREATE TRIGGER            FETCH
  ALTER TABLE               CREATE TYPE               GRANT
  ALTER TRIGGER             CREATE USER               INSERT
  ALTER USER                CREATE VIEW               LISTEN
  ANALYZE                   DEALLOCATE                LOAD
  BEGIN                     DECLARE        &nbs
### ❓问题: **视图 `v_em` 中无法插入删除数据,为什么?** --- ### ✅ 答案简述: 视图 `v_em` 无法插入INSERT)或删除DELETE),是因为它 **不满足“可更新视图”的条件**。数据库系统对通过视图进行数据修改有严格限制,只有在特定情况下才允许。 --- ## 🔍 详细解释 SQL 规定:**并非所有视图都支持 INSERTUPDATEDELETE 操作**。能否操作取决于视图的定义方式。 我们来分析可能导致 `v_em` 无法插入/删除的常见原因,并结合示例说明。 --- ## 🧩 常见导致视图不可更新的原因 | 原因 | 是否阻止 INSERT/DELETE | 示例 | |------|------------------------|------| | 1. 视图包含聚合函数(如 COUNT, SUM) | ✅ 是 | 统计员工数量的视图 | | 2. 使用了 GROUP BY 或 HAVING | ✅ 是 | 分组统计类视图 | | 3. 包含 JOIN 多连接 | ✅ 可能是 | 关联员工与部门 | | 4. 使用 DISTINCT 去重 | ✅ 是 | `SELECT DISTINCT ...` | | 5. 子查询出现在 FROM 中(派生) | ✅ 是 | `(SELECT ...) AS t` | | 6. 使用 UNION / UNION ALL | ✅ 是 | 合并多个查询结果 | | 7. SELECT 列中缺少基主键 | ⚠️ 可能影响 | 插入时需保证唯一性 | | 8. 视图定义中使用了达式或计算列 | ⚠️ 部分限制 | 如 `salary * 1.1 AS new_salary` | --- ## ✅ 示例场景分析 假设 `v_em` 定义如下: ### ❌ 场景一:包含 JOIN 的多视图(最常见) ```sql CREATE VIEW v_em AS SELECT e.employeeID, e.empName, e.deptID, d.deptName FROM employee e JOIN department d ON e.deptID = d.departmentID; ``` 👉 尝试删除: ```sql DELETE FROM v_em WHERE employeeID = '1001'; -- ❌ 失败或不允许 ``` 📌 原因: - 虽然数据来自 `employee` ,但视图涉及两个。 - 数据库无法确定应该从哪个删除,或者是否会影响关联逻辑。 - 因此大多数数据库默认禁止此类操作。 > ✅ 特殊情况:MySQL 在某些条件下允许更新单个基,但仍有限制。 --- ### ❌ 场景二:带聚合函数的统计视图 ```sql CREATE VIEW v_em AS SELECT deptID, COUNT(*) AS emp_count FROM employee GROUP BY deptID; ``` 👉 尝试插入: ```sql INSERT INTO v_em (deptID, emp_count) VALUES ('1', 5); -- ❌ 错误! ``` 📌 原因: - 这是一个汇总视图,没有对应的实际行可以插入。 - `COUNT(*)` 是计算出来的,不能反向写入。 --- ### ❌ 场景三:使用了 DISTINCT ```sql CREATE VIEW v_em AS SELECT DISTINCT empName, deptID FROM employee; ``` 👉 不允许 DELETEINSERT,因为可能存在重复映射,语义模糊。 --- ## ✅ 如何判断一个视图是否可更新? ### 方法一:查看视图定义是否简单 满足以下条件的视图通常是 **可更新的**: ✅ 可更新视图的要求(以 MySQL 为例): - 基于单一(不能是 JOIN) - 不含子查询(尤其在 FROM 中) - 不使用 DISTINCT、UNION、GROUP BY、HAVING - 不包含聚合函数(SUM, COUNT, AVG 等) - 不包含计算列(如 `price * qty`) - 必须包含基的主键字段(推荐) 例如这个视图就是可更新的: ```sql CREATE VIEW v_em_simple AS SELECT employeeID, empName, deptID, salary FROM employee WHERE salary > 5000; ``` 👉 即使加了 WHERE 条件,也可以执行: ```sql DELETE FROM v_em_simple WHERE employeeID = '1001'; INSERT INTO v_em_simple VALUES ('1002', '李四', '1', 6000); ``` 只要新插入的数据满足 `salary > 5000`,就能成功。 --- ## 🔍 如何检查你的 `v_em` 视图结构? 运行以下命令查看定义: ### MySQL: ```sql SHOW CREATE VIEW v_em; ``` ### PostgreSQL: ```sql \d v_em -- 或 SELECT definition FROM pg_views WHERE viewname = 'v_em'; ``` ### SQL Server: ```sql sp_helptext 'v_em'; ``` 🔍 查看输出中的 `SELECT` 语句是否有上述“不可更新”的特征。 --- ## ✅ 解决方案:如何实现“看似”通过视图修改数据? ### 方案一:使用 `INSTEAD OF` 触发器(适用于 PostgreSQLOracle、SQL Server) ```sql -- PostgreSQL 示例 CREATE OR REPLACE FUNCTION insert_v_em() RETURNS TRIGGER AS $$ BEGIN INSERT INTO employee (employeeID, empName, deptID) VALUES (NEW.employeeID, NEW.empName, NEW.deptID); RETURN NEW; END; $$ LANGUAGE plpgsql; CREATE TRIGGER instead_of_insert_v_em INSTEAD OF INSERT ON v_em FOR EACH ROW EXECUTE FUNCTION insert_v_em(); ``` 这样即使视图本身不可更新,也能通过触发器拦截操作并手动处理。 > ⚠️ 注意:MySQL 不支持 `INSTEAD OF` 触发器,只能用其他方法绕行。 --- ## ✅ 总结 | 问题 | 回答 | |------|------| | 为什么 `v_em` 无法插入/删除? | 因为它的定义违反了“可更新视图”的规则(如含 JOIN、GROUP BY、DISTINCT 等) | | 所有视图都不能改吗? | 否,基于单且无复杂操作的视图是可以更新的 | | 如何修复? | 修改视图为简单结构,或使用触发器模拟更新行为 | | 如何避免这类问题? | 创建视图前明确用途:展示用 vs. 可编辑用 | ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值