Beispiele für Datenbankfunktionen

 

Beispiel für eine Datenbankfunktion für die Partieverteilung:

 

CREATE PROCEDURE "admin"."p_PartieAutoSuche"

(

     -- Die Parameter wurden automatisch mit der  Einrichtung unter FRZ/Partie/DB Prozedur für Verteilung

     -- zusammengestellt( Cursor im Feld DB Prozedur für Verteilung positionieren, SF8, Parameter auswählen / Testfunktion ausführen)

     in in_Vorgangsklasse   integer

   , in in_Unterklasse    integer

   , in in_VerteilMenge   numeric (15,6)

   , in in_Mengeneinheit    integer

   , in in_ArtikelId    integer

   , in in_KundId   integer

   , in in_EKVK_kennzeichen   integer

   , in in_AbgrenzDatum   date

   , in in_ArtikelStammId   integer

   , in in_NurDiesePartie_Id   integer

   , in in_LagerPLatzNummer   integer

)

-- Das Resultset muss mindestens die hier aufgeführten Felder haben. Die Reihenfolge

-- ist nicht wichtig - die Namensgebung aber um so mehr !

-- eine eine Zurückgegeben zeile entspricht einer Partiezuordnung

-- es können mehrere, eine oder auch keine Zeilen zurückgegeben werden

result

(

   PartieId integer,                    -- Die Partieid ist absolut wichtig

   PartieNummer integer,

   PartieBezeich char(40),

   PartieAbdatum date,

   PartieEKP_Kennz smallint,            -- wichtige Kennzeichen für die Partiepreisermittlung

   PartieVKP_Kennz smallint,            -- dito

   WaehrNummer smallint,                -- in welcher Währung wird die Partie geführt

   Me_NummerPartie integer,             -- die Mengeneinheit der Partiebestandsbuchführung

   PartieArtiPosit integer,             -- wichtig für die eindeutige Identifiziere des Artikels in der Partie

   LagerplatzNummer integer,            -- von welchem Lagerplatz soll abgebucht werden

   sort_lagerplatz integer,             -- Hilfsfeld zum Sortieren eigenen und fremden Lagerplätze ( zum Lagerplatz der Warenposition)

   RestMenge_VK numeric(15,4 )          -- Benennung dieses Feldes ist historisch gewachsen. Es gibt sowohl bei Einkauf als auch

                                        -- bei Verkauf die zugeordnete Menge dieser Partiezeile an !!!

)

BEGIN

-- lokale temporäre Tabelle für Zwischenergebnisse

declare local temporary table p_result

(

   PartieId integer,

   PartieNummer integer,

   PartieBezeich char(40),

   PartieAbdatum date,

   PartieEKP_Kennz smallint,

   PartieVKP_Kennz smallint,

   WaehrNummer smallint,

   Me_NummerPartie integer,

   PartieArtiPosit integer,

   LagerplatzNummer integer,

   sort_lagerplatz integer,

   RestMenge_VK numeric(15,4 )

) on commit preserve rows;

   declare dc_err_notfound exception for sqlstate value '02000';

   declare dc_PartieId integer;

   declare dc_PartieNummer integer;

   declare dc_PartieBezeich char(40);

   declare dc_PartieAbdatum date;

   declare dc_PartieEKP_Kennz smallint;

   declare dc_PartieVKP_Kennz smallint;

   declare dc_WaehrNummer smallint;

   declare dc_Me_NummerPartie integer;

   declare dc_PartieArtiPosit integer;

   declare dc_LagerplatzNummer integer;

   declare dc_sort_lagerplatz integer;

   declare dc_RestMenge_VK numeric(15,4) ;

   declare dc_buchmenge numeric(15,4);

   declare me_Nummer_Artikel integer;

   declare me_nummer_effektiv integer;

-- Ein Cursor für alle potentiell möglichen Partien

  declare partiedaten dynamic scroll cursor for

  -- Hinweis: der With-Anteile selektiert  alle  formal passenden Partien

  -- gemäß der   Bedeutung in Aeins

  with preselect( partieid,artikelid,partieartiposit) as

  (

    select s.partieid, a.artikelid,min(a.partieartiposit)

    from PartieArtikel a join Partiestamm s on (a.PartieId = s.PartieId)

    where

      ( ((a.ArtikelId = in_ArtikelStammId) and (a.PartieArtiTyp = 4))

      or((a.ArtikelId = in_ArtikelId) and (a.PartieArtiTyp = 5)))

    and (s.PartieErlKennz = 0)

    and (s.PartieLoeKennz = 0)

    and (s.PartieSperrKennz = 0)

    and (s.PartieTyp = 1)

    and (in_AbgrenzDatum    between s.PartieAbDatum and s.PartieBisDatum)

    and ( in_NurDiesePartie_Id  = 0 or in_NurDiesePartie_Id  = s.PartieId)

    and ( ( (in_EKVK_kennzeichen = 2) and ( (s.PartieKunLiKennz = 0)     //:OR_IS_LGU_ARU

        or (in_KundId in ( select KundId from PartieKundListe l

                         where (l.PartieId = s.PartieId) ) ) ) )

      or ( (in_EKVK_kennzeichen != 2) and ( (s.PartieLieLiKennz = 0)    // :OR_IS_LGU_ARU

        or (in_KundId in ( select KundId from PartieLiefListe l

                     where (l.PartieId = s.PartieId) ) ) ) ) )

    and ( (s.PartieWagrKennz = 0) )

    group by s.partieid, a.artikelid

  )

   -- Zusammenstellen der Ergebnisse im eigentlichen Select

  select

  s.PartieId,s.PartieNummer,s.PartieBezeich,s.PartieAbdatum,s.PartieEKP_Kennz,s.PartieVKP_Kennz,

  s.WaehrNummer,s.ME_Nummer as Me_NummerPartie,a.PartieArtiPosit,pbp.LagerplatzNummer,

  if ( pbp.LagerplatzNummer = in_LagerPLatzNummer )

    then cast(0 as integer)

    else cast(1 as integer)

  endif as sort_lagerplatz,   -- bewirkt in der Itembox Sortierung: zunächst Partien passend zum vorgegebenen LAgerplatz

  AMIC_FUNC_PARTIEBESTAND(ps.PartieId,in_ArtikelId,pbp.lagerplatznummer,0,1)

    as  RestMenge_VK

  from preselect ps

  join PartieArtikel a on a.partieid = ps.partieid and a.partieartiposit = ps.partieartiposit

  join Partiestamm s on (a.PartieId = s.PartieId)

  LEFT join partiebestandpur pbp on pbp.partieid = ps.partieid and pbp.artikelid = in_Artikelid

  left outer join partiestammaddon padd on(ps.partieid=padd.partieid)

  where 1 = 1

  and Restmenge_VK > 0

  //AND_ONLY_ID

  order by isnull(padd.mhd,s.PartieAbDatum) , s.PartieNummer, a.PartieArtiPosit;

  // Einige Vorselects

  select me_nummerLager into me_Nummer_Artikel   from artikelstamm ars join

  mengeinhgruppe mg on mg.me_grupnummer  =  ars.me_grupnummer and ars.Artistammid = in_ArtikelStammId;

  // Steupa für Mengenbuchführung in ME der Partie

  IF VAREXISTS('db_SPA606') = 0 THEN

    create variable db_SPA606 integer;

    select   AMIC_STEUPA_WERT_TODAY( 606 ) into db_SPA606 from dummy  ;

  END IF;

  open  partiedaten;

  workloop::

  loop

    fetch next partiedaten

    into

      dc_PartieId ,

      dc_PartieNummer,

      dc_PartieBezeich ,

      dc_PartieAbdatum ,

      dc_PartieEKP_Kennz ,

      dc_PartieVKP_Kennz ,

      dc_WaehrNummer ,

      dc_Me_NummerPartie ,

      dc_PartieArtiPosit,

      dc_LagerplatzNummer ,

      dc_sort_lagerplatz ,

      dc_RestMenge_VK ;

    if sqlstate = dc_err_notfound then

      leave workloop;

    end if;

    // schon genug Menge zurückgegeben

    if in_VerteilMenge <= 0 then

      leave workloop;

    end if;

    set dc_buchmenge = 0;

    // Umrechnung Mengeneinheit aus der Partie

    // in die Mengeneinheit der zu verteilenden Menge

    set me_nummer_effektiv = me_Nummer_Artikel;

    if ( db_SPA606 = 1  and isnull(dc_Me_NummerPartie,0)  != 0 )  then // Me Nummer der Partie soll wirken für Bestandsmenge

      set  me_nummer_effektiv = dc_Me_NummerPartie;

    end if;

    if ( me_Nummer_Artikel is not null ) then

      set dc_RestMenge_VK = Amic_Me_Umrechnung( dc_RestMenge_VK,me_nummer_effektiv,0,in_Mengeneinheit,0,in_Artikelid,4 );

    end if;

    if ( dc_RestMenge_VK >= in_VerteilMenge ) then

       set dc_buchmenge = in_VerteilMenge;

    else

     set dc_buchmenge = dc_RestMenge_VK;

    end if;

    if ( dc_buchmenge > 0 ) then

      insert into p_result values

      (

        dc_PartieId ,

        dc_PartieNummer,

        dc_PartieBezeich ,

        dc_PartieAbdatum ,

        dc_PartieEKP_Kennz ,

        dc_PartieVKP_Kennz ,

        dc_WaehrNummer ,

        dc_Me_NummerPartie ,

        dc_PartieArtiPosit,

        dc_LagerplatzNummer ,

        dc_sort_lagerplatz ,

        dc_buchmenge

      );

      // den noch zu verteilenden Rest anpassen

      set in_VerteilMenge = in_VerteilMenge - dc_buchmenge;

    end if ;

  end loop workloop;

  close partiedaten;

  commit;

  --Rückgabe der Ergebnisse

  select * from p_result;

END

 

Beispiel für eine Datenbankfunktion für Gebindeparameter:

 

// FUNCTION AMIC_V_UKlassGebFak1Proc

//       

//---------------------------------------------------------------------

CREATE FUNCTION AMIC_V_UKlassGebFak1Proc (

  IN ArtikelId INTEGER,

  IN MeNummer INTEGER,

  IN Lagerplatznummer INTEGER,

  IN Menge DECIMAL(15,4))  

  RETURNS DECIMAL(15,4)

BEGIN

 

  DECLARE anzahl_partien INTEGER;

  DECLARE ergebnis DECIMAL(15,4);

  set anzahl_partien = (select count(*) from Temp_Partie_Uebergabe);

  if  anzahl_partien > 0 THEN

   // für 'mit Partien' temporäre Tabelle Temp_Partie_Uebergabe nutzen

   // für jeden einzelnen Datensatz die Menge anpassen

   // Menge möglichst auf zwei Nachkommastellen runden

   update Temp_Partie_Uebergabe set menge = round(menge * 1.276,2); 

   commit;

   set ergebnis = (select sum(isnull(menge,0)) from Temp_Partie_Uebergabe);

  ELSE

    // neue Gesamtmenge zurückgeben

    set ergebnis = round (menge * 1.5,2);

  END IF ;

  return ergebnis;

END