我正在尝试在用于创建materialisd视图的脚本中搜索关键字
CUSTOMER
。我通过搜索表 QUERY
的 all_mviews
列来完成此操作。所以理论上这个说法
SELECT *
FROM ALL_MVIEWS
WHERE UPPER(QUERY) LIKE '%CUSTOMER%';
应该可以。但是,因为查询不是 CHAR 数据类型,所以我无法执行此操作。我尝试过使用
TO_CHAR(QUERY)
、DMBS_LOB.INSTR(QUERY, 'CUSTOMER')
、TO_LOB(QUERY)
。似乎什么都不起作用。理想情况下,我想用普通 SQL 而不是 PL/SQL 来完成此操作。
您当然可以使用纯 SQL 进行查询,但您将无法摆脱在幕后使用 PL/SQL。那是因为 LONG 只能由 PL/SQL 操作。
要实现此目的,您必须编写一个 PL/SQL 函数来包装相关字典视图(此处为
all_mviews
),将 LONG
数据类型转换为 CLOB
,并发出替换行。然后,您可以使用纯 SQL 查询来查询该函数,并像平常一样对其应用搜索谓词。这是适用于 19c 中可用列的版本:
CREATE OR REPLACE TYPE dba_mviews_rectype IS OBJECT (
CONTAINER_NAME VARCHAR2(128),
QUERY CLOB,
QUERY_LEN NUMBER,
UPDATABLE VARCHAR2(1),
UPDATE_LOG VARCHAR2(128),
MASTER_ROLLBACK_SEG VARCHAR2(128),
MASTER_LINK VARCHAR2(128),
REWRITE_ENABLED VARCHAR2(1),
REWRITE_CAPABILITY VARCHAR2(9),
REFRESH_MODE VARCHAR2(9),
REFRESH_METHOD VARCHAR2(8),
BUILD_MODE VARCHAR2(9),
FAST_REFRESHABLE VARCHAR2(18),
LAST_REFRESH_TYPE VARCHAR2(8),
LAST_REFRESH_DATE DATE,
LAST_REFRESH_END_TIME DATE,
STALENESS VARCHAR2(19),
AFTER_FAST_REFRESH VARCHAR2(19),
UNKNOWN_PREBUILT VARCHAR2(1),
UNKNOWN_PLSQL_FUNC VARCHAR2(1),
UNKNOWN_EXTERNAL_TABLE VARCHAR2(1),
UNKNOWN_CONSIDER_FRESH VARCHAR2(1),
UNKNOWN_IMPORT VARCHAR2(1),
UNKNOWN_TRUSTED_FD VARCHAR2(1),
COMPILE_STATE VARCHAR2(19),
USE_NO_INDEX VARCHAR2(1),
STALE_SINCE DATE,
NUM_PCT_TABLES NUMBER,
NUM_FRESH_PCT_REGIONS NUMBER,
NUM_STALE_PCT_REGIONS NUMBER,
SEGMENT_CREATED VARCHAR2(3),
EVALUATION_EDITION VARCHAR2(128),
UNUSABLE_BEFORE VARCHAR2(128),
UNUSABLE_BEGINNING VARCHAR2(128),
DEFAULT_COLLATION VARCHAR2(100),
ON_QUERY_COMPUTATION VARCHAR2(1)
)
/
CREATE OR REPLACE TYPE dba_mviews_tabtype IS TABLE OF dba_mviews_rectype
/
CREATE OR REPLACE FUNCTION f_dba_mviews_ext (in_owner IN varchar2, in_mview_name IN varchar2)
RETURN dba_mviews_tabtype PIPELINED
AS
var_cursor binary_integer;
var_query varchar2(4000);
res pls_integer;
tab_desc dbms_sql.desc_tab;
var_column_count pls_integer;
rec_dummy_mview dba_mviews_rectype;
var_owner dba_mviews.owner%TYPE;
var_mview_name dba_mviews.mview_name%TYPE;
BEGIN
var_query := 'SELECT *
FROM dba_mviews
WHERE owner = :owner
AND mview_name = :mview_name';
var_cursor := dbms_sql.open_cursor;
dbms_sql.parse(var_cursor,var_query,dbms_sql.native);
dbms_sql.bind_variable(var_cursor,'owner',in_owner);
dbms_sql.bind_variable(var_cursor,'mview_name',in_mview_name);
dbms_sql.define_column(var_cursor,1,var_owner,128);
dbms_sql.define_column(var_cursor,2,var_mview_name,128);
dbms_sql.define_column(var_cursor,3,rec_dummy_mview.container_name,128);
dbms_sql.define_column_long(var_cursor,4);
dbms_sql.define_column(var_cursor,5,rec_dummy_mview.query_len);
dbms_sql.define_column(var_cursor,6,rec_dummy_mview.updatable,1);
dbms_sql.define_column(var_cursor,7,rec_dummy_mview.update_log,128);
dbms_sql.define_column(var_cursor,8,rec_dummy_mview.master_rollback_seg,128);
dbms_sql.define_column(var_cursor,9,rec_dummy_mview.master_link,128);
dbms_sql.define_column(var_cursor,10,rec_dummy_mview.rewrite_enabled,1);
dbms_sql.define_column(var_cursor,11,rec_dummy_mview.rewrite_capability,9);
dbms_sql.define_column(var_cursor,12,rec_dummy_mview.refresh_mode,9);
dbms_sql.define_column(var_cursor,13,rec_dummy_mview.refresh_method,8);
dbms_sql.define_column(var_cursor,14,rec_dummy_mview.build_mode,9);
dbms_sql.define_column(var_cursor,15,rec_dummy_mview.fast_refreshable,18);
dbms_sql.define_column(var_cursor,16,rec_dummy_mview.last_refresh_type,8);
dbms_sql.define_column(var_cursor,17,rec_dummy_mview.last_refresh_date);
dbms_sql.define_column(var_cursor,18,rec_dummy_mview.last_refresh_end_time);
dbms_sql.define_column(var_cursor,19,rec_dummy_mview.staleness,19);
dbms_sql.define_column(var_cursor,20,rec_dummy_mview.after_fast_refresh,19);
dbms_sql.define_column(var_cursor,21,rec_dummy_mview.unknown_prebuilt,1);
dbms_sql.define_column(var_cursor,22,rec_dummy_mview.unknown_plsql_func,1);
dbms_sql.define_column(var_cursor,23,rec_dummy_mview.unknown_external_table,1);
dbms_sql.define_column(var_cursor,24,rec_dummy_mview.unknown_consider_fresh,1);
dbms_sql.define_column(var_cursor,25,rec_dummy_mview.unknown_import,1);
dbms_sql.define_column(var_cursor,26,rec_dummy_mview.unknown_trusted_fd,1);
dbms_sql.define_column(var_cursor,27,rec_dummy_mview.compile_state,19);
dbms_sql.define_column(var_cursor,28,rec_dummy_mview.use_no_index,1);
dbms_sql.define_column(var_cursor,29,rec_dummy_mview.stale_since);
dbms_sql.define_column(var_cursor,30,rec_dummy_mview.num_pct_tables);
dbms_sql.define_column(var_cursor,31,rec_dummy_mview.num_fresh_pct_regions);
dbms_sql.define_column(var_cursor,32,rec_dummy_mview.num_stale_pct_regions);
dbms_sql.define_column(var_cursor,33,rec_dummy_mview.segment_created,3);
dbms_sql.define_column(var_cursor,34,rec_dummy_mview.evaluation_edition,128);
dbms_sql.define_column(var_cursor,35,rec_dummy_mview.unusable_before,128);
dbms_sql.define_column(var_cursor,36,rec_dummy_mview.unusable_beginning,128);
dbms_sql.define_column(var_cursor,37,rec_dummy_mview.default_collation,100);
dbms_sql.define_column(var_cursor,38,rec_dummy_mview.on_query_computation,1);
res := dbms_sql.execute(var_cursor);
WHILE dbms_sql.fetch_rows(var_cursor) > 0
LOOP
DECLARE
var_query_clob clob;
var_offset pls_integer := 0;
var_buffer_length pls_integer := 32760;
var_value_length pls_integer := 0;
var_long_piece long;
rec_mview dba_mviews_rectype := dba_mviews_rectype(NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL);
BEGIN
dbms_sql.column_value(var_cursor,3,rec_mview.container_name);
dbms_lob.createtemporary(var_query_clob, false, dbms_lob.call);
LOOP
dbms_sql.column_value_long(c => var_cursor,
position => 4,
length => var_buffer_length,
offset => var_offset,
value => var_long_piece,
value_length => var_value_length);
EXIT WHEN var_value_length = 0;
dbms_lob.append(var_query_clob, var_long_piece);
var_offset := var_offset + var_value_length;
END LOOP;
rec_mview.query := var_query_clob;
dbms_sql.column_value(var_cursor,5,rec_mview.query_len);
dbms_sql.column_value(var_cursor,6,rec_mview.updatable);
dbms_sql.column_value(var_cursor,7,rec_mview.update_log);
dbms_sql.column_value(var_cursor,8,rec_mview.master_rollback_seg);
dbms_sql.column_value(var_cursor,9,rec_mview.master_link);
dbms_sql.column_value(var_cursor,10,rec_mview.rewrite_enabled);
dbms_sql.column_value(var_cursor,11,rec_mview.rewrite_capability);
dbms_sql.column_value(var_cursor,12,rec_mview.refresh_mode);
dbms_sql.column_value(var_cursor,13,rec_mview.refresh_method);
dbms_sql.column_value(var_cursor,14,rec_mview.build_mode);
dbms_sql.column_value(var_cursor,15,rec_mview.fast_refreshable);
dbms_sql.column_value(var_cursor,16,rec_mview.last_refresh_type);
dbms_sql.column_value(var_cursor,17,rec_mview.last_refresh_date);
dbms_sql.column_value(var_cursor,18,rec_mview.last_refresh_end_time);
dbms_sql.column_value(var_cursor,19,rec_mview.staleness);
dbms_sql.column_value(var_cursor,20,rec_mview.after_fast_refresh);
dbms_sql.column_value(var_cursor,21,rec_mview.unknown_prebuilt);
dbms_sql.column_value(var_cursor,22,rec_mview.unknown_plsql_func);
dbms_sql.column_value(var_cursor,23,rec_mview.unknown_external_table);
dbms_sql.column_value(var_cursor,24,rec_mview.unknown_consider_fresh);
dbms_sql.column_value(var_cursor,25,rec_mview.unknown_import);
dbms_sql.column_value(var_cursor,26,rec_mview.unknown_trusted_fd);
dbms_sql.column_value(var_cursor,27,rec_mview.compile_state);
dbms_sql.column_value(var_cursor,28,rec_mview.use_no_index);
dbms_sql.column_value(var_cursor,29,rec_mview.stale_since);
dbms_sql.column_value(var_cursor,30,rec_mview.num_pct_tables);
dbms_sql.column_value(var_cursor,31,rec_mview.num_fresh_pct_regions);
dbms_sql.column_value(var_cursor,32,rec_mview.num_stale_pct_regions);
dbms_sql.column_value(var_cursor,33,rec_mview.segment_created);
dbms_sql.column_value(var_cursor,34,rec_mview.evaluation_edition);
dbms_sql.column_value(var_cursor,35,rec_mview.unusable_before);
dbms_sql.column_value(var_cursor,36,rec_mview.unusable_beginning);
dbms_sql.column_value(var_cursor,37,rec_mview.default_collation);
dbms_sql.column_value(var_cursor,38,rec_mview.on_query_computation);
PIPE ROW(rec_mview);
END;
END LOOP;
dbms_sql.close_cursor(var_cursor);
RETURN;
EXCEPTION
WHEN OTHERS THEN
dbms_output.put_line(SQLERRM);
IF dbms_sql.is_open(var_cursor)
THEN
dbms_sql.close_cursor(var_cursor);
END IF;
RAISE;
END;
/
CREATE OR REPLACE VIEW dba_mviews_ext
AS
SELECT v.owner,
v.mview_name,
x.*
FROM dba_mviews v
CROSS APPLY TABLE(f_dba_mviews_ext(v.owner,v.mview_name)) x
ORDER BY owner,mview_name
/
CREATE OR REPLACE VIEW all_mviews_ext
AS
SELECT v.owner,
v.mview_name,
x.*
FROM all_mviews v
CROSS APPLY TABLE(f_dba_mviews_ext(v.owner,v.mview_name)) x
ORDER BY owner,mview_name
/
CREATE OR REPLACE VIEW user_mviews_ext
AS
SELECT USER owner,
v.mview_name,
x.*
FROM user_mviews v
CROSS APPLY TABLE(f_dba_mviews_ext(USER,v.mview_name)) x
ORDER BY mview_name
/
GRANT select ON DBA_MVIEWS_EXT TO select_catalog_role;
GRANT select ON ALL_MVIEWS_EXT TO public;
GRANT select ON USER_MVIEWS_EXT TO public;
CREATE PUBLIC SYNONYM DBA_MVIEWS_EXT FOR DBA_MVIEWS_EXT;
CREATE PUBLIC SYNONYM ALL_MVIEWS_EXT FOR ALL_MVIEWS_EXT;
CREATE PUBLIC SYNONYM USER_MVIEWS_EXT FOR USER_MVIEWS_EXT;
现在您可以简单地使用常规 SQL 进行查询:
SELECT *
FROM all_mviews_ext
WHERE UPPER(query) LIKE '%CUSTOMER%'
相同的技术可用于
dba_views
。对于其他更短的 LONG
,永远不会超过 4KB,就像您在 dba_tab_partitions/subpartitions
、dba_tab_columns
、dba_ind_expressions
等中找到的那样。您可以通过将 LONG
转换为 varchar2(4000)
来简化,这可以通过以下方式完成简单的 PL/SQL 变量赋值,因此不需要 dbms_sql
。该代码要短得多,但适用相同的原则:使用 PL/SQL 转换为可搜索数据类型并使用包装该函数的替换视图。
LONG
数据类型在 SQL 中使用时有很多限制,因此您不能直接对 LONG
应用任何函数或使用除 null 测试之外的任何谓词(尽管 Oracle Corporation strongly 建议您将 LONG 列转换为LOB 列至少从版本 8.2(24 年)开始,并且尽快从版本 9.2(21 年)开始,但他们仍然在数据字典中保留这种类型)。
但是可以通过 XML 传递此数据类型并反序列化为
CLOB
,这将允许公开 CLOB
的所有 SQL 功能。您可以使用 DBMS_XMLGEN
包来实现此目的。
create view v_test as
select 'some text' as res
from dual
select
v.owner,
v.view_name,
v.text,
v.text_length
from all_views v
join xmltable(
'/ROWSET/ROW'
passing dbms_xmlgen.getxmltype('
select view_name, owner, text
from all_views
where text is not null')
columns
view_name varchar2(200),
owner varchar2(200),
text clob
) flt
on v.view_name = flt.view_name
and v.owner = flt.owner
where flt.text like '%some%text%'
业主 | VIEW_NAME | 文字 | TEXT_LENGTH |
---|---|---|---|
FIDDLE_SHCEJNRFMOROSMIQCFFB | V_测试 | 从双 选择“某些文本”作为资源 |
35 |
sys_dburigen 应该为你完成这项工作。 它需要一个 LONG 并将返回一个 CLOB
选择我的所有者 , m.mview_name , sys_dburigen( 所有者 , mview_name, 查询, 'text()').getclob() mview_query_text 来自 all_mviews m