知识大全 使用动态SQL克隆数据库对象

Posted

篇首语:能够说服别人最好的方式,其实就是你始终坚持在做的事。本文由小常识网(cha138.com)小编为大家整理,主要介绍了知识大全 使用动态SQL克隆数据库对象相关的知识,希望对你有一定的参考价值。

使用动态SQL克隆数据库对象  以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧!

  首先给出一个警告 下面的技巧提示如果使用不小心会造成严重的安全漏洞 当你在一个非测试环境下使用这种方法之前 一定要完完全全地理解这样做的后果     如果你需要复制一个表并在(另一个用户名下的)另一个方案(schema)制作它的一个副本 那么你可以使用 SQL*Plus 的 COPY 命令 或者使用简单的语句 create table foo as select * from other foo; 只要你在另一个用户的表上有足够的 select 权限     然而 如果你需要对任何其它数据库对象做同样的事情 比如包 过程 函数或视图 就没有这么简单的命令了 你需要手工找出其代码并在新实例中运行它 如果能够简单 克隆对象 并让另一个用户的对象出现在自己的实例中 那将是一件非常值得高兴的事 对于为开发过程创建测试方案来说 这一点非常有用 在这个例子中 我将创建一个包 使用该包可以对大多数对象进行克隆(具有一些限制)     要处理的主要问题是获得源代码 对象所有者通过视图USER_SOURCE 可以访问源代码 而对于其它用户 如果对象被授予了EXECUTE 权限给一个用户 那么这个用户就只能看到通过视图ALL_SOURCE 选出的源代码 我们可以通过一个过程来封装 give me the source for your object(给我你的对象的源代码) 请求     create or replace procedure get_source  (  p_type     varchar   p_name     varchar   p_cursor out  sys_refcursor  )  as  begin  open p_cursor for  select text from user_source  where type = upper(p_type) and name = p_name  order by line;  end get_source;  /  show errors;    注意 我没有用 UPPER(name) 这就意味着你必须匹配这个存储过程的字母大小写 Java 存储过程使用很多大小写混合的名字     如果这个过程是由对象所有者所有的 那么那个对象的源代码就可以通过一个 REF CURSOR 变量导出 如果这个过程被授予了其他用户 EXECUTE 权限 那么这个用户将能够调用这个过程并查看任何数据库对象的源代码——即使是那些没有授权给他们的对象和那些在 ALL_SOURCE 中不给出的对象 比如 TYPE 声明 为了说明这种方法可行 请尝试在 SQL*Plus 中输入以下代码     SQL> connect scott/tiger  SQL> create function foo return varchar as begin return hello world ; end;  SQL> /  SQL> @get_source sql  SQL> variable c refcursor;  SQL> exec get_source( FUNCTION FOO :c);  SQL> print c    有了从对象所有者手中得到的源代码 调用者就可以在创建自己的方案中创建对象了 我们需要动态 SQL 来从文本字符串构建对象 另外一个需要处理的问题是一些数据库对象的源代码的长度可能会超过 个字符 即超过 VARCHAR 字符串的最大长度限制 这样就不能使用简单的 VARCHAR 字符串来保存 SQL 在 Oracle 中有一个很少使用的变量DBMS_SQL PARSE 可以使用它将源代码存储为一个由 VARCHAR 字符行所组成的表中 这样的表可以用来存储超过 长度限制的 SQL (在实际的应用中 你可能还需要将任何大于 个字符的代码行包装起来 因为USER_SOURCE 最多只能存储 行字符) 下面将其实现为一个带有命令行参数的 SQL*Plus 脚本的代码     declare  ipls_integer := ;  l_source dbms_sql varchar s;  l_line varchar ( );  l_cursorsys_refcursor;  c pls_integer;  r pls_integer;  begin  & get_source( & & l_cursor);  l_source(i) := create or replace ;  loop  fetch l_cursor into l_line;  exit when l_cursor%notfound;  i := i + ;  l_source(i) := l_line text;  end loop;  close l_cursor;  if i = then  raise_application_error( object does not exist );  end if;  c := dbms_sql open_cursor;  dbms_sql parse(c l_source unt true dbms_sql native);  dbms_sql close_cursor(c);  end;  /  show errors;    举个例子 假设一个方案需要克隆 SCOTT 的方案中的 FOO 的函数 SCOTT 将拥有 CLONER 的一个副本并将 EXECUTE 权限授予允许克隆 SCOTT 的对象的用户 其它的用户可以发出以下 SQL*Plus 命令     SQL> connect ANOTHER USER  SQL> @clone SCOTT FUNCTION FOO    这种做法可行 但是依然需要 SQL*Plus 会话和脚本 我想将所有东西都放在 SQL 中 以使得任何应用程序都可以执行这一功能 为了实现这一想法 我们需要将前面的 SQL*Plus 脚本包装成另外一个动态 SQL 语句 在这个语句中我们可以加上所有者的名称并将所有者和类型参数组合 可以用以下过程来实现     create or replace procedure clone_obj  (  p_owner     varchar   p_type     varchar   p_name     varchar   )  authidcurrent_user  is  lf     char := chr( );  begin  execute immediate   declare || lf  ||   ipls_integer := ; || lf  ||   l_source dbms_sql varchar s; || lf  ||   l_line varchar ( ); || lf  ||   l_cursorsys_refcursor; || lf  ||   c pls_integer; || lf  ||   r pls_integer; || lf  || begin || lf  ||    ||p_owner|| get_source(: : l_cursor); || lf  ||   l_source(i) := create or replace ; || lf  ||   loop || lf  ||     fetch l_cursor into l_line; || lf  ||     exit when l_cursor%notfound; || lf  ||     i := i + ; || lf  ||     l_source(i) := l_line; || lf  ||   end loop; || lf  ||   close l_cursor; || lf  ||   if i = then || lf  ||     raise_application_error(   || object does not exist ); || lf  ||   end if; || lf  ||   c := dbms_sql open_cursor; || lf  ||   dbms_sql parse(c l_source unt   || true dbms_sql native); || lf  ||   dbms_sql close_cursor(c); || lf  || end; || lf  using p_type p_name;  end clone_obj;  /  show errors;    注意 使过程具有足够的权限来创建数据库对象 我必须添加AUTHID CURRENT_USER 现在你可以用任何能够调用 Oracle 存储过程的产品来调用这个过程 下面这个例子与前面的例子相同 只不过这个例子是写在 SQL*Plus 中的     SQL> @clone_obj  SQL> exec clone_obj( SCOTT FUNCTION FOO );    在这里会有一些安全问题 但是不多 只有被授予对 GET_SOURCE 有 EXECUTE 权限的用户才能读取他们常规情况下无法看到的对象的源代码 在理想情况下 你可以创建一个只包含 GET_SOURCE 和一组模板对象的用户     上面的程序还不完整 但是还是可以作为一个例子来用的 除了需要将 个字符的源代码包装成 个字符长的目标行之外 可能还需要对其进行扩展以扫描对象的名称并插入一个所有者名称 以使得 DBA 所有者能够将对象从一个用户克隆到其他用户 cha138/Article/program/SQLServer/201311/22241

相关参考

知识大全 为什么在使用动态 SQL 语句时必须为低层数据库对象授予权限

为什么在使用动态SQL语句时必须为低层数据库对象授予权限?  以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一

知识大全 Oracle数据库编程动态SQL

Oracle数据库编程动态SQL  以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧!  动态SQL  编

知识大全 使用动态数据库访问对象

  前两天看到Warpframework的介绍它基于GoogleGuice是一个轻量级的web开发框架它的Dynamicfinder特性实在让人兴奋代码非常简单支持注入大大简化了DAO层的开发下面看看

知识大全 VB中用ADO对象动态创建数据库和表

VB中用ADO对象动态创建数据库和表  以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧!  :问题的提出

知识大全 使用PL/SQL从数据库中读取BLOB对象

使用PL/SQL从数据库中读取BLOB对象  以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧!  确认现

知识大全 使用ADO对象连接SQL Server数据库

使用ADO对象连接SQLServer数据库  以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧!  链接代

知识大全 SQL Server数据库对象信息的获取方法

SQLServer数据库对象信息的获取方法  以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧!  在开发

知识大全 SQL Server数据库对象信息的获取[4]

SQLServer数据库对象信息的获取[4]  以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧!&nbs

知识大全 SQL Server数据库对象信息的获取[3]

SQLServer数据库对象信息的获取[3]  以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧!&nbs

知识大全 SQL Server数据库对象信息的获取[2]

SQLServer数据库对象信息的获取[2]  以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧!&nbs