PL / SQL UTL_HTTP отправляет несколько необработанных файлов - PullRequest
1 голос
/ 29 мая 2020

Я пытаюсь отправить с помощью метода POST веб-службы десятки записей на другую сторону, но проблема в том, что другая сторона получает только один набор данных. Ставлю курсор, открываю в разделе начало курсор и делаю l oop. Думаю проблема где-то в UTL_HTTP.read_raw. Мне нужно добавить что-то дополнительное или изменить функцию. Где загвоздка, где я ошибаюсь?

создать или заменить ФУНКЦИЮ "TST" return clob is

l_http_request   UTL_HTTP.req;
l_http_response  UTL_HTTP.resp;
l_buffer_size    NUMBER(10) := 20000;
l_line_size      NUMBER(10) := 50;
l_lines_count    NUMBER(10) := 20;
l_string_request VARCHAR2(32767);
l_line           VARCHAR2(128);
l_substring_msg  VARCHAR2(20000);
l_raw_data       RAW(20000);
l_clob_response  CLOB ;
v_clob clob;
url varchar2(200) := 'http://tst';

cursor c_get_prihod is 
select     IDORIG   ,    IDSUSTAVA  ,    DATUM  ,    SIFAGENCIJE    ,    SIFDRZAVE  ,
SIFOSUSL    ,    IZNOSNETO  ,    IZNOSBRUTO ,    IZNOSPOREZA    ,    SIFHOTELA
from HRS_LASERLINE_PRIHOD
where datum = pms_p.business_date
and sifhotela = pms_p.resort
;

begin

for a in c_get_prihod loop

l_string_request:= 
'{
IdOrig:"'||a.IDORIG||'",
IdSustava:"'||a.IDSUSTAVA||'",
Datum:"'||a.DATUM||'",
SifAgencije:"'||a.SIFAGENCIJE||'",
SifDrzave:"'||a.SIFDRZAVE||'",
SifOsUsl:"'||a.SIFOSUSL||'",
IznosNeto:"'||a.IZNOSNETO||'",
IznosBruto:"'||a.IZNOSBRUTO||'",
IznosPoreza:"'||a.IZNOSPOREZA||'",
SifHotela:"'||a.SIFHOTELA||'",
}}'
;

end loop;

l_http_request := UTL_HTTP.begin_request(url , method => 'POST', http_version => 'HTTP/1.1');
utl_http.set_header(l_http_request, 'user-agent', 'mozilla/4.0'); 
utl_http.set_header(l_http_request, 'content-type', 'application/json'); 
utl_http.set_header(l_http_request, 'Content-Length', length(l_string_request));

BEGIN

<<request_loop>>

FOR i IN 0..CEIL(LENGTH(l_string_request) / l_buffer_size) - 1 LOOP
    l_substring_msg := SUBSTR(l_string_request, i * l_buffer_size + 1, l_buffer_size);

BEGIN
    l_raw_data := utl_raw.cast_to_raw(l_substring_msg);
    UTL_HTTP.write_raw(r => l_http_request, data => l_raw_data);

EXCEPTION

WHEN NO_DATA_FOUND THEN
EXIT request_loop;

END;
END LOOP request_loop;

l_http_response := UTL_HTTP.get_response(l_http_request);

BEGIN

LOOP
    UTL_HTTP.read_raw(l_http_response, l_raw_data, l_buffer_size);
    l_clob_response := l_clob_response || UTL_RAW.cast_to_varchar2(l_raw_data);
END LOOP response_loop; 

EXCEPTION

WHEN UTL_HTTP.end_of_body THEN
    UTL_HTTP.end_response(l_http_response);
END; 

<<print_response>>

FOR i IN 0..CEIL(LENGTH(l_clob_response) / l_line_size) - 1 
LOOP
    l_line := SUBSTR(l_clob_response, i * l_line_size + 1, l_line_size);
EXIT WHEN i > l_lines_count - 1;
END LOOP print_response;

v_clob:= l_clob_response;        

return v_clob ;

exception
  when utl_http.end_of_body then
  utl_http.end_response(l_http_response);
end;
end TST;

1 Ответ

0 голосов
/ 29 мая 2020

Ваш запрос курсора может найти десятки строк, но вы делаете это:

for a in c_get_prihod loop

l_string_request:= ... ;

end loop;

Каждый раз вокруг этого l oop вы заменяете все содержимое l_string_request, поэтому сколько бы строк вы ни получили и сколько раз вы go вокруг l oop, вы всегда получите строку, содержащую только последнюю строку, возвращаемую этим запросом. Таким образом, вы отправляете только эту единственную последнюю запись в веб-службу.

Предполагая, что принимающая служба ожидает массив записей, вам может понадобиться что-то вроде:

begin

  l_string_request := '[ ';

  for a in c_get_prihod loop
    if a.FLAG > 1 then
      l_string_request := l_string_request || ', ';
    end if;
    l_string_request := l_string_request || '{ ';
    l_string_request := l_string_request || '"IdOrig": "' || a.IDORIG || '", ';
    l_string_request := l_string_request || '"IdSustava": "' || a.IDSUSTAVA ||' ", ';
    l_string_request := l_string_request || '"Datum": "' || a.DATUM || '", ';
    l_string_request := l_string_request || '"SifAgencije": "' || a.SIFAGENCIJE || '", ';
    l_string_request := l_string_request || '"SifDrzave": "' || a.SIFDRZAVE || '", ';
    l_string_request := l_string_request || '"SifOsUsl": "' || a.SIFOSUSL || '", ';
    l_string_request := l_string_request || '"IznosNeto": "' || a.IZNOSNETO || '", ';
    l_string_request := l_string_request || '"IznosBruto": "' || a.IZNOSBRUTO || '", ';
    l_string_request := l_string_request || '"IznosPoreza": "' || a.IZNOSPOREZA || '", ';
    l_string_request := l_string_request || '"SifHotela": "' || a.SIFHOTELA || '"';
    l_string_request := l_string_request || ' }';
  end loop;
  
  l_string_request := l_string_request || ' ]';

  dbms_output.put_line(l_string_request);

  ...

где flag - это дополнительный столбец, добавляемый к результату курсора, например, , ROWNUM AS FLAG - так же, как механизм, чтобы узнать, находитесь ли вы в первой строке или в следующей строке (и поэтому требуется запятая между элементами массива).

dbms_output позволяет вам видеть все сгенерированное значение, которое вы можете вручную проверить и / или пропустить через валидатор JSON, чтобы убедиться, что это именно то, что вы (и, что более важно, получающая служба) ожидаете увидеть. Вы по-прежнему можете добавлять новые строки во время построения JSON для удобочитаемости, хотя сервис не заботится об этом.

В зависимости от того, сколько строк у вас может быть, вам может понадобиться l_string_request, чтобы быть CLOB вместо а varchar2. Я также предлагаю вам явно форматировать значения даты / времени и правильно обрабатывать числа, если они у вас есть.

После модификации по вашему совету я получаю эту ошибку:

ORA-06502: PL / SQL: numeri c или ошибка значения ORA-06512: at "OPERA_MARRIOTT. HRS_LASERLINE_BI_PRIHOD ", строка 87

Вы получите это, если l_clob_response пуст, поэтому, возможно, ваше чтение l oop не дает того, что вы ожидаете сейчас. (Что вполне может быть связано с тем, что запрос теперь недействителен JSON или не соответствует ожиданиям службы). После вызова UTL_HTTP.get_response() посмотрите, что показывают l_http_response.status_code и l_http_response.reason_phrase. Коды состояния есть в документации .

...