`

ORA-01031 权限不足-过程中DBA 角色用户无法执行DDL

 
阅读更多

Oracle的存储过程,是我们使用数据库应用开发的重要工具手段。在存储过程中,我们大部分应用场景都是使用DML语句进行数据增删改操作。本篇中,我们一起探讨一下数据定义语句DDL在存储过程中使用的细节和要点。

 

1、“借道而行”的DDL

 

Oracle PL/SQL和存储过程程序开发原则上,应该是不鼓励在SP中使用DDL语句的。首先一个表现,就是Oracle在编译时就不允许直接在SP中使用DDL语句。下面我们使用Oracle 10gR2作为实验环境。

 

 

SQL> select * from v$version;

 

BANNER

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

Oracle Database10gEnterpriseEdition Release10.2.0.1.0 - Prod

PL/SQL Release10.2.0.1.0 - Production

CORE    10.2.0.1.0      Production

 

TNS for 32-bit Windows: Version10.2.0.1.0 - Production

NLSRTL Version10.2.0.1.0 – Production

 

 

建立存储过程p_test_nc,进行简单的数据表创建。

 

 

SQL> create or replace procedure P_TEST_NC

 2 is

 3 begin

 4   create table t (id number);

 5 end P_TEST_NC;

 6 /

 

Warning: Procedure created with compilation errors

 

SQL> select name, text from user_errors;

 

NAME      TEXT

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

P_TEST_NC PLS-00103:出现符号"CREATE"在需要下列之一时:

           begin case declare exit

             for goto if loop mod null pragma raise return select update

             while with <an identifier>

             <a double-quoted delimited-identifier> <a bind variable> <<

             close current delete fetch lock insert open rollback

             savepoint set sql execute commit forall merge pipe

 

 

显然,在编译时Oracle就报错不允许存储过程创建。之后的实验droptruncate table操作,也都是不允许直接在存储过程中书写DDL语句。说明起码使用直接的DDL语句,存储过程是不能编译通过的。

 

那么,有没有什么折中的方法呢?我们说是有的,就是借助“execute immediate”方法,“绕过”编译过程中对DDL的屏蔽。我们使用truncate table DDL语句实验。

 

 

SQL> create or replace procedure P_TEST_NC

 2 is

 3 begin

  4   execute immediate'truncate table t';

 5 end P_TEST_NC;

 6 /

Procedure created

 

 

编译通过了,DDL语句以一个字符串的形式避开了编译时Oracle的语法检查,编译成功。那么,执行起来会不会报运行时错误呢?

 

 

SQL> exec p_test_nc;

PL/SQL procedure successfully completed

 

 

执行成功,说明:Oracle存储过程中,可以使用exectue immediate语句绕开编译时对DDL语句的检查,生成运行代码。

 

 

2SPDDL权限

 

任何程序编译执行都会伴随着语法语义的一系列检查。使用execute immediate虽然可以回避编译时检查,但是SQL语句还是面临着运行时检查的问题。下面看实验的例子。

 

--scott用户下进行试验;

SQL> create or replace procedure P_TEST_NC

 2 is

 3 begin

 4   execute immediate 'create table t(id number)';

 5 end P_TEST_NC;

 6 /

Procedure created编译时通过;

 

SQL> exec p_test_nc;

 

begin p_test_nc; end;

 

ORA-01031:权限不足

ORA-06512:"SCOTT.P_TEST_NC", line 4

ORA-06512:line 1

 

 

在用户自己的schema下创建数据表,难道是不允许的吗?显然不是。

 

 

SQL> create table m (id number);

Table created

 

 

单独创建是允许的,说明是由于权限机制导致的问题。我们切换到sys用户上,提高scott用户权限。

 

 

Connected as SYS

--赋予最高创建数据表的系统权限;

SQL> grant create any table to scott;

Grant succeeded

 

 

切换回scott用户,继续实验。

 

 

SQL> conn scott/tiger@orcl;

Connected to Oracle Database10gEnterpriseEdition Release10.2.0.1.0

Connected as scott

 

SQL> exec p_test_nc;

PL/SQL procedure successfully completed

 

SQL> select * from t;

       ID

----------

 

执行成功!这个原因是什么呢?还是由于存储过程权限体系特点和DDL语句特点共同造成的。

 

在之前笔者的系列文章《所有者权限和调用者权限》(http://space.itpub.net/17203031/viewspace-692161)中,介绍了Oracle存储过程采用的两种权限体系方式和role权限在存储过程执行中的特殊性。

 

默认情况下,Oracle对存储过程是使用所有者权限,也就是说:如果用户B调用了用户A schema下的一个存储过程,其中使用的对象权限和系统权限,全部都是用户A的。如果用户A没有权限,用户B执行要报错。

 

同时,用户的角色权限在进入存储过程后,会被剥离掉,是不其效果的。

 

结合上面的实验,就好解释了:scott自身只拥有一个resource的角色权限,单独在SQL中使用没有问题。进入到SP之后,这个create table的权限就被剥离掉了。而该SP存在被其他用户调用生成数据表的可能。所以会在运行时报错权限不足。

 

当我们显示的赋予scott用户create any table/create table之后,系统权限就可以渗透到SP中起效果了。

 

这并不是解决该问题的唯一方法。此处我们可以使用调用者权限机制,改写SP代码。首先我们剔除掉scottcreate any table权限。

 

 

Connected to Oracle Database10gEnterpriseEdition Release10.2.0.1.0

Connected as SYS

 

SQL> revoke create any table from scott;

Revoke succeeded

 

SQL> conn scott/tiger@orcl;

Connected to Oracle Database10gEnterpriseEdition Release10.2.0.1.0

Connected as scott

 

SQL> exec p_test_nc;

begin p_test_nc; end;

 

ORA-01031:权限不足

ORA-06512:"SCOTT.P_TEST_NC", line 4

ORA-06512:line 1

 

 

我们改写代码为:

 

 

SQL> create or replace procedure P_TEST_NC

 2 Authid Current_User

 3 is

 4 begin

 5   execute immediate 'create table t (id number)';

 6 end P_TEST_NC;

 7 /

Procedure created

 

SQL> exec p_test_nc;

PL/SQL procedure successfully completed

 

 

执行成功,这里使用“authid Current_user”将存储过程转化为调用者权限。每次调用存储过程,都是动态根据调用者的权限构成去判定是否有权限,这样就回避了该问题的出现。

 

总之:在使用DDL在存储过程中时,权限管理和使用的复杂度是在增加。

 

 

4DDL对事务的提交影响

 

DDL语句放置在存储过程中,潜在最大风险就是对事务管理的破坏。在Oracle中,如果调用一个DDL语句,潜藏效果就是将当前会话的未提交事务进行提交。这个过程显然是对原有的事务逻辑破坏。

 

 

SQL> create table m (id number);

Table created

 

SQL> select * from m;

       ID

----------

 

SQL> create or replace procedure P_TEST_NC

 2 is

 3 begin

 4   insert into m values (3);

 5   execute immediate 'truncate table t';

 6 

 7   rollback;

 8 end P_TEST_NC;

 9 /

 

Procedure created

 

--执行代码

SQL> exec p_test_nc;

PL/SQL procedure successfully completed

 

--事务提交

SQL> select * from m;

       ID

----------

        3

 

 

从上面的例子上,我们可以清楚的看到现象。由于中间的truncate table操作,引起数据表m的插入操作被提交commit。而真正的事务逻辑可能是一个rollback

 

所以,在SP中使用DDL命令,可能引起业务逻辑的不可控提交和数据不一致,这个风险在任何应用中是不可以允许的。

 

那么,有没有方法回避这个过程呢?经一个同事提醒,的确可以使用手段回避。

 

 

5DDL与自治事务

 

自治事务(AUTONOMOUS_TRANSACTION)是保证在事务进行过程中一段独立的事务过程。如果在DDL操作外套入一个自治事务过程,是否就可以回避问题了。

 

 

SQL> select * from m;

 

       ID

----------

 

SQL> create or replace procedure P_TEST_NC is

 2   procedure p_inner_test

 3   is

 4   PRAGMA AUTONOMOUS_TRANSACTION;

 5   begin

 6     --调用ddl

 7     execute immediate 'truncate table t';

 8   end;

 9 begin

 10   insert into m values (3);

 11   p_inner_test;

 12 

 13   rollback;

 14 end P_TEST_NC;

 15 /

Procedure created

 

SQL> exec p_test_nc;

PL/SQL procedure successfully completed

\

SQL> select * from m;

       ID

----------

 

 

实验成功,通过自治事务的确可以回避DDL的事务问题。

 

6、结论

 

DDLSP中,与常规的DML操作差异很大。这种差异不仅仅是语法上,更多的是权限、事务等更深层次复杂的差异。所以,从Oracle的角度看,尽量少在SP中使用DDL语句,避免出现不可控的问题。

 

PLS-00157:   AUTHID only allowed on schema-level programs

查了下错误原因 An AUTHID clause was specified for a subprogram inside a package or type. These clauses are only supported for top-level stored procedures, packages, and types.

大致意思就是authid只能用在顶级的存储过程、包、类型上,不能用在包或类型的子程序上

 

在包上加入authid,执行正常了。

 

create or replace package rule_execute
authid current_user

 

文献出处:http://www.cnblogs.com/HondaHsu/archive/2012/11/02/2751618.html

分享到:
评论

相关推荐

    Oracle错误代码大全.pdf

    19. ORA-00034: 无法在当前PL/SQL会话中执行某些操作,可能是由于会话限制或语法错误。 20. ORA-00035: LICENSE_MAX_USERS不能小于当前用户数,这涉及到数据库许可证限制。 21. ORA-00036: 超过递归SQL级别的最大...

    oracle错误一览表

    - **描述**: 在PL/SQL环境中执行某些操作时出现错误。 - **解决方法**: 检查PL/SQL代码中的错误,并确保所有必要的资源都可用。 **ORA-00035: LICENSE_MAX_USERS不能小于当前用户数** - **描述**: 尝试降低`LICENSE...

    oracle错误码大全

    **描述**: 无法在当前的PL/SQL环境中执行特定操作。 **解决方法**: - 检查PL/SQL环境的配置。 - 确认操作是否适用于当前环境。 #### ORA-00035: LICENSE_MAX_USERS不能小于当前用户数 **描述**: 许可证的最大用户...

    ORACLE错误一览表

    在Oracle数据库管理与开发过程中,遇到错误代码是常有的事。理解这些错误代码及其含义对于快速定位问题并解决故障至关重要。以下是从“ORACLE错误一览表”中挑选出的部分常见错误代码及其详细解释,旨在帮助数据库...

    oracle goldengate ddl

    2. **权限验证**:确保GoldenGate用户拥有足够的权限执行DDL语句。 3. **DDL语句捕获**:启用GoldenGate的DDL捕获功能,确保所有DDL语句都能被GoldenGate正确捕获。 4. **性能监控**:监控GoldenGate进程的性能,...

    oracle 10 Ora 10G 官方文档

    - Oracle 10g中的错误信息有助于诊断和解决数据库运行时遇到的问题,如ORA-00001(唯一性约束违反)、ORA-01422(精确提取超出范围)等。 - 了解这些错误代码和其背后的含义,对于DBA来说至关重要,能快速定位并...

    oracle面试题

    在Oracle数据库管理中,面试题通常涵盖了许多关键概念和技术,如SQL语法、完整性约束、数据库权限、事务管理和视图创建。以下是对所给面试题的详细解析: 1. 错误提示ORA-02292表明违反了外键约束。在本例中,尝试...

    Oracle学习一:安装配置,sqlplus ,使用em控制工具管理oracle

    4. 用户与角色管理:创建和删除用户,分配权限。 5. 作业调度:安排自动任务,如备份、分析等。 通过学习Oracle的安装配置、SQL*Plus的使用和EM的管理,你将能够更好地理解和操作Oracle数据库,为后续的数据库开发...

    Oracle DBA必备技能详解

    5. **数据库安全**:设置用户权限、角色、对象权限,理解Oracle的审计功能,以及如何实现行级和列级的安全策略。 6. **备份与恢复**:学习RMAN(恢复管理器)的使用,进行完整备份、增量备份、差异备份等操作,并...

    Oracle DBA 笔试题

    1. 创建用户时,需要赋予`CONNECT`权限,使得新用户能够连接到数据库。 2. 重构索引通常涉及重建索引,可以通过`ALTER INDEX REBUILD`命令实现,或者在索引碎片过多时,考虑使用`ALTER INDEX REORGANIZE`来优化。 ...

    Oracle 数据库日常维护

    当发现启动参数不正确、重做日志无法切换、表空间被未经授权的用户删除、坏块或ORA-600错误时,应采取相应措施。处理方法包括:检查并调整初始化参数文件、增加重做日志文件组、提高检查点或归档操作效率、解决安全...

    oracle基础培训(熟悉作为数据库管理员(DBA)的任务和需要掌握的基础知识)

    Oracle的命令行接口sqlplus是DBA常用的工具,用于执行DDL(数据定义语言)、DML(数据操纵语言)、DCL(数据控制语言)和PL/SQL语句。此外,接口如ODBC和JDBC使得其他应用程序能够连接到Oracle数据库,需要熟悉相关...

    Oracle重建WMSYS用户及WMSYS.WM_CONCAT函数

    在SQL*Plus环境中,我们需要以拥有足够权限的用户登录,例如SYSDBA,然后逐个执行这些脚本。执行过程可能如下: 1. 首先,确保你有正确的连接信息,并以SYSDBA角色登录到SQL*Plus: ``` sqlplus / as sysdba ``` 2...

    深入浅出Oracle:DBA入门、进阶与诊断案例(盖国强)

    - 用户与权限:创建和管理数据库用户,设置用户权限,理解角色和权限的层次结构。 4. **SQL语言**: - DDL(Data Definition Language):包括CREATE、ALTER、DROP等语句,用于定义和修改数据库对象。 - DML...

    ORACLE DBA必备教程

    学习如何设置用户权限,管理角色,以及如何应用审计功能,以确保数据库的安全性和合规性。 总的来说,Oracle DBA入门教程涉及的内容广泛且深入,从基本的数据库概念到高级的性能调优和安全管理,都需要通过实践和...

    ORACLE_DBA培训教材.pdf

    根据给定的文件信息,我们可以提炼出一系列关于Oracle DBA培训教材的重要知识点,这些知识点涵盖了数据库管理员(DBA)应具备的基础知识、Oracle数据库系统的基本架构以及数据库管理的关键概念。 ### 关系数据库基础...

    oracle sql 练习

    - **用户管理**:创建、修改和删除用户,以及权限和角色的分配。 - **性能调优**:索引创建、统计信息收集、查询优化器的使用等,以提高查询性能。 - **备份与恢复**:了解RMAN(恢复管理器)和其他备份工具,...

    相克军老师DBA全套ppt教程超值下载

    5. **数据库安全性**:讲解如何设置用户权限、角色、对象权限,以及如何通过审计功能来保障数据库的安全性。 6. **高可用性与容灾**:这部分可能会涉及Oracle的Real Application Clusters (RAC)、Data Guard、...

    Oracle9i的init.ora参数中文说明

    如果设置为 TIMESTAMP, 只有在服务器与本地时间戳相匹配的情况下, 才能执行该过程。如果设置为 SIGNATURE, 在签名安全的情况下即可执行该过程。 值范围: TIMESTAMP | SIGNATURE 默认值: TIMESTAMP utl_file_dir: ...

    oracle dba必备技能详解

    Oracle DBA(数据库管理员)是IT领域中一个关键的角色,他们负责管理、监控和优化Oracle数据库系统,确保数据的安全性和高效性。Oracle DBA必备技能包括但不限于以下几个方面: 1. **Oracle基础知识**:DBA首先需要...

Global site tag (gtag.js) - Google Analytics