ORA-39109: Unprivileged users may not operate upon other users' schemas

本文介绍了解决在Oracle数据库中导出多个用户下部分表遇到的权限错误的方法。通过授予用户必要的系统权限,成功实现了数据导出。
Connected to: Oracle Database 10g Enterprise Edition Release 10.2.0.5.0 - Production
With the Partitioning, OLAP, Data Mining and Real Application Testing options
ORA-31631: privileges are required

ORA-39109: Unprivileged users may not operate upon other users' schemas


1.操作语句,目标是导出多个用户下面的部份表,

SQL> select * from v$version
  2  ;

BANNER
----------------------------------------------------------------
Oracle Database 10g Enterprise Edition Release 10.2.0.4.0 - 64bi
PL/SQL Release 10.2.0.4.0 - Production
CORE    10.2.0.4.0      Production
TNS for IBM/AIX RISC System/6000: Version 10.2.0.4.0 - Productio
NLSRTL Version 10.2.0.4.0 - Production

------------------------------------------------------------------

COMMAND:

expdp user/pwd  directory=DUMP_DIR  ESTIMATE=STATISTICS LOGFILE=001.log dumpfile=010.dmp  parfile=02.par


[oracle@GXDB1] $vi 02.par
"02.par" 5 lines, 76 characters
schemas=FDCK,FDCZM,FDCZ
include=table:"in (
'CC_CLUSTER',
'FF_IFMI'
)"

----------------------

soluation:

GRANT RESUMABLE TO UHG_TEST;
GRANT BACKUP ANY TABLE TO UHG_TEST;
GRANT EXECUTE ANY TYPE TO UHG_TEST;
GRANT SELECT ANY TABLE TO UHG_TEST;
GRANT READ ANY FILE GROUP TO UHG_TEST;
GRANT SELECT ANY SEQUENCE TO UHG_TEST;
GRANT EXECUTE ANY PROCEDURE TO UHG_TEST;
BEGIN
SYS.DBMS_RESOURCE_MANAGER_PRIVS.GRANT_SYSTEM_PRIVILEGE
(GRANTEE_NAME   => 'UHG_TEST',
 PRIVILEGE_NAME => 'ADMINISTER_RESOURCE_MANAGER',
 ADMIN_OPTION   => FALSE);
END;
/

grant EXP_FULL_DATABASE  ***--不要忘记这个。。

`ORA-01799: a column may not be outer-joined to a subquery` 是 Oracle 中一个常见但容易混淆的错误,它表示:**你试图将一个列通过外连接(`OUTER JOIN`)关联到一个子查询,这是不允许的语法。** --- ### ❌ 错误示例 ```sql SELECT A.NAME, B.AMOUNT FROM TABLE_A A LEFT JOIN ( SELECT CUSTOMER_ID, SUM(AMOUNT) AS AMOUNT FROM TABLE_B GROUP BY CUSTOMER_ID ) B ON A.ID = B.CUSTOMER_ID(+) ``` > 注意:`B.CUSTOMER_ID(+)` 这种写法是 **错误的**! 你不能在外连接中对 **子查询中的字段使用 `(+)` 操作符** —— 这正是触发 `ORA-01799` 的原因。 虽然你的意图可能是想做左连接,但 Oracle 不允许在子查询字段上使用 `(+)` 外连接符号。 --- ### ✅ 正确做法:使用标准 `LEFT JOIN` 语法 Oracle 支持 ANSI SQL 标准的 `JOIN` 语法。你应该 **移除 `(+)` 符号**,并正确使用 `LEFT JOIN`: ```sql SELECT A.NAME, B.AMOUNT FROM TABLE_A A LEFT JOIN ( SELECT CUSTOMER_ID, SUM(AMOUNT) AS AMOUNT FROM TABLE_B GROUP BY CUSTOMER_ID ) B ON A.ID = B.CUSTOMER_ID; ``` ✅ 这样就完全合法,不会报错。 --- ### 为什么会出现这个错误? #### 原因分析: - Oracle 的旧式外连接语法使用 `(+)`,但它有严格限制: - `(+)` 只能用于 **基础表(base table)的列**。 - 不能用于 **视图、子查询、物化视图或内联视图(inline view)中的列**。 - 当你在子查询的结果字段上加了 `(+)`,Oracle 就会抛出 `ORA-01799`。 #### 常见误用场景: ```sql -- ❌ 错误:对子查询字段使用 (+) LEFT JOIN (SELECT ... FROM ...) B ON A.ID = B.ID(+) -- ❌ 错误:混合使用 ANSI 和 (+) FROM A, B WHERE A.ID = B.ID(+) AND B.STATUS IN (SELECT ...) -- 子查询本身没问题,但如果前面用了 (+) 关联子查询就会出问题 ``` --- ### ✅ 解决方案总结 | 方法 | 说明 | |------|------| | ✅ 使用 ANSI `LEFT JOIN` | 推荐方式,清晰、标准、支持子查询 | | ✅ 移除所有 `(+)` | 特别是在涉及子查询、视图时 | | ✅ 把逻辑重构为嵌套子查询 | 如果必须保留老语法(不推荐) | --- ### 更复杂的修复示例(带条件过滤) 假设你想实现:“即使没有匹配记录,也要显示用户,并显示其最近一次交易时间”。 ```sql SELECT A.NAME, LATEST_TRADE.LAST_DATE FROM USERS A LEFT JOIN ( SELECT USER_ID, MAX(TRADE_DATE) AS LAST_DATE FROM USER_TRADES GROUP BY USER_ID ) LATEST_TRADE ON A.USER_ID = LATEST_TRADE.USER_ID; ``` ✅ 完全合法,无 `(+)`,使用标准 `LEFT JOIN`。 --- ### 如何避免 ORA-01799? 1. **优先使用 ANSI SQL 的 `LEFT JOIN`, `RIGHT JOIN` 等语法**。 2. **避免在复杂查询中使用 `(+)` 操作符**,尤其是涉及子查询时。 3. 使用现代工具(如 SQL Developer、Toad)通常会提示这种语法错误。 4. 若需兼容旧系统,可将子查询封装成视图后再用 `(+)`(但仍不推荐)。 --- ### 补充:哪些情况可以使用 `(+)`? ✅ 合法使用 `(+)` 的例子(仅限简单表): ```sql SELECT A.NAME, B.AMOUNT FROM TABLE_A A, TABLE_B B WHERE A.ID = B.CUSTOMER_ID(+); ``` 这是 Oracle 老式的左外连接写法,等价于: ```sql SELECT A.NAME, B.AMOUNT FROM TABLE_A A LEFT JOIN TABLE_B B ON A.ID = B.CUSTOMER_ID; ``` 但一旦 `B` 是个子查询,就不能再这么写了。 ---
评论 2
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值