如何将光标值从pivot SQL获取到固定变量 - 错误ORA-01007

时间:2017-07-25 23:29:27

标签: oracle plsql oracle11g oracle-sqldeveloper

我有一个带有PIVOT操作的SQL语句。我在PIVOT中的最大列数是5,但我可以少,4,3,2。 如何在光标中读取这些列并将(获取...转换为......)分配给固定变量,而不会出现错误ORA-01007。

...
sql_stmt := 'select * from 
                (select codcoligada, 
                        idprd, 
                        codcfo, 
                        valnegociado 
                 from tcitmorcamento 
                 where codcoligada = ' || p_codcoligada || ' 
                   and codcotacao = ' || '''' || p_codcotacao || '''' || ') 
                 pivot 
                 (
                   sum(valnegociado) for codcfo in (' || pivot_clause || ')
                 )';

  ret  := t_tab_sesa_cotacao();

  open vCursor for sql_stmt; 

  loop
    /* If my cursor returns less than 5 columns in PIVOT the error occurs ORA-01007 */ 
    fetch vCursor into vCodColigada, vIdProduto, vValor01, vValor02, vValor03, vValor04, vValor05;
    exit when vCursor%NOTFOUND;
      ret.extend;
      ret(ret.count) := t_type_sesa_cotacao(vCodColigada, vIdProduto, vValor01, vValor02, vValor03, vValor04, vValor05);
  end loop;

  close vCursor;
...

如果我返回少于5个列,我想用值0或null填充其余变量。

识别变量vCodColigada和vIdProduto,只有PIVOT列可以在1到5之间变化(vValor1,vValor2,vValor3,vValor4,vValor5)

结果PIVOT SQL:

CODCOLIGADA       IDPRD            '000125'         '002272'         '002342'         
----------------- ---------------- ---------------- ---------------- ---------------- 
                1            15464               45              300               30 
                1            18460               35              200               20 
                1            57492               20              100               10 
-------- End of Data --------

实施例: 如果光标在PIVOT(上图)中返回3个值,则将填充变量vValor01,vValor02,vValor03,变量vValor04,vValor05必须为0或null。

示例:

CODCOLIGADA       IDPRD            VALOR01          VALOR02          VALOR03          VALOR04          VALOR05          
----------------- ---------------- ---------------- ---------------- ---------------- ---------------- ---------------- 
                1            15464               45              300               30                0                0 
                1            18460               35              200               20                0                0 
                1            57492               20              100               10                0                0 
-------- End of Data --------

因为我在PIVOT中只有3列,而且我有5个变量,所以ORA-01007错误发生在(fetch .. into ...)中。

2 个答案:

答案 0 :(得分:1)

希望下面的代码段有用。基本的理解是我们需要将多余的变量添加为null或空白以使其工作。

SET serveroutput ON;
DECLARE
  lv_pivot VARCHAR2(100):='''Y'',''N''';
TYPE lv
IS
  RECORD
  (
    flg_y VARCHAR2(100),
    flg_n VARCHAR2(100),
    flg_e VARCHAR2(100));
type lv_tab
IS
  TABLE OF lv;
  lv_num lv_tab;
  lv_check VARCHAR2(1000);
BEGIN
  lv_check   :=regexp_count(lv_pivot,',',1);
  IF lv_check < 3 THEN
    FOR z IN 1..(2-lv_check)
    LOOP
      lv_pivot:=lv_pivot||',null as val'||z;
    END LOOP;
  ELSE
    lv_pivot:=lv_pivot;
  END IF;
  dbms_output.put_line(lv_pivot);
  EXECUTE IMMEDIATE ' SELECT * FROM                         
(SELECT col1 FROM <table>  )                       
pivot ( COUNT(1) FOR col1 IN ('||lv_pivot||'))' BULK COLLECT INTO lv_num;
END;


---------------------------Refactoring in Function------------------------------

--Create Object Type
CREATE OR REPLACE TYPE lv_obj IS OBJECT
(
        flg_y VARCHAR2(100),
        flg_n VARCHAR2(100),
        flg_e VARCHAR2(100)
);

--Create Table Type
CREATE OR REPLACE TYPE lv_tab IS TABLE OF lv_obj;

--Create Function
CREATE OR REPLACE
  FUNCTION test_func
    RETURN lv_tab
  AS
    lv_pivot VARCHAR2(100):='''Y'',''N''';
    lv_num lv_tab;
    lv_check VARCHAR2(1000);
  BEGIN
    lv_check   :=regexp_count(lv_pivot,',',1);
    IF lv_check < 3 THEN
      FOR z IN 1..(2-lv_check)
      LOOP
        lv_pivot:=lv_pivot||',null as val'||z;
      END LOOP;
    ELSE
      lv_pivot:=lv_pivot;
    END IF;
    dbms_output.put_line(lv_pivot);
    EXECUTE IMMEDIATE ' SELECT * FROM                         
(SELECT col1 FROM <table>  )                       
pivot ( COUNT(1) FOR col1 IN ('||lv_pivot||'))' BULK COLLECT INTO lv_num;
    RETURN lv_tab;
  END;

-------------------------------------------------Output-----------------------------------------------

SELECT * FROM TABLE(test_func);
-------------------------------------------------------------------------------------------------------

答案 1 :(得分:-1)

尝试在查询中填充结果。将连接添加到从双重语句中选择,该语句将传回所有五列。