Как присвоить несколько значений переменной с помощью предложения into в запросе oracle? - PullRequest
0 голосов
/ 18 июня 2020

У меня есть такая хранимая процедура oracle

CREATE OR REPLACE PROCEDURE DEMO (V_IN CHAR, V_OUT VARCHAR2) 
IS
  BEGIN
    FOR ITEM IN LOOP (SELECT DISTINCT (NAME) 
                        FROM TABLE1 INTO V_OUT 
                       WHERE ID = V_IN
    LOOP 
      --CODE TO PRINT V_OUT
    END LOOP;
  END;

Теперь, как мне создать эту переменную V_OUT, чтобы она могла хранить все значения, поступающие из запроса? Я делаю это в oracle12 C.

Ответы [ 3 ]

0 голосов
/ 18 июня 2020

Вы можете работать с коллекциями, например:

--declare the pakage type
CREATE OR REPLACE PACKAGE PKG_TYPES AS        
  TYPE LIST_VARCHAR        IS TABLE OF VARCHAR2(2000);                        
END;

--create the proc that will assemble the value list
CREATE OR REPLACE PROCEDURE DEMO ( V_IN IN  varchar2, V_OUT IN OUT PKG_TYPES.LIST_VARCHAR) IS
  BEGIN
    FOR ITEM IN ( 
      SELECT DISTINCT (NAME) name 
        FROM (SELECT 'X' ID, 'A' name FROM dual
              UNION 
              SELECT 'X' ID, 'b' name FROM dual
              UNION
              SELECT 'y' ID, 'c' name FROM dual
              ) TABLE1 
        WHERE ID= V_IN 
        )
    LOOP
      V_OUT.EXTEND;
      V_OUT(V_OUT.LAST) := item.name;
      --CODE TO PRINT V_OUT
    END LOOP;
  END;

--use the list. I separated this step but it can be in the demo proc as well
DECLARE 
  names PKG_TYPES.LIST_VARCHAR := PKG_TYPES.LIST_VARCHAR();
BEGIN
  demo('X',names) ;
  FOR i IN names.first..names.last LOOP
    Dbms_Output.put_line(i); 
  END LOOP;
END;

Вам придется обрабатывать исключения, когда из курсора не возвращается значение (когда не найден ID).

0 голосов
/ 18 июня 2020

Если вам нужна переменная коллекции - вы можете использовать вложенную таблицу и массовый сбор, как показано ниже. Чтобы иметь возможность вернуть значение из процедуры, вам нужно будет объявить тип вложенной таблицы в каком-либо пакете или на уровне схемы БД.

declare
    type test_type is table of varchar2(2000);

    test_collection test_type;
begin
    select distinct(name) bulk collect into test_collection
    from (
        select 1 id, 'AAA' name from dual
        union all
        select 1 id, 'BBB' name from dual
        union all
        select 1 id, 'AAA' name from dual
        union all
        select 2 id, 'CCC' name from dual
    )
    where id = 1;

    for i in test_collection.first..test_collection.last loop
        dbms_output.put_line(test_collection(i));
    end loop;
end;
/

Если вам просто нужна строка с конкатенированными значениями - вы можете использовать listagg, чтобы создать его, как показано ниже

declare
    test_str varchar2(4000);
begin
    select listagg(name, ', ') within group(order by 1)
    into test_str
    from (
        select distinct name
        from (
            select 1 id, 'AAA' name from dual
            union all
            select 1 id, 'BBB' name from dual
            union all
            select 1 id, 'AAA' name from dual
            union all
            select 2 id, 'CCC' name from dual
        )
        where id = 1
    );

    dbms_output.put_line(test_str);
end;
/
0 голосов
/ 18 июня 2020

Вы не помещаете предложение INTO в запрос курсора. И даже если вы это сделали, вы поместили его не в том месте в операторе SQL.

Вы имеете дело с этим, когда выбираете строку из запроса:

CREATE OR REPLACE PROCEDURE 
 DEMO (V_IN CHAR, V_OUT 
   VARCHAR2)IS
  BEGIN
    FOR ITEM IN LOOP
        (SELECT DISTINCT (NAME) 
         FROM TABLE1 
         WHERE ID= V_IN
        )
    LOOP 
      dbms_output.put_line(item.name);
      v_out := item.name;
     END LOOP;
   END;

Но тогда проблема в том, что мы просто продолжаем накладывать предыдущее значение, так что когда ваша процедура действительно завершается, единственное значение v_out - это последнее присвоенное значение. Если вам действительно нужен набор значений, вам нужно объявить выходную переменную как указатель ссылки и соответствующим образом скорректировать код. На самом деле я никогда с ними не работал, так что, возможно, кто-нибудь еще вмешается.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...