oracle - Oracle 中的动态提示
问题描述
我正在研究是否可以在 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 相当复杂)而不得不放弃它们。
你知道如何实现这样的事情吗?谢谢!
解决方案
好的,我将从完全否定这种方法开始。我编写了很多高性能的 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 /”,并且您将在每个客户站点以不同的方式填充此表。您显然可以比这更复杂。
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
推荐阅读
- python - 在 filtfilt 的情况下,ba 和 sos 过滤器顺序不同?
- angular - 检索 firebase 列表数据以创建动态表
- java - 当 double 作为 int 输入时,尝试输出不带小数的 double
- bash - Bash 递归脚本变得非常慢
- python - 如何在 python 代码中自动识别加密最佳实践
- python - 直接从“云”或“在线”github 工作
- apache-kafka - 禁用 Kafka 会话超时
- android - FirebaseRecyclerAdapter 没有显示任何内容
- neo4j - 将 Neo4j 子图导出到 Http 端点
- java - 具有多层项目的 ManageDependencies 的 Maven 问题