Как сделать процедуру, которая суммирует значения, хранящиеся во вложенных таблицах? - PullRequest
0 голосов
/ 18 декабря 2018

У меня есть следующие таблицы:

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
)

И prod_an_marca в таблице marca, и prod_an_bod в таблице bodega являются вложенными таблицами следующего типа:

CREATE OR REPLACE TYPE tipo_valor AS OBJECT (
ano        DATE, --year
cantidad   INTEGER --ammount of wine produced
)

У меня естьвыполнила следующую процедуру, которая должна получить количество вина, произведенного какой-либо данной винодельней в любой данный год, цель этого состоит в том, чтобы позже вставить эту сумму во вложенную таблицу для значений производства в винодельне, способ, которым это работает черезтаблица отношений n: m (Presentacion), в которой хранится внешний ключ для (bodega) и внешний ключ для (marca) wine.

Я использую курсор, который извлекает производственные суммы за данный годи суммирует их, используя 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;

1 Ответ

0 голосов
/ 18 декабря 2018

Проблема на самом деле намного проще, чем может показаться из вашего описания.Ваш запрос имеет:

AND nt.ano = ano

Как указано в документации :

Если оператор 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;
/
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...