循环遍历Oracle中的行和列
Posted
技术标签:
【中文标题】循环遍历Oracle中的行和列【英文标题】:Looping through rows and then columns in Oracle 【发布时间】:2014-07-28 17:55:54 【问题描述】:我有一个看起来像这样的表:
__________________________________________________________________________________
|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
...);
我不确定这是否对任何人都有意义。
【问题讨论】:
这毫无意义...你能发布你的 actual 表结构吗?您提供的表格有重复的列名... 一个表不能有多个同名的列。您不能拥有一个包含多个名为code
或 code_due_date
的列的表。
我的错。我已经解决了这个问题并添加了实际的结构。
【参考方案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;
【讨论】:
【参考方案2】:我不确定我是否完全按照您的要求进行操作,但似乎与其循环遍历,不如将UNPIVOT
和JOIN
用于包含您的代码的表格:
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、字段和值。如果您需要基表中的其他信息,可以使用这些结果重新加入。
【讨论】:
【参考方案3】:您可以使用SYS_REFCURSOR
和DBMS_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;
【讨论】:
以上是关于循环遍历Oracle中的行和列的主要内容,如果未能解决你的问题,请参考以下文章
急求!VB编程问题:有一个n×m的矩阵,编写程序,找出其中最大的元素所在的行和列,并输出其值及行号和列