在Oracle DB中动态搜索2个值

时间:2018-06-18 17:04:11

标签: sql oracle

美好的一天,

试图绕过这个并设法让它在某种程度上发挥作用 - 但仍然有点挣扎。

我希望在此示例的两列中找到两个值: VARCHAR和DATE 约翰1984-01-01

让我们说这是约翰的出生日期。

我希望能够找到具有DATE值的值JOHN,例如2000表,并使列名称不完全复杂化。数据类型是。

以下选择具有我需要的两个列名的所有表。

SELECT A.TABLE_NAME, A.COLUMN_NAME, B.COLUMN_NAME
  FROM all_tab_columns A
       JOIN all_tab_columns B
          ON     A.TABLE_NAME = B.TABLE_NAME
             AND B.DATA_TYPE = 'DATE'
             AND A.COLUMN_NAME IN ('NAME', 'FULLNAME')

所以,现在我得到了我需要的数据类型为DATE的表,其中列名为NAME和FULLNAME。

所以2000年的表格中我有300个符合我的标准。我想搜索找到约翰的表格,其日期为1984-01-01,其中约翰可以是FULLNAME或NAME,1984-01-01可以是任何列名,即。 DTTM,BDAY,DATEFLD,DTFIELD等。

我希望TABLE_NAME将这两个值存在于同一行中,而不是其他任何内容。

我看过这些类型的例子:

Search All Fields In All Tables For A Specific Value (Oracle)

但不断遇到问题。我错过了什么?

DECLARE
   match_count       INTEGER;
   v_search_string   VARCHAR2 (11) := 'JOHN';
BEGIN
   FOR t
      IN (SELECT A.owner, A.table_name, A.column_name
            FROM all_tab_columns A
                 JOIN all_tab_columns B
                    ON     A.TABLE_NAME = B.TABLE_NAME
                       AND A.COLUMN_NAME IN ('NAME', 'FULLNAME')
                       AND B.DATA_TYPE = 'DATE'
                       AND A.TABLE_NAME LIKE 'DATA%')
   LOOP
      BEGIN
         EXECUTE IMMEDIATE
               'SELECT * FROM '
            || t.owner
            || '.'
            || t.table_name
            || ' WHERE '
            || t.column_name
            || ' = :1 '
            INTO match_count
            USING v_search_string;

         IF match_count > 0
         THEN
            DBMS_OUTPUT.put_line (
                t.table_name
               );
         END IF;
      EXCEPTION
         WHEN OTHERS
         THEN
            DBMS_OUTPUT.put_line (
                  'Error encountered trying to read '
               || t.column_name
               || ' from '
               || t.owner
               || '.'
               || t.table_name);
      END;
   END LOOP;
END;
/

2 个答案:

答案 0 :(得分:1)

我对您的代码做了一些小修改:

before_action :authenticate_user!

答案 1 :(得分:0)

您可以尝试做的是使用all_tab_columns中的select来构造where子句,并在动态where子句中查询相应的表。

SET serveroutput ON 
DECLARE 
    v_count INTEGER; 
BEGIN 
    FOR r IN (SELECT a.table_name, 
                     ' WHERE ' 
                     || LISTAGG(CASE data_type 
                                  WHEN 'DATE' THEN column_name 
                                                   || ' = DATE ' 
                                                   || '''1984-01-01''' 
                                  ELSE column_name 
                                       || ' = ' 
                                       || '''JOHN''' 
                                END, ' or ') 
                          WITHIN GROUP( ORDER BY column_name ) AS where_clause 
              FROM   user_tab_columns a 
              WHERE  column_name IN ( 'NAME', 'FULLNAME' ) 
                      OR ( data_type = 'DATE' 
                           AND column_name IN ( 'DTTM', 'BDAY', 'DATEFLD', 
                                                'DTFIELD' 
                                              ) ) 
              GROUP  BY table_name) LOOP 
        EXECUTE IMMEDIATE 'SELECT COUNT(*) FROM '|| r.table_name|| 
        r.where_clause 
        INTO 
        v_count; 

        IF v_count > 0 THEN 
          dbms_output.Put_line(r.table_name); 
        END IF; 
    END LOOP; 
END; 

/ 

请注意,我给你的是一个给你一些想法的例子,你可以构建它并调整隐式游标循环的查询(在r in ()内)以使用AND/OR/JOIN来满足你的需求条件INTERSECT运算符等但是你想要。我这样做是为了从我的角度测试它。

编辑:另一种选择是强制方法,即使用动态where子句搜索数据库中的所有表,如果找不到where子句中的列,则忽略该异常一张桌子。

SET serveroutput ON 
DECLARE 
    v_count        NUMBER; 
    v_where_clause VARCHAR2(400) := 
    ' WHERE DTTM = DATE ''1984-01-01'' AND FULLNAME = ''JOHN'''; 
BEGIN 
    FOR r IN (SELECT owner, 
                     table_name 
              FROM   all_tables) LOOP 
        BEGIN 
            EXECUTE IMMEDIATE 'SELECT COUNT(*) FROM '|| r.owner|| '.'|| 
            r.table_name 
            || 
            v_where_clause INTO v_count; 

            IF v_count > 0 THEN 
              dbms_output.put_line(r.owner||'.'||r.table_name); 
            END IF; 
        EXCEPTION 
            WHEN OTHERS THEN 
              NULL; --It is ok in this case as you know why it fails. 
        END; 
    END LOOP; 
END; 
/