检查表访问以获取BLOB中的Oracle SQL语句

时间:2018-09-07 00:39:47

标签: sql oracle plsql blob access

我有一个表,该表的列包含BLOB格式的SQL查询(仅适用于select语句)。 我正在尝试找出一种分析SQL查询的方法,并检查每个SQL查询将访问哪些表。

有人做过类似的事情吗?

我现在的想法是创建一个PLSQL循环:

  1. 将BLOB转换为文本以获取SQL查询
  2. 执行查询的解释计划
  3. 查看解释计划的结果,并使用TABLE ACCESS获取所有行

编辑:我正在使用Oracle Database 11g 11.2.0.4.0版-如果有帮助,请使用64位,并且具有对数据库的只读访问权限,因此,我需要创建一个不会干扰数据库的解决方案。

2 个答案:

答案 0 :(得分:0)

这可能是另一种更简单的方法。

在BLOB字段中为那些SQL创建动态视图。

EXECUTE IMMEDIATE 'CREATE OR REPLACE VIEW YOUR_VIEW_NAME AS '|| 
utl_raw.cast_to_varchar2(dbms_lob.substr(blob_field)); 

查询user_dependencies以获取引用的表名。

SELECT referenced_name AS table_name 
FROM   user_dependencies 
WHERE  type = 'VIEW' 
       AND NAME = 'YOUR_VIEW_NAME' 
       AND referenced_type = 'TABLE'; 

答案 1 :(得分:0)

所以,这是我的做法:

DECLARE
  b BLOB;
  c CLOB;
  n NUMBER;

BEGIN

  -- << loop_through_table >>
  FOR o IN (SELECT TRIM(LABEL) lbl, REQUEST req FROM REQUEST_TABLE) LOOP

      b := o.req;
      IF ((b is null) OR (LENGTH(b)=0)) THEN
        DBMS_OUTPUT.PUT_LINE(o.lbl || ' : No query found');
        CONTINUE;
      END IF;

      -- Convert the BLOB to text to get the SQL query
      DBMS_LOB.CREATETEMPORARY(c,TRUE);
      n:=1;
      -- << loop_through_blob >>
      WHILE (n+32767<=LENGTH(b)) LOOP
        DBMS_LOB.WRITEAPPEND(c,32767,UTL_RAW.CAST_TO_VARCHAR2(DBMS_LOB.SUBSTR(b,32767,n)));
        n:=n+32767;
      END LOOP;
      DBMS_LOB.WRITEAPPEND(c,length(b)-n+1,UTL_RAW.CAST_TO_VARCHAR2(DBMS_LOB.SUBSTR(b,length(b)-n+1,n)));

      -- Execute explain plan
      execute immediate 'EXPLAIN PLAN SET STATEMENT_ID=''temp1'' FOR ' || c;

      -- Look at the result of the explain plan, and get all the lines of OBJECT_TYPE='TABLE'
      -- << loop_through_plan >>
      FOR p IN ( SELECT OBJECT_NAME FROM PLAN_TABLE WHERE STATEMENT_ID='temp1' AND OBJECT_TYPE='TABLE') LOOP
          DBMS_OUTPUT.PUT_LINE(o.lbl || ', ' || p.OBJECT_NAME);
      END LOOP;

      execute immediate 'DELETE FROM PLAN_TABLE WHERE STATEMENT_ID=''temp1'' ';

  END LOOP;
  DBMS_OUTPUT.PUT_LINE('-- Completed --');
END;