Oracle 动态数组使用-2

Posted 丹心石

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Oracle 动态数组使用-2相关的知识,希望对你有一定的参考价值。

动态数组语法:

type <类型名> is table of 类型 index by binary_integer;
<变量名> 类型名

  • 示例:
declare 
  type jo_arr_type is table of pljson;  --jo_arr_type 为表(数组)类型
  jo_arr jo_arr_type;  -- jo_arr 为数组类型变量名
  type cur_ref_type is ref cursor; --声明一个游标引用类型  cur_ref_type
  cur cur_ref_type;  --声明一个游标引用类型变量
  i integer;
  ja pljson_listl;
  c clob;
begin
  i:=1;
  ja:=new pljson_list();
  open cur for \'select f1,f2 from tbname\';
  for item in cur loop
    jo_arr(i):=new pljson();
	jo_arr(i).put(\'name\',f1);
	jo_arr(i).put(\'value\',f2);
	i:=i+1;
	...
	ja.append(jo_arr(i));
  end loop;
  dbms_lob.createtemporary(c,true);
  ja.to_clob(c);
  dbms_output.put_line(c);
end;
  

oracle动态sql,查询中查找使用过的表

【中文标题】oracle动态sql,查询中查找使用过的表【英文标题】:Oracle dynamic sql, find used tables in query 【发布时间】:2019-10-22 14:59:30 【问题描述】:

有没有办法在 Oracle 动态 SQL 中找到已用表的列表。我需要设置一些表格的使用限制。

动态查询文本示例:

select *
  from Table1 T1
  join Table2 T2
    on T1.Col1 = T2.Col1
 where exists (select 1
          from Table3 T3
         where T1.Col2 = T3.Col2)

结果应该是:[Table1, Table2, Table3]。有什么想法吗?

【问题讨论】:

我认为没有任何方法可以做到这一点。您也许可以解析解释计划调用的结果 将查询放在一个字符串中,并使用正则表达式来查找 from 和 join 关键字之后的表?当您过滤掉TABLE ACCESS 所在的行时,解释输出的相同想法.. 感谢所有帮助解决此问题的人。我计划为我的软件添加机会,让用户可以通过自己编写 SQL Query 来获取报告。但问题是我不能允许使用所有表格和所有功能。我想,我应该找到另一种方法来解决这个问题 【参考方案1】:

“有没有办法在 Oracle 动态 SQL 中找到已用表的列表”。

没有。也就是说,没有铸铁和直截了当的方法。动态 SQL 的后果之一是影响分析的难度增加。

确实,您也许能够在源代码中找到一些嵌入在文字字符串中的表名。

select *
from user_source
where lower(text) like '%table1%'
or  lower(text) like '%table2%'
or  lower(text) like '%table3%'

显然,您需要清除输出以隔离表名,并可能处理table17table23 上的误报。

但是,动态 SQL 通常会处理名称在运行时作为参数字符串传递或从数据字典中查询的表。你不太可能抓住所有这些。显然,这个差距的大小取决于你如何使用动态 SQL:也许你会没事的。

如果您的组织为 Tuning 和 Diagnostics 包付费,您可以使用 ASH 来查找已执行的 SQL ID,您可以对其进行解析以找到相关的表,幸运的话还可以预测生成和执行 SQL 的代码。

【讨论】:

【参考方案2】:

将您的动态 SQL 字符串放入 SQL SELECT 语句中,如下所示,以提取字符串中包含的表名:

with t(str) as
(
 select 'select *
  from Table1 T1
  join Table2 T2
    on T1.Col1 = T2.Col1
 where exists (select 1
          from Table3 T3
         where T1.Col2 = T3.Col2)' from dual
), t2 as
(
  select level as row_num, regexp_substr(to_char(t.str),'^.*$',1,level,'m') as str
    from t
   connect by level <= length (to_char(t.str)) 
                     - length (replace (to_char(t.str), chr (10))) + 1 
), t3 as
(
select regexp_substr(
           regexp_substr(str,'From[[:space:]].*[[:space:]]',1,1,'i'),
                        '[^ ]+',1,2) as x,
       regexp_substr(
           regexp_substr(str,'Join[[:space:]].*[[:space:]]',1,1,'i'),
                        '[^ ]+',1,2) as y
  from t2 
)
select coalesce(x,y) as "Tables"
  from t3
 where coalesce(x,y) is not null;

Tables
-------
Table1
Table2
Table3 

Demo

【讨论】:

【参考方案3】:

可以使用DBMS_UTILITY.EXPAND_SQL_TEXT、临时视图和查询DBA_DEPENDENCIES生成SQL语句使用的表列表。

DBMS_UTILITY.EXPAND_SQL_TEXT 负责查找视图引用的表。临时视图和DBA_DEPENDENCIES 然后生成扩展 SQL 语句中使用的所有表的列表。

功能

create or replace function get_dependent_tables_from_sql(p_sql varchar2)
return sys.odcivarchar2list authid current_user is
    v_expanded_sql clob;
    v_tables sys.odcivarchar2list := sys.odcivarchar2list();
    pragma autonomous_transaction;
begin
    --Expand the SQL, which will go through all the recursive dependencies.
    dbms_utility.expand_sql_text
    (
        input_sql_text  => p_sql,
        output_sql_text => v_expanded_sql
    );

    --Create a view with the expanded SQL.
    execute immediate
    '
        create or replace view temp_view_for_dependencies as
        select count(*) the_count
        from
        (
        '||v_expanded_sql||'
        )
    ';

    --Find dependencies.
    --(Use execute immediate to simplify compilation privileges.)
    execute immediate
    q'[
        select distinct referenced_owner||'.'||referenced_name
        from dba_dependencies
        where name = 'TEMP_VIEW_FOR_DEPENDENCIES'
            and owner = user
            and referenced_type = 'TABLE'
    ]'
    bulk collect into v_tables;

    return v_tables;
end get_dependent_tables_from_sql;
/

示例架构

create table table1(col1 number, col2 number);
create table table2(col1 number, col2 number);
create table table3(col1 number, col2 number);
create table table4(col1 number, col2 number);
create table table5(col1 number, col2 number);
create or replace view view1 as select 1 a from dual;

调用函数

select column_value table_name
from table(get_dependent_tables_from_sql(q'[
        select *
        from table1 t1
        --ANSI joins
        join table2 t2
            on t1.col1 = t2.col1
        where exists
        (
            select 1
            --Oracle style joins, views.
            from table3 t3, table4, view1
            where t1.col2 = t3.col2
        )
        --A table that won't be in execution plan.
        and exists (select 1 from table5 where 1 = 2)   
    ]'))
order by 1;

TABLE_NAME
----------
JHELLER.TABLE1
JHELLER.TABLE2
JHELLER.TABLE3
JHELLER.TABLE4
JHELLER.TABLE5
SYS.DUAL

关于其他解决方案的警告

小心涉及自定义 SQL 解析的解决方案。这是看起来非常容易的问题之一。您可以构建一个 98% 的时间都有效的正则表达式,但实际上不可能构建一个 100% 的时间有效的正则表达式。

谨慎使用执行计划解决方案。将执行计划对象追溯到表并非易事,就像只使用索引一样。并且某些表可以在查询中使用,但由于连接消除而被排除在执行计划之外。

【讨论】:

以上是关于Oracle 动态数组使用-2的主要内容,如果未能解决你的问题,请参考以下文章

Oracle SQL - 动态案例语句

oracle 数组长度

如何在 oracle 中使用 sys_refcursor 创建动态 sql

水晶报表显示动态图片

如何在ORACLE中定义一个数组

在Oracle中使用NTILE和动态查询结果