【问题标题】:Any alternative way of DBMS_METADATA.GET_DDLDBMS_METADATA.GET_DDL 的任何替代方式
【发布时间】:2018-06-20 06:20:30
【问题描述】:

我正在开发一个用于获取 Oracle 数据库对象的 ddl 的应用程序。

使用以下查询获取数据库对象

SELECT object_name, object_type  
FROM dba_objects 
where owner = '" + alternative_schema + "' 
order by object_type, object_name;

使用以下查询获取 db 对象的 ddl

SELECT DBMS_METADATA.GET_DDL('TABLE','" + tableName + "','" + alternative_schema + "') 
FROM dual;

它工作正常。

要执行上述查询 oracle 用户需要以下授权

GRANT SELECT_CATALOG_ROLE TO john;
GRANT SELECT ANY TABLE TO john;

现在由于一些安全问题,dba 不允许授予 SELECT_CATALOG_ROLE,正如我的研究表明,使用 SELECT_CATALOG_ROLE 是不可能的。 p>

但有人建议通过 'sys' 来做

所以现在我可以通过以下查询列出所有对象

select * 
from sys.all_tables 
where owner ='mydb'

它返回 mydb 模式下创建的所有对象。

但我的下一个挑战是获取 ddl

没有SELECT_CATALOG_ROLE如何获得ddl?

是否可以在不授予 SELECT_CATALOG_ROLE 的情况下以任何方式执行 DBMS_METADATA.GET_DDL?

更新: 根据链接oracle Security Model

非特权用户只能看到自己对象的元数据。

所以所有者不需要拥有"SELECT_CATALOG_ROLE"get_ddl() 的权限

我的用户是只读类型的用户,我需要从只读用户(非所有者)帐户获取 DDL 的最终解决方案,该帐户不应该有 SELECT_CATALOG_ROLE

【问题讨论】:

  • 据我所知,您确实需要select_catalog_role。您提到的sys 在这里无关紧要,因为您从all_tables 中进行选择,无论如何您都可以访问它(它包含您可以访问的所有对象)。 “sys”只是说谁拥有它,但在这种情况下并不重要。
  • 谢谢@Littlefoot。实际上由于安全要求,dba 不能让我们对 Oracle 数据库中的 DBA_OBJECTS 表具有选择权限。所以我们不能使用DBA_OBJECTS。那么我们是否可以通过其他任何方式来做到这一点,或者这是不可能的,这意味着我必须授予 CATALOG_ROLE 才能获得 DDL。
  • 如果你必须做那份工作(因为有人(老板?)告诉过你)但因为你没有所需的权限而不能做,你必须和那个 老板 人,解释发生了什么,看看结果。要么你会得到特权(并且去做),要么你不会得到它(并且不会去做)。
  • 感谢@Littlefoot 的反馈
  • 不客气。祝你好运!

标签: sql oracle ddl


【解决方案1】:

我们需要运行DBMS_METADATA.GET_DDL() 的唯一情况是,当我们使用的数据库的架构不受适当的源代码控制时。这是一种糟糕的情况,DBA 应该想要改善这种情况。

因此,您需要让 DBA 支持您。如果您的请求的目的是让数据库进入源代码控制,这应该很容易,也就是说,这是一次性的练习,并且正在实施安全的开发实践,以确保跟踪数据库的所有未来更改受源代码控制。

建议的方法:在不是生产但具有与生产相同数据结构的数据库上工作。这应该比在生产环境中要求提升权限更容易推销。

理想情况下,它应该已经可用(UAT,Pre-prod 环境),但如果您需要使用DBMS_METADATA.GET_DDL(),也许您在没有这样的环境的情况下工作。在这种情况下,您需要 DBA 为您创建一个新数据库。


@AlexPoole 提出了一个很好的建议。您可以通过带有sqlfile 选项的Data Pump 使用元数据导出来生成源文件。 Find out more.

【讨论】:

  • 如果它不受源代码控制,那么 UAT/预生产很可能与生产不匹配,因此将新数据库作为生产的克隆可能会更安全。 (但随后获取仅元数据导出并使用 sqlfile 获取 DDL 可能同样好?)
  • 我无法要求制作与生产相同的数据结构。
【解决方案2】:

是的,可以从数据字典视图中提取对象的 DDL,但几乎不可能编写完整或正确或两者兼而有之的代码。

Oracle 的安全概念具有三个基本作用:

1) 架构的所有者:您可以在没有任何权限的情况下对表/视图/对象做任何您想做的事情,甚至可以执行DBMS_METADATA。您使用以USER_ 开头的数据字典视图,例如USER_TABLESUSER_TAB_COLUMNS 等。

2) 一个“应用程序用户”或对其他模式对象有一些特权的人。您使用以ALL_ 开头的数据字典视图,例如ALL_TABLESALL_TAB_COLUMNS。哪些其他对象出现在您的视图中,取决于很多事情,例如选择表上的权限。但坦率地说,没有人知道完整列表(只需在工作面试中询问您需要查看或更改另一个架构中的物化视图)

3) 数据库管理员。他/她可以查看和更改所有模式中的所有其他对象。您使用以DBA_ 开头的数据字典视图,例如DBA_TABLESDBA_TAB_COLUMNS 等。在您的示例中,一些较新的包以DBA 权限的子集运行,例如SELECT_CATALOG_ROLE

有理由相信DBMS_METADATA 是为 Oracle 的导出/导入数据泵产品编写的,该产品需要查看所有对象,因此属于第 3 类)

所以,你有三个选项来解决你的任务。

1) 沿着路线 1。在 PL/SQL 中作为表的所有者编写一个存储过程,使用 DBMS_METADATA 获取 DDL 并执行您需要执行的任何操作。此过程可以授予其他用户。

2) 沿着路线 2 前进。使用视图 ALL_ 提取一点 DDL。请注意,Oracle 11.2 中有 365 个这些视图。

3) 沿着路线 3 前进。与您的 DBA 交谈,让他们参与进来。也许他们在开发数据库上授予您SELECT_CATALOG_ROLE。也许他们可以为脚本/程序做出贡献并自己执行。

【讨论】:

    【解决方案3】:

    首先感谢大家的所有建议。根据链接enter link description here,我得到了我的方案的解决方案

    非特权用户只能看到自己对象的元数据。

    所以所有者不需要拥有"SELECT_CATALOG_ROLE"get_ddl() 的权限。我的要求是从不应具有“SELECT_CATALOG_ROLE”权限的用户那里获取 ddl。所以一种解决方案是,如果在内部执行 dbma_metadata.get_ddl() 并返回 ddl 字符串的所有者帐户下创建一个函数,并且如果我们将新方法的选择/执行权限授予用户(非所有者),那么她可以获得ddl 没有来自所有者帐户之外的"SELECT_CATALOG_ROLE"

    create function get_ddl( i_owner in varchar2, i_name in varchar2, i_type in varchar2)
        return clob
    is
    begin
        dbms_output.put_line('Listing active session roles...');
        for r_role in (select role from sys.session_roles) loop
            dbms_output.put_line('Role : '||r_role.role);
        end loop;
        dbms_output.put_line('Roles listed');
        dbms_output.put_line('Userid is : '||sys_context('userenv', 'current_userid'));
        return dbms_metadata.get_ddl( schema => i_owner, name => i_name, object_type => i_type);
    end;
    

    从其他用户(非所有者)调用此方法。通过这个只读用户将只能访问 getDDL() 来获取定义。但是没有其他权限的用户会被授予只读用户。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-05-19
      • 2014-12-27
      • 1970-01-01
      相关资源
      最近更新 更多