我有下表:
CREATE TABLE bodega ( --winery
id_bod INTEGER NOT NULL,
prod_an_bod nt_tipo_valor , --annual production
)
CREATE TABLE marca ( --wine
id_marca INTEGER NOT NULL,
prod_an_marca nt_tipo_valor , --annual production
)
CREATE TABLE presentacion ( --n:m relation table
id_pres INTEGER NOT NULL,
bodega_fk INTEGER NOT NULL,
marca_fk INTEGER NOT NULL
)
表marca中的prod_an_marca和表bodega中的prod_an_bod都是以下类型的嵌套表:
CREATE OR REPLACE TYPE tipo_valor AS OBJECT (
ano DATE, --year
cantidad INTEGER --ammount of wine produced
)
我已经执行了以下过程,该过程应该检索任何给定酿酒厂在任何给定年份生产的葡萄酒数量,其目的是稍后将该数量插入嵌套表中,以获取该酿酒厂的生产价值,这种工作方式是通过n:m关系表(presentacion)进行的,该表存储了(bodega)的外键和(marca)葡萄酒的外键。
我正在使用一个游标,该游标检索给定年份的生产量,并在选择中使用SUM求和,问题是它求和了满足搜索条件的每个单个生产值,这意味着它确实检索了生产属于某个酒庄的所有葡萄酒的价值,但每年的总和而不是指定年份的价值。
我尝试使用GROUP BY按年份对总和进行分组,该总和将存储在游标中的每年的正确值存储起来,这可能有效,但是我需要一种方法将其插入嵌套表中以供酿酒厂生产数字,我不确定如何做到这一点,我们将不胜感激。
Create or replace procedure prueba(idbod INTEGER, ano DATE)
CURSOR prodbod IS
SELECT
sum(nt.cantidad)
FROM bodega b,
presentacion p,
marca m,
TABLE(m.prod_an_marca) nt
WHERE m.id_marca = p.marca_fk
AND b.id_bod = p.bodega_fk
AND b.id_bod = idbod
AND nt.ano = ano;
tempvar INTEGER;
BEGIN
OPEN prodbod;
LOOP
FETCH prodbod INTO tempvar;
EXIT WHEN prodbod%NOTFOUND;
DBMS_OUTPUT.PUT_LINE('tempvar:'||to_char(tempvar));
END LOOP;
CLOSE prodbod;
END;
答案 0 :(得分:1)
问题实际上比您的描述中出现的要简单得多。您的查询有:
AND nt.ano = ano
As stated in the documentation:
如果SQL语句引用的名称既属于列又属于局部变量或形式参数,则该列名称优先。
所以您实际上是在做:
AND nt.ano = nt.ano
这显然总是正确的。您似乎通过为id_bod
和idbod
使用稍微不同的名称来避免了相同的问题,这可能是偶然的。您可以通过在过程名称前添加前缀来明确声明第二个引用是PL / SQL变量:
AND nt.ano = prueba.ano
或更改您的正式参数名称。通常使用前缀来避免这种混淆,例如:
Create or replace procedure prueba(p_id_bod INTEGER, p_ano DATE) as
...
AND b.id_bod = p_id_bod
AND nt.ano = p_ano;
...
如评论中所述,您实际上应该使用显式联接语法,并且您的示例确实不需要显式游标或循环(甚至不需要任何PL / SQL,尽管我知道您将对其进行扩展) ;您可以通过以下方式获得总数:
Create or replace procedure prueba(p_idbod INTEGER, p_ano DATE) as
tempvar INTEGER;
BEGIN
SELECT sum(nt.cantidad)
INTO tempvar
FROM bodega b
JOIN presentacion p on p.bodega_fk = b.id_bod
JOIN marca m on m.id_marca = p.marca_fk
CROSS JOIN TABLE(m.prod_an_marca) nt
WHERE b.id_bod = p_id_bod
AND nt.ano = p_ano;
DBMS_OUTPUT.PUT_LINE('tempvar:'||to_char(tempvar));
END;
/