用于列的Oracle Dynamic SQL

时间:2009-11-04 00:32:52

标签: sql oracle plsql oracle10g dynamic-sql

我正在编写一个存储过程,我需要根据报告的数据填充表。

在这种情况下,我会在日期范围内为某个代码每天提取三个值。

假设在这个存储过程的某个运行中,我有一个日期范围的代码值X,Y和Z,如下所示:

select abc.code, 
       abc.date, 
       abc.val_1, 
       abc.val_2, 
       abc.val_3
  from data.abc
 where abc.date BETWEEN '01-OCT-2009' AND '31-OCT-2009'

因此,对于日期范围内的每一天,我有三个代码x,y和z的记录。

在我的决赛桌中,我需要将其从行转换为列。通常我会使用解码函数,但在这里我想根据返回的数据动态创建我的最终表。

在这种情况下,我会在该范围内的每一天有一条记录,并且还有9列(val_1_X,val_2_x,val_3_x,val_1_y等)。

我想动态设置它,以便在引入新的“代码”时不需要重新打开我的存储过程,因此在报表的每个实例上只返回“代码”该报告的实例包含在决赛桌上。

这可以通过动态sql实现吗?我使用的是Oracle 10g版本。

3 个答案:

答案 0 :(得分:1)

根据我的理解,01-OCT-2009至31-OCT-2009只有代码 x y z 到31-NOV-2009也可能会让你 w

最终,您需要这样的查询:

CREATE TABLE t1 AS
  SELECT
    abc.date,
    MAX(DECODE(code, 'x', val_1, NULL)) AS abc_val_1_x,
    MAX(DECODE(code, 'x', val_2, NULL)) AS abc_val_2_x,
    MAX(DECODE(code, 'x', val_3, NULL)) AS abc_val_3_x,
    MAX(DECODE(code, 'y', val_1, NULL)) AS abc_val_1_y,
    MAX(DECODE(code, 'y', val_2, NULL)) AS abc_val_2_y,
    MAX(DECODE(code, 'y', val_3, NULL)) AS abc_val_3_y,
    ...
  FROM data.abc
  WHERE abc.date BETWEEN '01-OCT-2009' AND '31-OCT-2009'
  GROUP BY abc.date

我不是Oracle人员,也无权访问Oracle,所以您可能会发现下面有很多语法错误等。您还需要将硬编码日期更改为变量,声明一些变量并实际运行创建的查询。

-- Figure out all valid codes for date range.
-- Might also require ordering depending on your report.
CURSOR c1
  IS
    SELECT
      abc.code
    FROM data.abc
    WHERE abc.date BETWEEN '01-OCT-2009' AND '31-OCT-2009'
    GROUP BY abc.code;

query1 := 'CREATE TABLE abc_report AS SELECT date';
LOOP
    FETCH c1 INTO code1
    EXIT WHEN c1%NOTFOUND;
    query1 := query1 || ', DECODE(code, ''' || code1 || ''', val_1, NULL)) AS abc_val_1_' || code1 ||
        ', DECODE(code, ''' || code1 || ''', val_2, NULL)) AS abc_val_2_' || code1 ||
        ', DECODE(code, ''' || code1 || ''', val_3, NULL)) AS abc_val_3_' || code1
END LOOP;
query1 := query1 || ' FROM data.abc WHERE date BETWEEN ''01-OCT-2009'' AND ''31-OCT-2009'''

答案 1 :(得分:0)

非常感谢你的帮助,但事实证明,毕竟我不能走这条路。存储的程序将被启动并由报告工具使用,我需要做好准备,以便同时运行此报告的多个实例,因此我不能重复使用表名,我赢了允许有一个存储过程创建一个对每个运行实例唯一的表。

再次感谢您的帮助!

答案 2 :(得分:0)

对于多个实例,使用全局临时表,其中包含基于需求的提交删除行或提交保留的选项。无论选项记录是否仅适用于该会话。