Выбор данных и сохранение их в переменной с помощью EXECUTE IMMEDIATE - PullRequest
0 голосов
/ 26 июня 2018

Я пытаюсь выбрать несколько строк и поместить данные в переменную. Процедура

CREATE OR REPLACE PROCEDURE GET_MESSAGE
AS
V_RESULT                VARCHAR2(2000);

begin


    EXECUTE IMMEDIATE 'SELECT MESSAGE_ID FROM MSG_TABLE WHERE ( DATE_OF_OPERATION BETWEEN 20180530 AND 20180622) AND (ROWNUM BETWEEN 1 and 2)' INTO V_RESULT;
        dbms_output.put_line('V_RESULT:'||V_RESULT);


end;
/

При выполнении процедуры я получаю следующую ошибку

Error starting at line : 37 in command -
BEGIN GET_MESSAGE; END;
Error report -
ORA-01422: exact fetch returns more than requested number of rows
ORA-06512: at "PG_DBO11.GET_MESSAGE", line 8
ORA-06512: at line 1
01422. 00000 -  "exact fetch returns more than requested number of rows"
*Cause:    The number specified in exact fetch is less than the rows returned.
*Action:   Rewrite the query or change number of rows requested

MSG_TABLE содержит следующие столбцы и данные

MESSAGE_ID    DATE_OF_OPERATION     MESSAGE
1000          20180530              AABC
1001          20180622              XXYZ

Сам запрос работает нормально. Я не знаю, как сохранить выбранные строки в переменную. Я могу упустить очень общую вещь здесь.

Ответы [ 2 ]

0 голосов
/ 27 июня 2018

Следующее решение послужило моей цели. Я использовал V_RESULT как XmlType ...

CREATE OR REPLACE PROCEDURE GET_MESSAGE
IS
V_RESULT                XMLTYPE;
V_QUERY                 VARCHAR(2000);
begin
V_QUERY:='SELECT
XMLELEMENT("root",XMLAGG(
                XMLELEMENT("data",
                        XMLELEMENT("MESSAGE_ID",MESSAGE_ID),
                        XMLELEMENT("MESSAGE",MESSAGE )

                        ))
                ) FROM MSG_TABLE WHERE (
DATE_OF_OPERATION BETWEEN 20180530 AND 20180622)  AND (ROWNUM BETWEEN 1 and 10)';
    EXECUTE IMMEDIATE  V_QUERY INTO V_RESULT;
    dbms_output.put_line('the result xml is '||v_result.getStringVal());
end;
/

Таким образом, я могу выбрать несколько строк, преобразовать их в xml и сохранить в одной переменной.

0 голосов
/ 26 июня 2018

Для этого вам не нужен динамический SQL.Процедура может принимать 2 параметра даты и может использоваться непосредственно в запросе.Если вы хотите отобразить несколько строк в DBMS_OUTPUT, одним простым способом является использование неявного цикла for.

CREATE OR REPLACE PROCEDURE GET_MESSAGE( p_start_date date, p_end_date date)
AS

BEGIN

FOR rec IN 
(
    SELECT MESSAGE_ID FROM MSG_TABLE  
     WHERE  DATE_OF_OPERATION BETWEEN p_start_date AND p_end_date

 ) LOOP
        dbms_output.put_line('V_RESULT:'||rec.MESSAGE_ID);
   END LOOP;
END;
/

вызовите процедуру как

BEGIN 
 GET_MESSAGE(DATE '2018-05-30', DATE '2018-06-22'); 
END;
/

Демо

Что именно вы пытались сделать при использовании ROWNUM BETWEEN 1 and 2?Обратите внимание, что простое использование ROWNUM без ORDER BY внутри подзапроса не гарантирует, что вы увидите верхние 2 message_ids.Если ваше требование связано с чем-то другим, укажите его в вопросе, отредактировав его, и мы можем помочь вам изменить запрос на выборку.

РЕДАКТИРОВАТЬ : Похоже, что вы можете использоватьВывод XML, вы должны предпочесть dbms_xmlgen.getxml, который дает результат CLOB, который можно выбрать из запроса выбора.Вот пример.

CREATE OR REPLACE FUNCTION pr_outxml RETURN CLOB
    AS
BEGIN
    RETURN dbms_xmlgen.getxml('select * from employees where rownum<= 2');
END;
/

Теперь получите вывод как select pr_outxml from dual;.Вы можете изменить этот код с помощью дополнительных параметров.

...