循环遍历Oracle中的行和列

时间:2014-07-28 17:55:54

标签: sql oracle plsql

我有一张看起来像这样的表:

__________________________________________________________________________________
|id   |code  |code_status |code_due_date|code2  |code_status2 |code_due_date2|...|
|1    |ABCD  |A           |MMDDYYYY     |Null   |Null         |Null          |...|
|2    |Null  |Null        |Null         |Null   |Null         |Null          |...|
|3    |EFGH  |A           |MMDDYYYY     |ABCD   |B            |MMDDYYYY      |...|
|...  |...   |...         |...          |...    |...          |...           |...|
----------------------------------------------------------------------------------

实际表格结构是:

CREATE TABLE MY_DATA (
    PRSN_UNIV_ID                            VARCHAR2(11),
    CHKL_ITM_CD_1                           VARCHAR2(6),
    CHKL_ITM_CD_2                           VARCHAR2(6),
    CHKL_ITM_CD_3                           VARCHAR2(6),
    CHKL_ITM_CD_4                           VARCHAR2(6),
    CHKL_ITM_CD_5                           VARCHAR2(6),
    CHKL_ITM_CD_6                           VARCHAR2(6),
    CHKL_ITM_CD_7                           VARCHAR2(6),
    CHKL_ITM_CD_8                           VARCHAR2(6),
    CHKL_ITM_CD_9                           VARCHAR2(6),
    CHKL_ITM_CD_10                          VARCHAR2(6),
    CHKL_ITM_CD_11                          VARCHAR2(6),
    CHKL_ITM_CD_12                          VARCHAR2(6),
    CHKL_ITM_CD_13                          VARCHAR2(6),
    CHKL_ITM_CD_14                          VARCHAR2(6),
    CHKL_ITM_CD_15                          VARCHAR2(6),
    CHKL_ITM_CD_16                          VARCHAR2(6),
    CHKL_ITM_CD_17                          VARCHAR2(6),
    CHKL_ITM_CD_18                          VARCHAR2(6),
    CHKL_ITM_CD_19                          VARCHAR2(6),
    CHKL_ITM_CD_20                          VARCHAR2(6),
    CHKL_ITM_CD_21                          VARCHAR2(6),
    CHKL_ITM_CD_22                          VARCHAR2(6),
    CHKL_ITM_CD_23                          VARCHAR2(6),
    CHKL_ITM_CD_24                          VARCHAR2(6),
    CHKL_ITM_CD_25                          VARCHAR2(6),
    CHKL_ITM_CD_26                          VARCHAR2(6),
    CHKL_ITM_CD_27                          VARCHAR2(6),
    CHKL_ITM_CD_28                          VARCHAR2(6),
    CHKL_ITM_CD_29                          VARCHAR2(6),
    CHKL_ITM_CD_30                          VARCHAR2(6),
    CHKL_ITM_STAT_CD_1                      VARCHAR2(1),
    CHKL_ITM_STAT_CD_2                      VARCHAR2(1),
    CHKL_ITM_STAT_CD_3                      VARCHAR2(1),
    CHKL_ITM_STAT_CD_4                      VARCHAR2(1),
    CHKL_ITM_STAT_CD_5                      VARCHAR2(1),
    CHKL_ITM_STAT_CD_6                      VARCHAR2(1),
    CHKL_ITM_STAT_CD_7                      VARCHAR2(1),
    CHKL_ITM_STAT_CD_8                      VARCHAR2(1),
    CHKL_ITM_STAT_CD_9                      VARCHAR2(1),
    CHKL_ITM_STAT_CD_10                     VARCHAR2(1),
    CHKL_ITM_STAT_CD_11                     VARCHAR2(1),
    CHKL_ITM_STAT_CD_12                     VARCHAR2(1),
    CHKL_ITM_STAT_CD_13                     VARCHAR2(1),
    CHKL_ITM_STAT_CD_14                     VARCHAR2(1),
    CHKL_ITM_STAT_CD_15                     VARCHAR2(1),
    CHKL_ITM_STAT_CD_16                     VARCHAR2(1),
    CHKL_ITM_STAT_CD_17                     VARCHAR2(1),
    CHKL_ITM_STAT_CD_18                     VARCHAR2(1),
    CHKL_ITM_STAT_CD_19                     VARCHAR2(1),
    CHKL_ITM_STAT_CD_20                     VARCHAR2(1),
    CHKL_ITM_STAT_CD_21                     VARCHAR2(1),
    CHKL_ITM_STAT_CD_22                     VARCHAR2(1),
    CHKL_ITM_STAT_CD_23                     VARCHAR2(1),
    CHKL_ITM_STAT_CD_24                     VARCHAR2(1),
    CHKL_ITM_STAT_CD_25                     VARCHAR2(1),
    CHKL_ITM_STAT_CD_26                     VARCHAR2(1),
    CHKL_ITM_STAT_CD_27                     VARCHAR2(1),
    CHKL_ITM_STAT_CD_28                     VARCHAR2(1),
    CHKL_ITM_STAT_CD_29                     VARCHAR2(1),
    CHKL_ITM_STAT_CD_30                     VARCHAR2(1),
    CHKL_ITM_DUE_DT_1                       DATE,
    CHKL_ITM_DUE_DT_2                       DATE,
    CHKL_ITM_DUE_DT_3                       DATE,
    CHKL_ITM_DUE_DT_4                       DATE,
    CHKL_ITM_DUE_DT_5                       DATE,
    CHKL_ITM_DUE_DT_6                       DATE,
    CHKL_ITM_DUE_DT_7                       DATE,
    CHKL_ITM_DUE_DT_8                       DATE,
    CHKL_ITM_DUE_DT_9                       DATE,
    CHKL_ITM_DUE_DT_10                      DATE,   
    CHKL_ITM_DUE_DT_11                      DATE,
    CHKL_ITM_DUE_DT_12                      DATE,
    CHKL_ITM_DUE_DT_13                      DATE,
    CHKL_ITM_DUE_DT_14                      DATE,
    CHKL_ITM_DUE_DT_15                      DATE,   
    CHKL_ITM_DUE_DT_16                      DATE,
    CHKL_ITM_DUE_DT_17                      DATE,
    CHKL_ITM_DUE_DT_18                      DATE,
    CHKL_ITM_DUE_DT_19                      DATE,
    CHKL_ITM_DUE_DT_20                      DATE,   
    CHKL_ITM_DUE_DT_21                      DATE,
    CHKL_ITM_DUE_DT_22                      DATE,
    CHKL_ITM_DUE_DT_23                      DATE,
    CHKL_ITM_DUE_DT_24                      DATE,
    CHKL_ITM_DUE_DT_25                      DATE,   
    CHKL_ITM_DUE_DT_26                      DATE,
    CHKL_ITM_DUE_DT_27                      DATE,
    CHKL_ITM_DUE_DT_28                      DATE,
    CHKL_ITM_DUE_DT_29                      DATE,
    CHKL_ITM_DUE_DT_30                      DATE   
    )

我需要做类似下面的伪代码,但我不知道如何写它或者甚至可能。我需要首先遍历每一行并测试该行中的列是否等于代码。如果是,我想取相同数字的状态和截止日期,并将其放入正确的变量中。我需要循环测试大约30种不同的代码。

Declare variables
    variable_code_status
    variable_code_due_date
    variable_code_status2
    variable_code_due_date2
    variable_code_status3
    variable_code_due_date3

    ...

for each row
    for each column
        if column = code
            set variable_code_status = code_status
            set variable_code_due_date = code_due_date
        end if
        if column = code2
            set variable_code_status = code_status2
            set variable_code_due_date = code_due_date2
        end if
        if column - code3
            set variable_code_status = code_status3
            set variable_code_due_date = code_due_date3
        end if

        ...
    end for
end for

insert into table(
    variable_code_status
    variable_code_due_date
    variable_code_status2
    variable_code_due_date2
    variable_code_status3
    variable_code_due_date3

    ...);

我不确定这对任何人是否有意义。

3 个答案:

答案 0 :(得分:1)

你可以这样做:

declare
   id MY_DATA.PRSN_UNIV_ID%type;
   cd varchar2(6);
   stat varchar2(1);
   due date;
   cur sys_refcursor;
begin
   for i in 1..30 loop
      open cur for 
      'select PRSN_UNIV_ID, CHKL_ITM_CD_'||i||', CHKL_ITM_STAT_CD_'||i||', CHKL_ITM_DUE_DT_'||i||' from MY_DATA';
      loop
         fetch cur into id, cd, stat, due;
         exit when cur%notfound;
         if .... then --> put here all your conditions
            insert into ....
         end if;
      end loop; 
   end loop;
end;

答案 1 :(得分:1)

我不确定我是否完全遵循了您之后所做的事情,但似乎您可能最好不要使用UNPIVOT和{{JOIN。 1}}到你的代码表:

WITH cte AS (
            SELECT *
            FROM  Table1 
            UNPIVOT (value FOR field IN ("code", "code_status", "code_due_date", "code2", "code_status2","code_due_date2"))
           )
SELECT a.*
FROM cte a
INNER JOIN codes b
 ON a.value = b."code_value"

演示:SQL Fiddle

这可以获取符合条件的ID,字段和值。如果您需要基表中的其他信息,可以使用这些结果加入。

答案 2 :(得分:1)

您可以使用SYS_REFCURSORDBMS_SQL包动态地满足此要求。以下过程是如何与查询动态交互的一般示例,在这种情况下,它只是将结果打印到控制台。您可以修改它以在每次迭代时测试列描述并执行一些不同的操作。 (这适用于11.2.0.3.0)

  PROCEDURE Output_Any_Query (
    pcRefCursor                 IN OUT SYS_REFCURSOR
  ) IS

    vnCursorNum         NUMBER;
    vnColCount          NUMBER;
    vtabDescriptions    DBMS_SQL.DESC_TAB;
    vsColumnValue       VARCHAR2(4000);

  BEGIN

    vnCursorNum := DBMS_SQL.to_cursor_number(pcRefCursor);      

    DBMS_SQL.DESCRIBE_COLUMNS(vnCursorNum, vnColCount, vtabDescriptions);

    --Print the column headers
    FOR i IN 1..vnColCount LOOP
      dbms_sql.define_column(vnCursorNum, i, vsColumnValue, 4000);
      dbms_output.put(RPAD(LPAD(vtabDescriptions(i).col_name,15),20)||'|');
    END LOOP;

    --End of line
    dbms_output.put_line('');

    --loop through the rows
    WHILE ( dbms_sql.fetch_rows(vnCursorNum) > 0 ) LOOP 

      --loop across the columns
      FOR i IN 1 .. vnColCount LOOP 
        dbms_sql.column_value(vnCursorNum, i, vsColumnValue);
        dbms_output.put(RPAD(NVL(vsColumnValue,' '),20)||'|');
      END LOOP;

      --End of line   
      dbms_output.put_line('');

    END LOOP;

  END;