Oracle中的动态提示

时间:2019-03-29 10:52:49

标签: oracle hints

我正在研究是否可以在Oracle中使用动态提示。我们拥有针对大量具有不同数据量的客户的系统,因此我们希望针对每个客户进行个性化查询。

我想这样做:

PROCEDURE PROCESS_STEP_1 (p_cust_id NUMBER)
IS
  v_hint_value NUMBER;
BEGIN
  -- Select correct value from param table
  SELECT value INTO v_hint_value
    FROM param_table
    WHERE cust_id = p_cust_id
      AND process_name = 'PROCESS_STEP_1';

  INSERT INTO result_table  
  SELECT /*+ PARALLEL v_hint_value */ * FROM etc.

END;

我知道可以通过动态查询来做到这一点。由于可读性差和其他问题(这些SQL相当复杂),我们有很多它们,不得不放弃它们。

您是否知道如何实施这种方法?谢谢!

1 个答案:

答案 0 :(得分:2)

好的,我将首先完全拒绝这种方法。我编写了许多高性能的SQL应用程序,很少使用提示。您似乎在谈论一个大型提示应用程序,其中提示因安装而异,这是一个很大的危险信号。我建议您尝试删除提示并解决可能存在的潜在应用程序设计问题。

总而言之,Oracle具有SQL转换功能。它旨在让您从为非Oracle数据库编写的应用程序转换SQL,但是它也可以满足您的目的。您要做的就是使用此功能在Oracle解析前在任何入站SQL语句中“翻译”提示。

这里是示例代码,用于说明概念并入门。再一次-我不建议这样做,但是SO是答案的地方,而不是讲座,所以这里是...

步骤1-确保您具有执行此操作的权限

-- GRANT CREATE ANY SQL TRANSLATION PROFILE TO yourapplication
-- GRANT TRANSLATE ANY SQL TO yourapplication
-- GRANT USE ANY SQL TRANSLATION PROFLE TO yourapplication
-- GRANT EXECUTE ON SYS.DBMS_SQL_TRANSLATOR TO yourapplication

创建一个表来存储提示翻译

这里的想法是,您在应用程序中嵌入了诸如“ / + HINT12345 /”之类的提示,并且您将在每个客户站点以不同的方式填充此表。显然,您可以比此更加复杂。 / p>

CREATE TABLE myapp_hint_translations ( hint_id VARCHAR2(80), hint_text VARCHAR2(800) );

INSERT INTO myapp_hint_translations VALUES ( '/*+HINT12345*/','/*+PARALLEL(4)*/');

COMMIT;

创建一个PL / SQL包以执行提示翻译

您必须使用给定的过程名称和参数。他们是必需的 我们将使用的DBMS_SQL_TRANSLATOR软件包。

CREATE OR REPLACE PACKAGE myapp_hint_translator IS
  PROCEDURE translate_sql( sql_text IN CLOB, 
                           translated_text OUT CLOB );

  PROCEDURE translate_error( error_code IN BINARY_INTEGER,
                             translated_code OUT BINARY_INTEGER,
                             translated_sqlstate OUT VARCHAR2 );

END myapp_hint_translator;
/

CREATE OR REPLACE PACKAGE BODY myapp_hint_translator IS
  PROCEDURE translate_sql( sql_text IN CLOB, 
                           translated_text OUT CLOB ) IS
  BEGIN
    <<hint_search>>
    FOR r IN ( SELECT hint_id, hint_text FROM myapp_hint_translations ) LOOP
      IF INSTR(sql_text, r.hint_id ) > 0 THEN
        translated_text := replace(sql_text,r.hint_id,r.hint_text);
        RETURN;
      END IF;
    END LOOP;
    -- No translation made
    translated_text := sql_text;
  END translate_sql;

  PROCEDURE translate_error( error_code IN BINARY_INTEGER,
                             translated_code OUT BINARY_INTEGER,
                             translated_sqlstate OUT VARCHAR2 ) IS
  BEGIN
    -- We are not using this feature
    NULL;
  END;

END myapp_hint_translator;

告诉Oracle开始使用我们的翻译器

BEGIN
  dbms_sql_translator.create_profile(profile_name => 'MYAPP');
  dbms_sql_translator.set_attribute(profile_name => 'MYAPP',
                                    attribute_name => dbms_sql_translator.attr_translator,
                                    attribute_value => 'myappschema.myapp_hint_translator');
END;

ALTER SESSION SET SQL_TRANSLATION_PROFILE=MYAPP;

ALTER SESSION SET EVENTS = '10601 trace name context forever, level 32';

-- Test some of your application and verify hints are being translated