如何遍历列并检索列值?

时间:2017-07-07 22:00:56

标签: sql oracle cursor

我对Oracle游标有疑问。

我需要比较所选列列中的值,查看更新后哪些记录已更改。表格很大,区分新旧记录的唯一方法是使用Batch_ID。

输出表将包含以下信息:

enter image description here

所以我有一些非常基本的东西,除了我需要编写数百个SELECT语句才能遍历数百列。

SELECT a.*, b.LAST_name AS last_name_updated --- here the variable could be ethnicity, income category etc..
from (SELECT person_id, last_name
      FROM   person  
      WHERE batch_id = (select max(batch_id) from person)
     ) a FULL OUTER JOIN
     (SELECT person_id, last_name
      FROM   person  
      WHERE batch_id = (select max(batch_id) - 1 from person)
     ) b
     ON a.person_id = b.person_id
WHERE  nvl(a.last_name,0) <> nvl(b.last_nm,0)

我需要查看大约500个字段名称的列表,例如Income,Race,Last_Name等,并捕获所有这些列中的所有更改(如果有)。

如何在不写出数百个SELECT语句的情况下解决这个问题?

提前感谢您的帮助!

1 个答案:

答案 0 :(得分:1)

这是一个通用SQL语句,它将使用ALL_TAB_COLS生成可用于比较列的SQL语句:

  SELECT    CASE WHEN column_id = '1' THEN q'[ select 'batchid: ' || batchid ]' END
         || CASE
                WHEN column_name <> 'BATCHID'
                THEN
                       q'[ || case when ]'
                    || column_name
                    || q'[<> lag(]'
                    || column_name
                    || q'[) over (partition by batchid order by col1, col2) then ' ]'
                    || column_name
                    || ' has changed'' end'
            END
         || CASE WHEN column_id = MAX (column_id) OVER () THEN q'[ as changemessage from testtable]' END
             sql
    FROM all_tab_cols a
   WHERE table_name = 'TESTTABLE'
ORDER BY column_id;

测试用例:

CREATE TABLE testtable
(
    batchid   INTEGER
  , col1      INTEGER
  , col2      INTEGER
);

BEGIN
    FOR batchid IN 1 .. 3
    LOOP
        FOR col1 IN 1 .. 3
        LOOP
            FOR col2 IN 1 .. 2
            LOOP
                INSERT INTO testtable
                     VALUES (batchid, col1, col2);
            END LOOP;
        END LOOP;
    END LOOP;
END;

执行SQL并生成以下SQL语句:

select 'batchid: ' || batchid 
     || case when COL1<> lag(COL1) over (partition by batchid order by col1, col2) then ' COL1 has changed' end
     || case when COL2<> lag(COL2) over (partition by batchid order by col1, col2) then ' COL2 has changed' end as changemessage from testtable

我会留给你减少结果集:

CHANGEMESSAGE
batchid: 1
batchid: 1
batchid: 1
batchid: 1
batchid: 1 COL2 has changed
batchid: 1
batchid: 1
batchid: 1
batchid: 1 COL1 has changed COL2 has changed
batchid: 1
batchid: 1
batchid: 1
batchid: 1 COL2 has changed
batchid: 1
batchid: 1
batchid: 1
batchid: 1 COL1 has changed COL2 has changed
batchid: 1
batchid: 1
batchid: 1
batchid: 1 COL2 has changed
batchid: 1
batchid: 1
batchid: 1
batchid: 2
batchid: 2
batchid: 2
batchid: 2
batchid: 2 COL2 has changed
batchid: 2
batchid: 2
batchid: 2
batchid: 2 COL1 has changed COL2 has changed
batchid: 2
batchid: 2
batchid: 2
batchid: 2 COL2 has changed
batchid: 2
batchid: 2
batchid: 2
batchid: 2 COL1 has changed COL2 has changed
batchid: 2
batchid: 2
batchid: 2
batchid: 2 COL2 has changed
batchid: 2
batchid: 2
batchid: 2
batchid: 3
batchid: 3
batchid: 3
batchid: 3
batchid: 3 COL2 has changed
batchid: 3
batchid: 3
batchid: 3
batchid: 3 COL1 has changed COL2 has changed
batchid: 3
batchid: 3
batchid: 3
batchid: 3 COL2 has changed
batchid: 3
batchid: 3
batchid: 3
batchid: 3 COL1 has changed COL2 has changed
batchid: 3
batchid: 3
batchid: 3
batchid: 3 COL2 has changed
batchid: 3
batchid: 3
batchid: 3