如何从数据透视表 SQL 获取游标值到固定变量 - 错误 ORA-01007
How to fetch cursor values from pivot SQL to fixed variables - Error ORA-01007
我有一个带有 PIVOT 操作的 SQL 语句。我将在 PIVOT 中拥有的最大列数是 5,但我可以拥有更少的 4、3、2。
我怎样才能在我的游标中读取这些列并分配(fetch .. into ...)到固定变量,而不发生错误 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;
...
如果我 return 少于 5 列,我想用值 0 或 null 填充剩余的变量。
识别变量 vCodColigada 和 vIdProduto,只有 PIVOT 列可以在 1 和 5 之间变化(vValor1、vValor2、vValor3、vValor4、vValor5)
结果枢轴 SQL:
CODCOLIGADA IDPRD '000125' '002272' '002342'
----------------- ---------------- ---------------- ---------------- ----------------
1 15464 45 300 30
1 18460 35 200 20
1 57492 20 100 10
-------- End of Data --------
示例:
如果游标return在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 个变量,所以在 (fetch .. into ...) 中出现了 ORA-01007 错误。
尝试填充查询中的结果。将连接添加到 select from dual 语句,返回所有五个列。
希望下面的代码片段对您有所帮助。基本的理解是我们需要将多余的变量添加为 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);
-------------------------------------------------------------------------------------------------------
我有一个带有 PIVOT 操作的 SQL 语句。我将在 PIVOT 中拥有的最大列数是 5,但我可以拥有更少的 4、3、2。 我怎样才能在我的游标中读取这些列并分配(fetch .. into ...)到固定变量,而不发生错误 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;
...
如果我 return 少于 5 列,我想用值 0 或 null 填充剩余的变量。
识别变量 vCodColigada 和 vIdProduto,只有 PIVOT 列可以在 1 和 5 之间变化(vValor1、vValor2、vValor3、vValor4、vValor5)
结果枢轴 SQL:
CODCOLIGADA IDPRD '000125' '002272' '002342'
----------------- ---------------- ---------------- ---------------- ----------------
1 15464 45 300 30
1 18460 35 200 20
1 57492 20 100 10
-------- End of Data --------
示例: 如果游标return在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 个变量,所以在 (fetch .. into ...) 中出现了 ORA-01007 错误。
尝试填充查询中的结果。将连接添加到 select from dual 语句,返回所有五个列。
希望下面的代码片段对您有所帮助。基本的理解是我们需要将多余的变量添加为 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);
-------------------------------------------------------------------------------------------------------