【问题标题】:Check table access for Oracle SQL statements in BLOB检查 BLOB 中 Oracle SQL 语句的表访问
【发布时间】:2019-02-12 06:58:57
【问题描述】:

我有一个表,其中有一列包含 BLOB 格式的 SQL 查询(仅限选择语句)。 我正在尝试找出一种方法来分析 SQL 查询,并检查每个 SQL 查询将访问哪些表。

有人做过类似的吗?

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

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

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

【问题讨论】:

  • 如果您有权选择所有表,您的方法应该有效。但是,为什么将 SQL 查询存储为BLOB 而不是CLOB
  • @Wernfried Domscheit 我也有同样的问题。不幸的是我没有控制数据模型,我只能查看已经存储在DB中的数据..

标签: sql oracle plsql blob


【解决方案1】:

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

在 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'; 

【讨论】:

  • 谢谢,理论上可行。不幸的是,我没有足够的权限来创建新对象,所以我需要一些可以由只读用户执行的东西。
  • @jellyfizz :你确定解释计划对你有用吗?顺便说一句,您不必在生产中执行所有这些操作,可以使用具有所有表集的测试设置。
  • 是的,说明计划有效。我已经到了可以“立即执行'解释计划'|| c;”的阶段。现在已经开始,并分析“SELECT PLAN_TABLE_OUTPUT FROM TABLE(DBMS_XPLAN.DISPLAY()) where PLAN_TABLE_OUTPUT like '%TABLE ACCESS%';”的结果。如果有更简单的方法肯定会有所帮助。谢谢。
【解决方案2】:

所以,我是这样做的:

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;

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-02-10
    • 2012-12-05
    • 1970-01-01
    • 1970-01-01
    • 2021-02-09
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多