with read only 必须紧接在 select 子句之后、语句末尾,且不可与 with check option 共存;含表达式时需显式列别名;dml 在解析阶段即被拦截,不受权限影响;关键词必须为“read only”两词间有空格。

WITH READ ONLY 必须放在 AS SELECT 之后、语句末尾
只读视图不是靠权限控制,而是靠语法硬约束。Oracle 要求 WITH READ ONLY 必须紧接在 SELECT 子句之后、整个语句结束前(分号前),且不能和 WITH CHECK OPTION 共存。
常见错误:
-
CREATE OR REPLACE VIEW v_ro AS WITH READ ONLY SELECT * FROM emp;→ 报ORA-00922: missing or invalid option -
CREATE OR REPLACE VIEW v_ro AS SELECT * FROM emp WITH CHECK OPTION WITH READ ONLY;→ 报错:两者互斥 - 正确写法:
CREATE OR REPLACE VIEW v_ro AS SELECT empno, ename FROM emp WITH READ ONLY;
带计算字段或函数的视图必须显式命名列
只要 SELECT 中出现表达式(如 salary * 12)、聚合、CASE 或函数(如 UPPER(ename)),Oracle 就要求你为该列提供别名,否则 WITH READ ONLY 会因语法不完整失败。
错误示例:CREATE OR REPLACE VIEW v_pay AS SELECT emp_id, salary * 12 FROM employees WITH READ ONLY; → 报 ORA-00998: must name this expression with a column alias
两种合法写法:
CREATE OR REPLACE VIEW v_pay AS (emp_id, annual_salary) SELECT emp_id, salary * 12 FROM employees WITH READ ONLY;CREATE OR REPLACE VIEW v_pay AS SELECT emp_id, salary * 12 AS annual_salary FROM employees WITH READ ONLY;
DML 操作在解析阶段就被拦截,与用户权限无关
WITH READ ONLY 的拦截发生在 SQL 解析器层面,不是权限检查环节。这意味着:
- 即使你是
SYS用户,对只读视图执行INSERT/UPDATE/DELETE也会立刻报ORA-42399: cannot perform a DML operation on a read-only view - 哪怕底层表有完整 DML 权限,也完全无效
- 通过同义词(
CREATE SYNONYM s FOR v_ro)访问,同样被拒 - 不生成执行计划,不进优化器,不触发表触发器
别把 WITH READ ONLY 写成 WITH READONLY 或 WITH READ_ONLY
这是大小写不敏感但单词结构敏感的关键词。Oracle 只认两个独立单词 READ ONLY,中间必须有空格。
以下全部非法:
-
WITH READONLY→ORA-00922 -
WITH READ_ONLY→ORA-00922 -
WITH read only(小写)→ 合法,Oracle 不区分大小写
真正容易被忽略的是:这个限制无法绕过,也不受角色、同义词、甚至 DBA 身份影响——它是一条写死在语法解析器里的铁律。











