7

変数の最大長を与える関数がplsqlに存在するかどうか疑問に思っていました。

たとえば、私が宣言した場合

DECLARE

varia VARCHAR2(7)
BEGIN
   call of a function that would return 7
END

varia が null であっても、varchar の長さ 7 を取得できました。

--- 例

create or replace 
TYPE ENREG_320_03 UNDER ENREG_320_BASE(
date_creation VARCHAR2(8),
raison_sociale_emetteur VARCHAR2(35),
adresse_emetteur_1 VARCHAR2(35),
adresse_emetteur_2 VARCHAR2(35),
adresse_emetteur_3 VARCHAR2(35),
num_siret VARCHAR2(14),
ref_remise VARCHAR2(16),
code_bic_emetteur VARCHAR2(11),
type_ident_compte_debit VARCHAR2(1),
ident_compte_debit VARCHAR2(34),
code_devise_compte_debit VARCHAR2(3),
ident_client VARCHAR2(16),
type_ident_compte_frais VARCHAR2(1),
ident_compte_frais VARCHAR2(34),
code_devise_compte_frais VARCHAR2(3),
zone_reserve VARCHAR2(16),
indice_type_debit_remise VARCHAR2(1),
indice_type_remise  VARCHAR2(1),
date_execution_souhait VARCHAR2(8),
devise_transfert VARCHAR2(3),

MEMBER FUNCTION get_date_creation RETURN VARCHAR2 AS
BEGIN
  RETURN CASE WHEN SELF.date_creation IS NULL THEN lpad(' ', 8, ' ') ELSE   rpad(SELF.date_creation, 8, ' ') END;
END get_date_creation;

MEMBER FUNCTION get_raison_sociale_emetteur RETURN VARCHAR2 AS
BEGIN
  RETURN CASE WHEN SELF.raison_sociale_emetteur IS NULL THEN lpad(' ', 35, ' ') ELSE rpad(SELF.raison_sociale_emetteur, 35, ' ') END;
END get_raison_sociale_emetteur;

MEMBER FUNCTION get_adresse_emetteur_1 RETURN VARCHAR2 AS
BEGIN
  RETURN CASE WHEN SELF.adresse_emetteur_1 IS NULL THEN lpad(' ', 35, ' ') ELSE rpad(SELF.adresse_emetteur_1, 35, ' ') END;
END get_adresse_emetteur_1;

MEMBER FUNCTION get_adresse_emetteur_2 RETURN VARCHAR2 AS
BEGIN
  RETURN CASE WHEN SELF.adresse_emetteur_2 IS NULL THEN lpad(' ', 35, ' ') ELSE rpad(SELF.adresse_emetteur_2, 35, ' ') END;
END get_adresse_emetteur_2;

MEMBER FUNCTION get_adresse_emetteur_3 RETURN VARCHAR2 AS
BEGIN
  RETURN CASE WHEN SELF.adresse_emetteur_3 IS NULL THEN lpad(' ', 35, ' ') ELSE rpad(SELF.adresse_emetteur_3, 35, ' ') END;
END get_adresse_emetteur_3;

MEMBER FUNCTION get_num_siret RETURN VARCHAR2 AS
BEGIN
  RETURN CASE WHEN SELF.num_siret IS NULL THEN lpad(' ', 14, ' ') ELSE rpad(SELF.num_siret, 14, ' ') END;
END get_num_siret;

MEMBER FUNCTION get_ref_remise RETURN VARCHAR2 AS
BEGIN
  RETURN CASE WHEN SELF.ref_remise IS NULL THEN lpad(' ', 16, ' ') ELSE rpad(SELF.ref_remise, 16, ' ') END;
END get_ref_remise;

MEMBER FUNCTION get_code_bic_emetteur RETURN VARCHAR2 AS
BEGIN
   RETURN CASE WHEN SELF.code_bic_emetteur IS NULL THEN lpad(' ', 11, ' ') ELSE rpad(SELF.code_bic_emetteur, 11, ' ') END;
END get_code_bic_emetteur;

MEMBER FUNCTION get_type_ident_compte_debit RETURN VARCHAR2 AS
BEGIN
  RETURN CASE WHEN SELF.type_ident_compte_debit IS NULL THEN lpad(' ', 1, ' ') ELSE rpad(SELF.type_ident_compte_debit, 1, ' ') END;
END get_type_ident_compte_debit;

MEMBER FUNCTION get_ident_compte_debit RETURN VARCHAR2 AS
BEGIN
  RETURN CASE WHEN SELF.ident_compte_debit IS NULL THEN lpad(' ', 34, ' ') ELSE rpad(SELF.ident_compte_debit, 34, ' ') END;
END get_ident_compte_debit;

MEMBER FUNCTION get_code_devise_compte_debit RETURN VARCHAR2 AS
BEGIN
  RETURN CASE WHEN SELF.code_devise_compte_debit IS NULL THEN lpad(' ', 3, ' ') ELSE rpad(SELF.code_devise_compte_debit, 3, ' ') END;
END get_code_devise_compte_debit;

MEMBER FUNCTION get_ident_client RETURN VARCHAR2 AS
BEGIN
  RETURN CASE WHEN SELF.ident_client IS NULL THEN lpad(' ', 16, ' ') ELSE rpad(SELF.ident_client, 16, ' ') END;
END get_ident_client;

MEMBER FUNCTION get_type_ident_compte_frais RETURN VARCHAR2 AS
BEGIN
  RETURN CASE WHEN SELF.type_ident_compte_frais IS NULL THEN lpad(' ', 1, ' ') ELSE rpad(SELF.type_ident_compte_frais, 1, ' ') END;
END get_type_ident_compte_frais;

MEMBER FUNCTION get_ident_compte_frais RETURN VARCHAR2 AS
BEGIN
  RETURN CASE WHEN SELF.ident_compte_frais IS NULL THEN lpad(' ', 34, ' ') ELSE rpad(SELF.ident_compte_frais, 34, ' ') END;
END get_ident_compte_frais;

MEMBER FUNCTION get_code_devise_compte_frais RETURN VARCHAR2 AS
BEGIN
  RETURN CASE WHEN SELF.code_devise_compte_frais IS NULL THEN lpad(' ', 3, ' ') ELSE rpad(SELF.code_devise_compte_frais, 3, ' ') END;
END get_code_devise_compte_frais;

MEMBER FUNCTION get_zone_reserve RETURN VARCHAR2 AS
BEGIN
  RETURN CASE WHEN SELF.zone_reserve IS NULL THEN lpad(' ', 16, ' ') ELSE rpad(SELF.zone_reserve, 16, ' ') END;
END get_zone_reserve;

MEMBER FUNCTION get_indice_type_debit_remise RETURN VARCHAR2 AS
BEGIN
  RETURN CASE WHEN SELF.indice_type_debit_remise IS NULL THEN lpad(' ', 1, ' ') ELSE rpad(SELF.indice_type_debit_remise, 1, ' ') END;
END get_indice_type_debit_remise;

MEMBER FUNCTION get_indice_type_remise RETURN VARCHAR2 AS
BEGIN
  RETURN CASE WHEN SELF.indice_type_remise IS NULL THEN lpad(' ', 1, ' ') ELSE rpad(SELF.indice_type_remise, 1, ' ') END;
END get_indice_type_remise;

MEMBER FUNCTION get_date_execution_souhait RETURN VARCHAR2 AS
BEGIN
  RETURN CASE WHEN SELF.date_execution_souhait IS NULL THEN lpad(' ', 8, ' ') ELSE rpad(SELF.date_execution_souhait, 8, ' ') END;
END get_date_execution_souhait;

MEMBER FUNCTION get_devise_transfert RETURN VARCHAR2 AS
BEGIN
  RETURN CASE WHEN SELF.devise_transfert IS NULL THEN lpad(' ', 3, ' ') ELSE rpad(SELF.devise_transfert, 3, ' ') END;
END get_devise_transfert;

フィールドのサイズを取得するための単純な関数が存在するかどうか疑問に思っていたので、ゲッターで数値を使用する必要はありません。フィールドのサイズが変更された場合、ゲッターを変更する必要はありません。うまくいくでしょうvarchar のサイズに関係なく

しかし、それが不可能であることは理解しています

みんなありがとう

4

3 に答える 3

10

Alex Poole が提案した属性を使用したアプローチは%TYPE、ベスト プラクティスの 1 つですが、参考までに VARCHAR2 変数の例を示します。

create or replace function f_declared_length (
     p in out varchar2
   )
     return integer
   is
     r integer;
     a varchar2(32767) := p;
     function f_c ( p in out char ) return integer is
     begin
       return length(p);
     end;
   begin
     p := 1;
     r := f_c(p);
     p := a;
     return r;
   end;
/

それでは、この関数をテストしましょう:

set serveroutput on
declare
   v1 varchar2(23331);
   v2 varchar2(500);
   v3 varchar2(10);

begin
  dbms_output.put_line ( f_declared_length (v1));
  dbms_output.put_line ( f_declared_length (v2));
  dbms_output.put_line ( f_declared_length (v3));
end;
/

anonymous block completed
23331
500
10

ここにオリジナルのコードとアイデアがあります。これは、コール スタックを通過する際に変数の値を VARCHAR2 から CHAR に明示的に変換するときに、Oracle が変数の長さを内部的に認識しているという結論に基づいています。このような情報は、実際の VARCHAR2 パラメータ値に追加する必要があるスペースの量を決定するために使用されます。

于 2013-07-17T13:16:19.150 に答える
2

suPPLer (拍手)
ただの楽しみのための本当にクールなアイデア、私のやり方を見てください )))

declare
    l_var varchar2(10);
begin
    for i in 1 .. 32767 loop
        begin
            l_var := l_var || '*';
        exception
            when others then
                dbms_output.put_line('max length for l_var is ' ||  to_char(i - 1));
                exit;
        end;
    end loop;
end;
于 2013-07-17T13:25:44.547 に答える