SQL:搜索具有给定值的列的列表(在一行内)

Dav*_*ill 7 sql oracle

我有一个包含许多列的表.有没有办法使查询回答问题:"对于特定的_id(主键),此行中的哪些字段的值为10"?

编辑:

澄清:表格设置正确.我正在进行的查询是一些手动查询,因为我跟踪了一些不正确的数据.该表已针对自动查询进行了优化,以便代表运行的大量查询.(并且有超过9500万行,每一点优化都很重要)

我意识到我的问题是要求做一些SQL不打算做的事情.我只是希望有一些技巧可以得到我想要的东西.

编辑后人:

在我们的系统中,我们有许多不同的用户帐户.一个帐户是我们用于所有只读查询的帐户(这是我大部分时间都使用的帐户).它不拥有相关表格,所以当我根据自己的情况调整答案时,我不得不做出以下更改:

USER_TAB_COLUMNS必须成为ALL_TAB_COLUMNS,我不得不添加OWNER = '[OWNER]'到查询.

APC*_*APC 3

这不是正常的数据库功能。然而,您并不是第一个提出此要求或类似要求的人。

该解决方案需要两件事。首先是数据字典;Oracle 数据库不支持反射,但它确实附带了一组视图,这些视图为我们提供有关数据库对象的元数据。在本例中,我们需要user_tab_columns,它将为我们提供给定表的列。第二件事是动态SQL;这是在运行时组装 SQL 查询然后执行它的能力。有几种方法可以做到这一点,但通常引用游标就足够了。

以下代码是概念证明。它需要四个参数:

  1. 您要搜索的表的名称
  2. 该表的主键列的名称
  3. 您想要限制的主键值
  4. 您要搜索的值。

它还很粗糙,因此您可能需要对其进行编辑以整理输出或使程序更加灵活。

create or replace procedure search_cols
  (tname in user_tables.table_name%type
   , pk_col in user_tab_columns.column_name%type
   , pk in number
   , val in number )
is
    firstcol boolean := true;
    stmt varchar2(32767);
    result varchar2(32767);
    rc sys_refcursor;
begin
    stmt := 'select ';
    << projection >>
    for lrec in ( select column_name from user_tab_columns
                  where table_name = tname
                  and column_name != pk_col
                  and data_type = 'NUMBER'
                  order by column_id )
    loop
        if not firstcol then
            stmt := stmt || chr(10) || '||'',''||';
        else
            firstcol := false;
        end if;
        stmt := stmt || ' case when '|| lrec.column_name||' = '|| val ||
                           ' then '''|| lrec.column_name || ''' else null end';
    end loop projection;
    stmt := stmt || chr(10)|| ' from '||tname||' where '|| pk_col || ' = '|| pk;
    --  dbms_output.put_line(stmt);
    open rc for stmt;
    fetch rc into result;
    close rc;
    dbms_output.put_line(tname || '::' || val || ' found in '||result);
end search_cols;
/
Run Code Online (Sandbox Code Playgroud)

正如您所看到的,动态 SQL 很难阅读。调试起来比较困难:) 因此,最好有一种方法来显示最终的语句。

无论如何,结果如下:

SQL> set serveroutput on size unlimited
SQL> exec search_cols('T23', 'ID', 111, 10)
T23::10 found in ,COL_B,COL_C,

PL/SQL procedure successfully completed.

SQL> exec search_cols('T23', 'ID', 222, 10)
T23::10 found in COL_A,,,

PL/SQL procedure successfully completed.

SQL>
Run Code Online (Sandbox Code Playgroud)