必须由具有CREATE ANY DIRECTORY权限的用户执行,如SYS或sqlplus / as sysdba连接的用户;普通DBA角色用户即使拥有DBA角色也无法创建,因该权限需显式授予而非角色继承。
外部表在 oracle 21c 中依赖 directory 对象,但直接 create directory 后仍无法读取文件,90% 的问题出在权限、路径校验或用户上下文上——不是语法错,而是环境没对齐。
用谁执行 CREATE DIRECTORY 才不报 ORA-01031
必须由具有 CREATE ANY DIRECTORY 权限的用户执行,普通 DBA 角色(哪怕有 DBA 角色)也不行。SYS 用户可以,但更稳妥的是用 sqlplus / as sysdba 连接后操作。
- 不要用应用用户(如
app_user)连上去就写CREATE DIRECTORY,一定报ORA-01031: insufficient privileges - 确认权限是显式授予的:
SELECT * FROM dba_sys_privs WHERE privilege = 'CREATE ANY DIRECTORY';,不能只查ROLE_SYS_PRIVS - RAC 环境下,该语句只需在任一节点执行一次,目录对象即全局可见
路径字符串写错导致 UTL_FILE 或外部表静默失败
Oracle 不做路径归一化,'/u01/data' 和 '/u01/data/' 是两个完全不同的目录;Linux 下大小写敏感,Windows 下不敏感但建议统一小写。
- 操作系统路径必须真实存在:
ls -ld /u01/data要能列出,且属主/属组为oracle:oinstall - Oracle 进程(通常是
oracle用户)必须对该路径有r-x(READ 需要)或rwx(WRITE 需要),仅靠755不够,需确认实际运行用户身份 - 外部表定义中
LOCATION ('data.csv')的文件名是相对于 DIRECTORY 路径的,不支持../向上跳转,否则运行时报KUP-04050
GRANT READ/WRITE 时常见权限误配
GRANT EXECUTE ON DIRECTORY 是无效语法,会立刻报 ORA-00990: missing or invalid privilege。外部表只认 READ,UTL_FILE 写文件至少要 WRITE,两者不可互换。
- 只读场景(如外部表查询):只需
GRANT READ ON DIRECTORY my_dir TO app_user; - 写文件场景(如
UTL_FILE.FOPEN(..., 'w')):必须含WRITE,GRANT WRITE ON DIRECTORY my_dir TO app_user; - Data Pump(
expdp)需要READ(读 dump 文件)和WRITE(写日志/转储),缺一不可 - 权限生效后,目标用户无需重新连接,但已有会话中的包状态(如已编译的存储过程)不会自动重载
验证 DIRECTORY 是否真正可用
别只查 dba_directories 就认为万事大吉。不同组件校验时机不同:外部表建表时只校验对象存在,真正 SELECT 才访问文件;UTL_FILE.FOPEN 则在调用瞬间校验路径可写性。
- 快速验证读能力:
SELECT * FROM all_directories WHERE directory_name = 'MY_DIR';+SELECT * FROM dba_tab_privs WHERE table_name = 'MY_DIR' AND privilege = 'READ'; - 模拟外部表读取:
BEGIN UTL_FILE.FOPEN('MY_DIR', 'test.txt', 'r'); END;—— 成功则说明 READ 可用 - 注意:删掉 DIRECTORY 后,已创建的外部表仍能
DESC,但SELECT必报ORA-29400: data cartridge error KUP-04063
最易被忽略的一点:Oracle 21c 在多租户(CDB/PDB)环境下,CREATE DIRECTORY 必须在 CDB$ROOT 中执行,但它在所有 PDB 中都可见;而赋权语句(GRANT)必须在目标 PDB 中执行,否则 PDB 内用户无法使用——跨容器权限不继承。


















