Как мы можем определить размер выходного параметра в хранимой процедуре?

Как мы можем определить размер выходного параметра в хранимой процедуре?

10
задан Peter Lang 6 July 2010 в 07:54
поделиться

3 ответа

Вы можете использовать подтип в заголовке пакета и проверить его в теле ...

CREATE OR REPLACE PACKAGE my_test
AS
   SUBTYPE   my_out   IS   VARCHAR2( 10 ); 

   PROCEDURE do_something( pv_variable IN OUT my_out );
END;
/

CREATE OR REPLACE PACKAGE BODY my_test
AS 
   PROCEDURE do_something( pv_variable IN OUT my_out )
   IS
      lv_variable   my_out;
   BEGIN
      -- Work on a local copy of the variable in question
      lv_variable := 'abcdefghijklmnopqrstuvwxyz';

      pv_variable := lv_variable;
   END do_something;

END;
/

Затем, когда вы запустите это

DECLARE
   lv_variable VARCHAR2(30);
BEGIN
   my_test.do_something( lv_variable );
   DBMS_OUTPUT.PUT_LINE( '['||lv_variable||']');
END;
/

, вы получите сообщение об ошибке

ORA-06502: PL/SQL: numeric or value error: character string buffer too small

Кажется, идти вразрез с духом использования параметра out, но после комментария Тони это было единственное, что я мог придумать для управления данными в вызываемом коде.

0
ответ дан 3 December 2019 в 23:48
поделиться

Вот простой пакет, который объявляет и использует подтип:

SQL> create or replace package my_pkg as
  2      subtype limited_string is varchar2(10);
  3      procedure pad_string (p_in_str varchar
  4                          , p_length number
  5                          , p_out_str out limited_string);
  6  end my_pkg;
  7  /

Package created.

SQL> create or replace package body my_pkg as
  2      procedure pad_string
  3          (p_in_str varchar
  4              , p_length number
  5              , p_out_str out limited_string)
  6      as
  7      begin
  8          p_out_str := rpad(p_in_str, p_length, 'A');
  9      end  pad_string;
 10  end my_pkg;
 11  /

Package body created.

SQL>

Однако, если мы вызываем PAD_STRING() таким образом, что выходная строка превышает точность подтипа, она все равно завершается успешно. Беспокоить!

SQL> var out_str varchar2(128)
SQL>
SQL> exec my_pkg.pad_string('PAD THIS!', 12, :out_str)

PL/SQL procedure successfully completed.

SQL>
SQL> select length(:out_str) from dual
  2  /

LENGTH(:OUT_STR)
----------------
              12

SQL>

Это раздражает, но это то, как работает PL / SQL, поэтому мы должны жить с этим.

Способ разрешения situaton в основном заключается в применении принципов DBC и проверке наших параметров. Таким образом, мы можем утверждать бизнес-правила против входных данных следующим образом:

SQL> create or replace package body my_pkg as
  2      procedure pad_string
  3          (p_in_str varchar
  4              , p_length number
  5              , p_out_str out limited_string)
  6      as
  7      begin
  8          if length(p_in_str) + p_length > 10 then
  9              raise_application_error(
 10                      -20000
 11                      , 'Returned string cannot be longer than 10 characters!');
 12          end if;
 13          p_out_str := rpad(p_in_str, p_length, 'A');
 14      end  pad_string;
 15  end my_pkg;
 16  /

Package body created.

SQL>
SQL> exec my_pkg.pad_string('PAD THIS!', 12, :out_str)
BEGIN my_pkg.pad_string('PAD THIS!', 12, :out_str); END;

*
ERROR at line 1:
ORA-20000: Returned string cannot be longer than 10 characters!
ORA-06512: at "APC.MY_PKG", line 9
ORA-06512: at line 1


SQL>

Или мы можем утверждать бизнес-правила против выходных данных, как это:

SQL> create or replace package body my_pkg as
  2      procedure pad_string
  3          (p_in_str varchar
  4              , p_length number
  5              , p_out_str out limited_string)
  6      as
  7          l_str limited_string;
  8      begin
  9          l_str := rpad(p_in_str, p_length, 'A');
 10          p_out_str := l_str;
 11      end  pad_string;
 12  end my_pkg;
 13  /

Package body created.

SQL>
SQL> exec my_pkg.pad_string('PAD THIS!', 12, :out_str)
BEGIN my_pkg.pad_string('PAD THIS!', 12, :out_str); END;

*
ERROR at line 1:
ORA-06502: PL/SQL: numeric or value error: character string buffer too small
ORA-06512: at "APC.MY_PKG", line 9
ORA-06512: at line 1

SQL>

В большинстве сценариев мы должны делать и то, и другое. Это вежливый способ создания интерфейсов, потому что это означает, что другие процедуры могут вызывать наши процедуры с уверенностью, что они вернут значения, которые, по их словам, они будут.

3
ответ дан 3 December 2019 в 23:48
поделиться

Вы не можете. Конечно, вы контролируете, сколько данных вы помещаете в параметр OUT в хранимой процедуре. При желании можно создать локальную переменную размера для хранения данных, а затем присвоить значение этой переменной параметру OUT.

Вызывающая программа определяет размер переменной, получая параметр OUT.

10
ответ дан 3 December 2019 в 23:48
поделиться
Другие вопросы по тегам:

Похожие вопросы: