如何使用一种功能测试我的包?
Posted
技术标签:
【中文标题】如何使用一种功能测试我的包?【英文标题】:How can I test my package with one function? 【发布时间】:2020-09-19 02:01:34 【问题描述】:我制作了一个编译良好的包,但是当我尝试对其进行测试时,它给了我“无效的数据类型”。 我尝试了两种不同的方法,第一种是这样的
select pkg_contabilidad.f_totalizar_Detalle(100) FROM DUAL;
它给了我 ORA-00902 '无效数据类型' 我也试过这个
DECLARE
TYPE r_registro IS RECORD
(rubro_contable CN_RUBROS_CONTABLES.COD_RUBRO%TYPE,
tipo VARCHAR2(1),
monto NUMBER(16));
resultao r_registro;
numero NUMBER :=100;
BEGIN
resultao := pkg_contabilidad.f_totalizar_detalle(numero);
END;
它给了我另一个错误 PLS-00382 '表达式类型错误' 我不知道我做错了什么,因为我的函数只接收一个参数并且是 NUMBER 类型,所以我不知道我的错误在哪里。我会留下我的包裹代码以防万一
CREATE OR REPLACE PACKAGE pkg_contabilidad AS
TYPE r_registro IS RECORD
(rubro_contable CN_RUBROS_CONTABLES.COD_RUBRO%TYPE,
tipo VARCHAR2(1),
monto NUMBER(16));
TYPE t_detalle IS TABLE OF
r_registro INDEX BY BINARY_INTEGER;
FUNCTION f_totalizar_detalle(p_clave NUMBER)RETURN t_detalle;
END pkg_contabilidad;
/
CREATE OR REPLACE PACKAGE BODY pkg_contabilidad AS
B_detalle t_detalle;
i integer :=1;
FUNCTION f_totalizar_detalle(p_clave NUMBER) RETURN t_detalle IS
v_detalle t_detalle;
CURSOR c_facturado IS
SELECT c.cod_rubro, 'H', CASE WHEN SUM(d.gravada)=0 THEN SUM(d.iva) ELSE SUM(d.gravada) END
FROM fn_documentos_det d JOIN fn_conceptos c ON d.cod_concepto = c.cod_concepto
WHERE d.clave_doc=p_clave
GROUP BY c.cod_rubro;
CURSOR c_datos IS
SELECT SUM(d.total_doc), 'D',r.cod_rubro
FROM fn_documentos d JOIN fn_cajas_ctas r ON d.num_caja_cta = r.num_caja_cta
WHERE d.clave_doc = p_clave
GROUP BY r.cod_rubro;
BEGIN
open c_datos;
LOOP
FETCH c_datos INTO v_detalle(1);
END LOOP;
CLOSE c_datos;
FOR fila IN c_facturado LOOP
i := i + 1;
v_detalle(i) := fila;
END LOOP;
END;
END PKG_CONTABILIDAD;
【问题讨论】:
【参考方案1】:函数返回一个pkg_contabilidad.t_detalle
,所以测试需要:
declare
resultao pkg_contabilidad.t_detalle;
numero number := 100;
begin
resultao := pkg_contabilidad.f_totalizar_detalle(numero);
end;
它在 SQL 中不起作用,因为pkg_contabilidad.t_detalle
是 PL/SQL 类型,而不是 SQL 类型 (create or replace type
)。数据库可以进行一些自动转换,但是还是有限制的。
顺便说一句,这个循环永远不会完成,因为它缺少exit
条件:
open c_datos;
loop
fetch c_datos into v_detalle(1);
end loop;
close c_datos;
【讨论】:
【参考方案2】:您的函数返回一个 PL/SQL 表类型,其中包含一个 PL/SQL 记录类型的表,该表在您的包中定义,普通 SQL 不知道也无法显示 - 因此您的数据类型无效错误.如果您需要调用该函数并从 SQL 访问数据,您可以创建模式级对象和集合类型。
在您的匿名块中,您是在声明一个新 记录类型。这对您来说看起来是一样的,因为结构是相同的,但是 Oracle 期望函数返回的确切类型。这使您的测试代码更短更简单。但是您也试图将整个集合返回到单个记录中。
DECLARE
l_detalle pkg_contabilidad.t_detalle;
l_registro pkg_contabilidad.r_registro;
l_idx pls_integer;
numero NUMBER :=100;
BEGIN
l_detalle := pkg_contabilidad.f_totalizar_detalle(numero);
l_idx := l_detalle.FIRST;
WHILE l_idx is not null LOOP
l_registro := l_detalle(l_idx);
-- do something with this record
dbms_output.put_line(l_registro.tipo);
l_idx := l_detalle.NEXT(l_idx);
END LOOP;
END;
db<>fiddle 带有虚拟光标。
你的函数有点奇怪,可能没有做你想要的;但也有两个致命的问题:它没有返回任何东西,并且它有一个无限循环。我已经为小提琴修复了这些,但没有其他任何东西,因为这似乎是一种练习。
【讨论】:
以上是关于如何使用一种功能测试我的包?的主要内容,如果未能解决你的问题,请参考以下文章
如何将 testthat 测试应用于我的包中与特定命名模式匹配的所有函数?