在不改变应用程序的前提下,在服务器端将查询语句替换成其他的查询语句执行,此时就需要查询重写(QUERY REWRITE)。DM使用DBMS_ADVANCED_REWRITE包实现该功能,不支持安全策略。DM支持对原始语句中的某些特定词的替换,以及整个语句的替换,不支持递归和变换替换。
相关方法 1. DECLARE_REWRITE_EQUIVALENCE 声明一个等价重写规则。
PROCEDURE DECLARE_REWRITE_EQUIVALENCE
( NAME VARCHAR(128), SOURCE_STMT VARCHAR(8188), DESTINATION_STMT VARCHAR(8188), VALIDATE BOOLEAN, REWRITE_MODE VARCHAR(16) );
参数详解 NAME 重写规则的唯一标识,在会话级唯一。
SOURCE_STMT 原始查询语句。
DESTINATION_STMT 目标语句。
VALIDATE 是否校验原始语句和目标语句等价。
REWRITE_MODE 包含4种:DISABLED,不允许重写;
TEXT_MATCH,文本匹配重写;
GENERAL,变换重写;RECURSIVE,递归重写。后面两种暂不支持,可以声明成功,但是不起作用。
如果一个SOURCE_STMT对应多个DESTINATION_STMT,即用户创建很多相同的重写规则,只是名字不同,在重写时只有第一个才有效。也就是说只执行第一个重写规则,后面的所有重写规则无效。
SOURCE_STMT不能和DESTINATION_STMT 相同,SOURCE_STMT和DESTINATION_STMT语句必须为查询语句, SOURCE_STMT和DESTINATION_STMT语句必须经过语法和语义正确解析
REWRITE_MODE为“TEXT_MATCH”时,只允许替换SOURCE_STMT中完全相同的语句,不区分大小写。
SOURCE_STMT和DESTINATION_STMT语句不允许包含“{}”字符。
扩展功能说明:如果SOURCE_STMT为空,DESTINATION_STMT格式为“TABLE/[TABLE]”,则可以将当前会话语句中的“TABLE”换成“[TABLE]”,“TABLE”为正则表达式。DM支持符合POSIX标准的正则表达式
2.ALTER_REWRITE_EQUIVALENCE 修改重写模式。
PROCEDURE ALTER_REWRITE_EQUIVALENCE ( NAME CHAR(128), REWRITE_MODE VARCHAR(16) );
3.VALIDATE_REWRITE_EQUIVALENCE 校验重写规则是否等效,暂不支持。提供该函数,但是不进行校验。
VALIDATE_REWRITE_EQUIVALENCE ( NAME CHAR(128) );
4.DROP_REWRITE_EQUIVALENCE。 删除重写规则。
5.
字典信息 所有的重写规则信息都保存到系统表SYS_REWRITE_EQUIVALENCES中,该系统表的结构如下表所示。所有的用户创建的语句重写信息都保存到该表中。
通过查询语句可以获得重写规则的信息: SELECT * FROM SYS_REWRITE_EQUIVALENCES;
使用
1.设置会话标记
每个会话对应一个QUERY_REWRITE_INTEGRITY标记,该标记只在会话期间起作用,不保存到字典信息中,如果会话结束,则该标记也无效。会话重建后,该标记也需要重新赋值
才有效。 QUERY_REWRITE_INTEGRITY标记用于表示该会话是否可以执行查询语句重写,默认值为“ENFORCED”,另外两个值为:“TRUSTED”和“STALE_TOLERATED”。默认不允许语句重写
2.重写规则的作用域
重写规则只允许在当前会话中执行,禁止跨模式使用其他用户指定的重写规则。SYSDBA也不可以使用其他用户的重写规则替换。
3.回滚 执行方法DECLARE_REWRITE_EQUIVALENCE后,将自动提交,不能执行回滚。在该方法之前的所有操作也自动提交。
4.自动重写
自动重写,指的是用户在执行任何查询语句时,可以自动调用重写规则执行重写,而不需要设置会话标记来控制是否执行查询重写。SYSDBA可以设置某些用户自动重写标记,设置函数为:SP_USER_SET_AUTO_REWRITE_FLAG。该标记和会话标记中有一个有效,则允许查询重写。
SP_USER_SET_AUTO_REWRITE_FLAG ( ‘USER_NAME’, VALUE );
USER_NAME用户名。 VALUE0表示不允许自动重写,1表示允许自动重写。
5.关闭重用执行计划功能
使用时,可以在DM.INI中将重用执行计划标记(USE_PLN_POOL)置为0。否则,先执行过查询语句后,再设置查询规则,然后对比两次的查询结果会相同,即未被重写。如果不关闭,只能等到设置过查询规则之后,才能执行查询。
修改dm.ini 的USE_PLN_POOL参数 修改为0,重启实例
使用前先开启系统包可以看到系统包都在sys模式下,系统包不能删除,只能开启和关闭
系统包多次关闭不会报错,不能多次开启
使用SP_USER_SET_AUTO_REWRITE_FLAG,设置用户是否能够自动重写
创建表数据
添加等价重写规则。
查询重写规则
查询效果,从x1表重写查询到x2表
没有设置会话标志,默认不允许重写
设置会话标志
删除重写规则
创建一个新的重写规则,为空时处理
查询结果
语句如下
call SP_CREATE_SYSTEM_PACKAGES (1,‘DBMS_ADVANCED_REWRITE’);
DROP TABLE X1;
CREATE TABLE X1(C1 INT, C2 CHAR(20));
INSERT INTO X1 VALUES(12, ‘TEST12’);
INSERT INTO X1 VALUES(13, ‘TEST13’);
INSERT INTO X1 VALUES(14, ‘TEST14’);
INSERT INTO X1 VALUES(15, ‘TEST15’);
CREATE TABLE X2(D1 INT, D2 CHAR(30));
COMMIT;
BEGIN DBMS_ADVANCED_REWRITE.DECLARE_REWRITE_EQUIVALENCE
( ‘TEST_REWRITE’, ‘SELECT COUNT() FROM X1’,
'SELECT COUNT() FROM X2’, FALSE, ‘TEXT_MATCH’ ); END; /
SELECT COUNT() FROM X1;
ALTER SESSION SET QUERY_REWRITE_INTEGRITY = TRUSTED;
SELECT COUNT() FROM X1;
DBMS_ADVANCED_REWRITE.DROP_REWRITE_EQUIVALENCE (‘TEST_REWRITE’);
BEGIN DBMS_ADVANCED_REWRITE.DECLARE_REWRITE_EQUIVALENCE
( ‘TEST_REWRITE’, NULL,‘FRO./FROM’, FALSE, ‘TEXT_MATCH’ );
END; /
SELECT COUNT(*) FROM X1;
重新使用SP_USER_SET_AUTO_REWRITE_FLAG控制重写
新开一个会话
CALL SP_USER_SET_AUTO_REWRITE_FLAG (‘SYSDBA’,‘1’);
SELECT * FROM SYS_REWRITE_EQUIVALENCES;
DROP TABLE X1;
CREATE TABLE X1(C1 INT, C2 CHAR(20));
INSERT INTO X1 VALUES(12, ‘TEST12’);
INSERT INTO X1 VALUES(13, ‘TEST13’);
INSERT INTO X1 VALUES(14, ‘TEST14’);
INSERT INTO X1 VALUES(15, ‘TEST15’);
drop TABLE x2;
CREATE TABLE X2(D1 INT, D2 CHAR(30));
COMMIT;
DBMS_ADVANCED_REWRITE.DROP_REWRITE_EQUIVALENCE (‘TEST_REWRITE’);
BEGIN DBMS_ADVANCED_REWRITE.DECLARE_REWRITE_EQUIVALENCE
( ‘TEST_REWRITE’, ‘SELECT COUNT() FROM X1’,
'SELECT COUNT() FROM X2’, FALSE, ‘TEXT_MATCH’ ); END; /
SELECT COUNT(*) FROM X1;
使用前先查询规则,删除并重新创建
DBMS_ADVANCED_REWRITE.DROP_REWRITE_EQUIVALENCE (‘TEST_REWRITE’);
BEGIN DBMS_ADVANCED_REWRITE.DECLARE_REWRITE_EQUIVALENCE
( ‘TEST_REWRITE’, NULL,‘FRO./FROM’, FALSE, ‘TEXT_MATCH’ );
END; /
CALL SP_USER_SET_AUTO_REWRITE_FLAG (‘SYSDBA’,‘1’);
DROP TABLE X1;
CREATE TABLE X1(C1 INT, C2 CHAR(20));
INSERT INTO X1 VALUES(12, ‘TEST12’);
INSERT INTO X1 VALUES(13, ‘TEST13’);
INSERT INTO X1 VALUES(14, ‘TEST14’);
INSERT INTO X1 VALUES(15, ‘TEST15’);
CREATE TABLE X2(D1 INT, D2 CHAR(30));
COMMIT;
BEGIN DBMS_ADVANCED_REWRITE.DECLARE_REWRITE_EQUIVALENCE
( ‘TEST_REWRITE’, ‘SELECT COUNT() FROM X1’,
'SELECT COUNT() FROM X2’, FALSE, ‘TEXT_MATCH’ ); END; /
SELECT COUNT(*) FROM X1;
ALTER SESSION SET QUERY_REWRITE_INTEGRITY = TRUSTED;
SELECT COUNT(*) FROM X1;
DBMS_ADVANCED_REWRITE.DROP_REWRITE_EQUIVALENCE (‘TEST_REWRITE’);
BEGIN DBMS_ADVANCED_REWRITE.DECLARE_REWRITE_EQUIVALENCE
( ‘TEST_REWRITE’, NULL,‘FRO./FROM’, FALSE, ‘TEXT_MATCH’ );
END; /
SELECT COUNT(*) FROM X1;
使用sysdba把系统包权限授予新建用户,判断新建用户是否会被SP_USER_SET_AUTO_REWRITE_FLAG影响
使用SYSDBA用户执行
使用test用户执行
发现SP_USER_SET_AUTO_REWRITE_FLAG参数设置后没有反应
多个重写规则可以同时存在,它们如果
原始语句相同会有什么影响。