【问题标题】:how to track and modify an in-flight oracle query before execution?如何在执行前跟踪和修改正在进行的 oracle 查询?
【发布时间】:2021-05-15 17:05:50
【问题描述】:

我的应用程序正在向 Oracle 发送以下查询。

SELECT * FROM EMPLOYEE WHERE DATE > (SYSDATE - 1) order by employee_id

我无法从应用程序更改此查询。我正在寻找一种方法让 oracle 监控查询,将其更改为以下查询格式并返回结果。

SELECT * FROM EMPLOYEE WHERE DATE > (SYSDATE - 1) and Current_employed = 'YES' order by employee_id

谢谢。 子类

【问题讨论】:

  • 为什么不直接更改应用程序以发送正确的查询?
  • 查询是从现在不支持的应用程序产品中触发的。所以我不能修改它。

标签: oracle oracle12c


【解决方案1】:

如果应用程序可以作为与表所有者不同的用户连接到数据库,您还可以实施虚拟专用数据库策略来修改正在进行的查询。见这里:

如果应用程序作为单独的用户连接,您还可以按照@ekochergin 的建议创建一个视图,并在应用程序的用户架构中使用同义词“EMPLOYEE”指向数据所有者架构中的视图。

如果应用程序以数据所有者的身份进行连接,您的选择会受到更多限制。重命名表格并按照建议将其替换为视图将是最简单的选择。如果您有大量资金投资于 Oracle 的数据库应用防火墙设备,您还可以在运行中使用安全策略修改查询。

【讨论】:

    【解决方案2】:

    您可能需要将员工表重命名为有点像“EMP_TABLE”,并使用创建一个名为“EMPLOYEE”的视图

    create view employee as select * from emp_table where currently_employed = 'YES';
    

    在上线之前,请先针对测试实例进行测试

    【讨论】:

      【解决方案3】:

      如果您只需要转换少量语句,请使用 SQL 翻译框架。如果您需要修改许多语句,那么您应该查看其他答案中描述的选项,例如虚拟私有数据库、视图或同义词。

      对于这个示例架构:

      create table employee
      (
          employee_id number,
          hire_date date,
          currently_employed varchar2(3)
      );
      
      insert into employee values(1, sysdate, 'NO');
      insert into employee values(1, sysdate, 'YES');
      
      commit;
      

      创建以下翻译配置文件,然后创建特定翻译:

      begin
          dbms_sql_translator.create_profile('EMPLOYEE_TRANSLATOR_PROFILE');
      
          dbms_sql_translator.register_sql_translation
          (
              profile_name    => 'EMPLOYEE_TRANSLATOR_PROFILE',
              sql_text        => q'[SELECT * FROM EMPLOYEE WHERE HIRE_DATE > (SYSDATE - 1) order by employee_id]',
              translated_text => q'[SELECT * FROM EMPLOYEE WHERE HIRE_DATE > (SYSDATE - 1) and Currently_employed = 'YES' order by employee_id]'
          );
      end;
      /
      

      必须在每个会话中启用翻译配置文件。由于您无法控制应用程序,因此您可以创建一个登录配置文件,该配置文件将自动运行命令以启用翻译:

      --Logon trigger that enables profiles.
      --I'm not sure why, but you must create this trigger as SYS.
      create or replace trigger sys.logon_trg
      after logon on database
      --Add your username here:
      when (user in ('JHELLER'))
      begin
          execute immediate 'alter session set sql_translation_profile = jheller.employee_translator_profile';
          execute immediate q'[alter session set events = '10601 trace name context forever, level 32']';
      end;
      /
      

      现在,当应用程序运行通常会返回两行的原始查询时,它将运行仅返回一行的第二个查询:

      SQL> SELECT * FROM EMPLOYEE WHERE HIRE_DATE > (SYSDATE - 1) order by employee_id;
      
      EMPLOYEE_ID HIRE_DATE CUR
      ----------- --------- ---
                1 12-FEB-21 YES
      

      但要小心会阻止翻译的微小语法更改。比如SELECT改成select,查询不会被替换,会再次返回两行:

      SQL> select * FROM EMPLOYEE WHERE HIRE_DATE > (SYSDATE - 1) order by employee_id;
      
      EMPLOYEE_ID HIRE_DATE CUR
      ----------- --------- ---
                1 12-FEB-21 YES
                1 12-FEB-21 NO
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2012-10-27
        • 1970-01-01
        • 1970-01-01
        • 2017-01-19
        相关资源
        最近更新 更多