如何选择所有可能包含已知特定值的记录,不引用 SQL 表达式中的特定列?
例如,我知道,某些未知列的值为“xxx”,并且有许多列 并记录在表中。
谢谢。
最佳答案
所以,您想对您的数据库进行类似 Google 的自由文本搜索。这是可以做到的,但性能会很糟糕! Google 速度很快,因为它在其索引、重复数据存储上有索引,并且通常会针对此类搜索优化所有内容。
无论如何,这是使用动态 SQL 和 Oracle 数据字典的概念证明。请注意,我将列限制为我要搜索的数据类型,即字符串。
SQL> set serveroutput on size unlimited
SQL> declare
2 dummy varchar2(1);
3 begin
4 for r in ( select table_name, column_name from user_tab_cols
5 where data_type in ('VARCHAR2', 'CHAR', 'CLOB') )
6 loop
7 begin
8 execute immediate 'select null from '||r.table_name
9 ||' where '||r.column_name||' like ''%&search_value%'' '
10 ||' and rownum = 1'
11 into dummy;
12 dbms_output.put_line('Found it in >>>'
13 ||r.table_name||'.'||r.column_name);
14 exception
15 when others then
16 -- bad practice ahoy!
17 null;
18 end;
19 end loop;
20 end;
21 /
Enter value for search_value: MAISIE
old 9: ||' where '||r.column_name||' like ''%&search_value%'' '
new 9: ||' where '||r.column_name||' like ''%MAISIE%'' '
Found it in >>>T23.NAME
PL/SQL procedure successfully completed.
SQL>
更健壮的实现可能需要处理大小写、整个单词等。如果您使用 10g 或更高版本,那么正则表达式可能会有用,但是结合正则表达式和动态 SQL 是一个,呃,有趣 前景。
我再说一遍,表演会很糟糕!在一个大数据集上。调优几乎是不可能的,因为我们无法索引每一列,当然也不支持 LIKE 或类似的模糊匹配。另一种方法是使用 XQuery 生成数据的 XML 表示,然后使用 Text 对其进行索引。维护这样的存储库会产生开销,但如果您需要定期使用此功能,尤其是在生产环境中,那么这项工作将是一项明智的投资。
我们可以通过使用 all_tab_cols
来对我们有权限的所有表进行更广泛的搜索。
for r in ( select owner, table_name, column_name from all_tab_cols
where data_type in ('VARCHAR2', 'CHAR', 'CLOB') )
显然,我们需要在生成的语句中为所属模式添加前缀。
execute immediate 'select null from '||r.owner||'.'||r.table_name
||' where '||r.column_name||' like ''%
关于SQL 选择可能包含特定值的所有记录,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3288199/