需要一个查询来从所有表/视图中搜索一个值(“数字”)

Posted

技术标签:

【中文标题】需要一个查询来从所有表/视图中搜索一个值(“数字”)【英文标题】:Need a Query to search a value("Number") from all tables/views 【发布时间】:2015-08-26 12:18:08 【问题描述】:

我使用 Oracle 11G 数据库并在 Toad 中工作。我需要一个查询来在所有表和视图中搜索一个数字(9901)。我找到了一些 PL/SQL 代码,但它们适用于字符串。我有关于 SQL 的知识,但我不知道 PL/SQL。我的用户是 SYS,我想我有权进行这样的查询。你能帮忙处理这个案子吗?

【问题讨论】:

如果你想查询它,你想要什么作为查询的返回值? 我想查看所有包含 number(9901) 的列和表/视图名称。 查看***.com/questions/208493/… 【参考方案1】:

如果您想搜索表/列的名称或表中包含的实际值,我没有收集。

在前一种情况下,您的目标可以通过一个简单的查询来实现(将过滤器中的值替换为正确的值(但保留 % 符号)):

select 
    owner, 
    table_name, 
    column_name
from 
    dba_tab_columns
where
    owner = '<TABLE_OWNER>'
    and ( table_name like '%<SEARCH_VALUE>%'
        or column_name like '%<SEARCH_VALUE>%' );

搜索实际的表数据有点复杂... 以下是执行此类搜索的示例计划:

    缩小搜索范围 - 按表所有者过滤(您确实不想在 SYS 或 SYSTEM 表中搜索...) 识别潜在的匹配候选者 - 在我们的案例中,表格包含数字列,因为我们正在搜索数字 检查每个表中是否有所需的值 找出包含所需值的确切列

这是一个示例 PL/SQL 脚本,它执行搜索并打印表名和列名(将 _SCHEMA_NAME_ 更改为正确的值):

declare
    v_owner varchar2( 30 ) := '_SCHEMA_NAME_';
    v_search_value number := 9901;

    v_query_template varchar2( 500 ) := 'select ''x'' from dual where exists ( select 1 from <OWNER>.<TABLE> where <FILTER> )';
    v_filter clob;
    v_query clob;
    v_match char(1);
begin
    -- loop through all tables which are potential candidates - have numeric columns
    for v_tab_row in
    (
        select distinct owner, table_name
        from dba_tab_columns
        where 
            owner = v_owner
            and data_type in ( 'NUMBER', 'FLOAT' )
    ) loop
        v_filter := '';

        -- loop through each table column in order to build general match query
        for v_col_row in
        (
            select owner, table_name, column_name
            from dba_tab_columns
            where 
                owner = v_tab_row.owner
                and table_name = v_tab_row.table_name
                and data_type in ( 'NUMBER', 'FLOAT' )
        ) loop
            v_filter := v_filter || v_col_row.column_name || ' = ' || v_search_value || ' or ';
        end loop;
            v_filter := rtrim( v_filter, ' or ' );


        v_query := replace( v_query_template, '<OWNER>', v_owner );
        v_query := replace( v_query, '<TABLE>', v_tab_row.table_name );
        v_query := replace( v_query, '<FILTER>', v_filter );

        -- debug output:
        --dbms_output.put_line( v_query );

        begin

            -- check if the table contains the search value anywhere in it
            -- if not foung throws NO_DATA_FOUND exception and the loop continues
            execute immediate v_query into v_match;

            -- print the table name
            dbms_output.put_line( v_tab_row.owner || '.' || v_tab_row.table_name );

            -- loop through each table column to check which one of them contains the desired value
            for v_col_row in
            (
                select owner, table_name, column_name
                from dba_tab_columns
                where 
                    owner = v_tab_row.owner
                    and table_name = v_tab_row.table_name
                    and data_type in ( 'NUMBER', 'FLOAT' )
            ) loop
                begin
                    v_query := replace( v_query_template, '<OWNER>', v_owner );
                    v_query := replace( v_query, '<TABLE>', v_tab_row.table_name );
                    v_query := replace( v_query, '<FILTER>', v_col_row.column_name || ' = ' || v_search_value );

                    -- debug output:
                    --dbms_output.put_line( v_query );

                    -- check if the specific column contains the desired value
                    -- if not foung throws NO_DATA_FOUND exception and the loop continues
                    execute immediate v_query into v_match;

                    -- print the column name
                    dbms_output.put_line( v_col_row.owner || '.' || v_col_row.table_name || '.' || v_col_row.column_name );
                exception
                when NO_DATA_FOUND 
                    then 
                        -- do nothing
                        null;
                end;
            end loop;
        exception
            when NO_DATA_FOUND 
                then 
                    -- do nothing
                    null;
        end;
    end loop;
end;

也可以轻松修改代码以执行文本搜索 - 只需在循环查询中包含 varchar2、nvarchar2、char 和 nchar 数据类型。

重要提示! - 如果您的数据库中有很多/大型表,这将运行非常缓慢并且可能会给系统带来高负载。毕竟会涉及到多次全表扫描。


对于视图,您需要检查报告表上每个视图的代码,并检查它是否包含任何报告列。

【讨论】:

ORA-06550:第 14 行,第 14 列:PL/SQL:ORA-00942:表或视图不存在 ORA-06550:第 13 行,第 9 列:PL/SQL:SQL 语句被忽略 ORA -06550:第 28 行,第 34 列:PLS-00364:循环索引变量“V_TAB_ROW”使用无效 ORA-06550:第 28 行,第 34 列:PL/SQL:ORA-00904:“V_TAB_ROW”。“TABLE_NAME”:geçersiz belirleyici ORA-06550:第 24 行,第 13 列:PL/SQL:SQL 语句被忽略 ORA-06550:第 31 行,第 37 列:它给出了这样的错误。我不知道原因。我更改了架构名称。 而且我不是在搜索列名或表名。我正在搜索值 9901,即在表/视图的记录中。 很可能您在字典视图 dba_tab_columns 上没有选择权限。如果您以要在其中执行搜索的表的所有者身份登录,请将其替换为 user_tab_columns 忘了提到 user_tab_columns 没有“所有者”列,因为那里描述的所有对象都是当前用户的财产。 all_tab_columns 包含有关所有当前可访问对象的信息,因此有一个“所有者”列。

以上是关于需要一个查询来从所有表/视图中搜索一个值(“数字”)的主要内容,如果未能解决你的问题,请参考以下文章

需要一个查询来从我的 sql 中的表中获取不同的数据

在所有表中搜索多个值

火鸟搜索并在所有列中找到一个字符串值

如何使用 sql 查询使用注册日期列搜索网格视图

需要一个 SQL 查询来从 SQL Server 数据库中获取特定条件下给定时间段的数据

如何在SQL Server的数据库中搜索字符串