我正在开发一个用于获取Oracle数据库对象的ddl 的应用程序。
使用以下查询获取数据库对象
SELECT object_name, object_type
FROM dba_objects
where owner = '" + alternative_schema + "'
order by object_type, object_name;
使用以下查询获取数据库对象的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
可能。
但是有人建议通过'sys'。
现在,我可以通过以下查询列出所有对象
select *
from sys.all_tables
where owner ='mydb'
它返回mydb模式下的所有已创建对象。
但是我的下一个挑战是获取DDL
如何在没有 SELECT_CATALOG_ROLE
的情况下获得ddl?
是否可以通过任何方式执行DBMS_METADATA.GET_DDL而无需授予 SELECT_CATALOG_ROLE
?
更新: 根据链接oracle Security Model
非特权用户只能看到他们自己对象的元数据。
因此所有者无需具有"SELECT_CATALOG_ROLE"
的{{1}}权限
并且我的用户是readOnly类型的用户,我需要从只读用户(非所有者)帐户(该帐户不应具有get_ddl()
答案 0 :(得分:2)
我们唯一需要运行DBMS_METADATA.GET_DDL()
的情况是当我们使用其模式不受适当的源代码控制的数据库时。这是一种糟糕的情况,DBA应该改善这种情况。
因此,您需要将DBA放在一边。如果您的请求的目的是使数据库进入源代码控制,这应该很容易,也就是说,这是一次性的练习,并且已经制定了安全的开发实践以确保可以跟踪对数据库的所有将来更改在源代码控制之下。
建议的方法:在不是Production但却具有与Production相同的数据结构的数据库上工作。这比要求在生产环境中提升特权要容易得多。
理想情况下,它应该已经可用(UAT,预生产环境),但是如果您需要使用DBMS_METADATA.GET_DDL()
,则可能是在没有这种环境的情况下进行的。在这种情况下,您需要DBA为您创建一个新数据库。
@AlexPoole提出了一个很好的建议。您可以使用通过sqlfile
选项通过Data Pump导出的元数据来生成源文件。 Find out more。
答案 1 :(得分:0)
是的,有可能从数据字典视图中提取对象的DDL,但几乎不可能编写完整或正确的代码,或两者都写。
Oracle的安全性概念具有三个基本角色:
1)模式的所有者:您可以对表/视图/对象做任何您想做的事而没有任何许可,甚至可以执行DBMS_METADATA
。您可以使用以USER_
开头的数据字典视图,例如USER_TABLES
,USER_TAB_COLUMNS
等。
2)一个“应用程序用户”或对其他模式对象具有一些特权的人。您可以使用以ALL_
开头的数据字典视图,例如ALL_TABLES
,ALL_TAB_COLUMNS
。哪些其他对象出现在您的视图中,取决于许多因素,例如在表上选择privs。但坦率地说,没有人知道完整的列表(只需在工作面试中问一下,Grants您需要查看或更改另一个架构中的物化视图)
3)一个DBA。他/她可以查看和更改所有架构中的所有其他对象。您使用以DBA_
开头的数据字典视图,例如DBA_TABLES
,DBA_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
。也许他们可以为脚本/程序做出贡献并自行执行。
答案 2 :(得分:0)
首先,感谢所有建议。根据链接enter link description here
,我找到了适合我的方案的解决方案非特权用户只能看到他们自己对象的元数据。
因此,所有者无需具有"SELECT_CATALOG_ROLE"
的{{1}}权限。我的要求是从不具有“ SELECT_CATALOG_ROLE”权限的用户那里获取ddl。因此,一种解决方案是,如果在所有者帐户下创建一个函数,该函数在内部执行dbma_metadata.get_ddl()并返回ddl字符串,并且如果我们向用户(非所有者)授予新方法的选择/执行权限,那么她可以ddl,而没有所有者帐户之外的get_ddl()
。
"SELECT_CATALOG_ROLE"
从其他用户(非所有者)调用此方法。通过此只读用户,只有访问getDDL()才能获取定义。但是没有其他权限的用户将被授予只读用户。