PDA

View Full Version : UDF



HEBORA
08-10-15, 16:28
Hallo,
Ich habe mit dem OPSNAV unter LIB/FUNTIONEN mit neue eine SQL-Function erstellt.

CREATE FUNCTION JAKAO/KDARTIKEL (
PMDT CHAR(1) ,
PKDNR DECIMAL(6, 0) ,
PPROG CHAR(4) ,
PARTNR CHAR(10) ,
PDATUM DECIMAL(8, 0) )
RETURNS CHAR(20)
LANGUAGE SQL
SPECIFIC JAKAO/KDARTIKEL
NOT DETERMINISTIC
READS SQL DATA
RETURNS NULL ON NULL INPUT
NO EXTERNAL ACTION
SET OPTION ALWBLK = *ALLREAD ,
ALWCPYDTA = *OPTIMIZE ,
COMMIT = *NONE ,
DECRESULT = (31, 31, 00) ,
DFTRDBCOL = *NONE ,
DYNDFTCOL = *NO ,
DYNUSRPRF = *USER ,
SRTSEQ = *HEX
BEGIN
.......

aber immer beim Ausführen mit 5 parametern:
select KDARTIKEL('1', 110406, 'CIEZ', 'H661-9', 20151008) from kdart1p


kommt folgende Meldung:
QL-Status: 42704
Vendorencode: -204
Nachricht: [SQL0204] KDARTIKEL der Art *N in *LIBL nicht gefunden. Ursache . . . . : KDARTIKEL der Art *N in *LIBL wurde nicht gefunden

mit zusätzlichem ?
select KDARTIKEL('1', 110406, 'CIEZ', 'H661-9', 20151008, ?) from kdart1p

folgende Meldung:


SQL-Status: 07001
Vendorencode: -99999
Nachricht: Anzahl definierter oder registrierter Parameterwerte stimmt nicht mit Anzahl der Parameter überein.


Was muss ich anders machen, damit es funktioniert?

Gruß
Heinfried

Fuerchau
08-10-15, 17:17
Die Aufrufparameter müssen zu den Definitionen genau passen.
Also entsprechende Cast's angeben damit es passt.
SQL verwendet VARCHAR bei Konstanten Zeichenketten und je nach Typ der Zahl eben Integer oder Decimal(n, m), wobei n und m automatisch festgelegt werden.

Also:

select KDARTIKEL(cast('1' as char(1)), cast(110406 as dec(6, 0)), cast('CIEZ' as char(4)), cast('H661-9' as char(10)), cast(20151008 as dec(8, 0)) from kdart1p

Bei der Verwendung von Variablen gilt dies dann genauso. Wenn die nicht passen, müssen die passend gecasted werden.
Für Zeichenvariablen eignen sich daher VARCHAR als Parameter am besten, da SQL hier fast alles erlaubt.
Bei Zahlen gibt es leider keine generelle Definition, die alles kann.

HEBORA
09-10-15, 09:56
Hallo,
funtioniert!!
Ich dachte das formatieren würde nur den Rückgabewert betreffen.

Fuerchau
09-10-15, 10:05
Beim Aufruf ist der Rückgabewert ja nicht relevant sondern ist ein Ergebnis.
Versuche trotzdem, ob du die Zeichenparameter als VARCHAR definieren kannst.
Für die Dezimalvariablen macht SQL (je nach Version V6 oder V7) ggf. auch einen Autocast.

HEBORA
12-10-15, 07:21
Hallo,
das klappt soweit alles wunderbar.
Aber wie muß ich ein Programm aufrufen, in dem die Parameter zum Teile über eine externe Datenstruktur übergeben werden?
aus einem anderen RPG-Programm sieht der Aufruf wie folgt aus:

D ...
D AUS1 E DS EXTNAME(DATEI)
D
D AUSGABE S DIM(999)
D LIKE(AUS1)
C *ENTRY PLIST
C PARM PARM1
C PARM PARM2
C PARM PARM3
C ...

C CALLB 'PROGRAMM'
C PARM PARM1
C PARM PARM2
C PARM PARM3
C ...
C PARM AUSGABE
C PARM PARMx
C ....


Gruß Heinfried

Fuerchau
12-10-15, 08:20
Das geht native überhaupt nicht.
Hier musst du einen "Wrapper" als externe Prozedur/Funktion schreiben, die das Original dann mit den Argumenten aufruft.
Bedenke aber, dass du zwar 256 Parameter definieren kannst, aber spätestens mein Aufrufen bekommt man ein Zählproblem.

Als Funktion kannst du ja nur einen Wert zurückgeben, als TABLE kannst du auch Strukturen als SQL-Tabelle zurückgeben.

B.Hauser
12-10-15, 10:34
Bedenke aber, dass du zwar 256 Parameter definieren kannst, aber spätestens mein Aufrufen bekommt man ein Zählproblem.

Seit V5R4 1024 Parameter für Stored Procedures, für UDFs bis Release 7.1 TR 9 bzw. Release 7.2 TR1 90 Parameter - seit Release 7.1 TR10 bzw. Release 7.2 TR2 1024 Parameter!
Seit Release 7.1 TR8 bzw. Release 7.2 können für Parameter, die an Stored Procedures übergeben werden Default-Werte festgelegt werden, beim Aufruf der Stored Procedure können die Parameter benannt und den benannten Parametern ein Wert zugewiesen werden. Nicht übergebene Parameter werden durch die Default-Werte ersetzt.
Für UD(T)Fs wurde dieser Mechanismus (Default-Werte und Parameter-Argumenten-Liste) erst mit dem letzten TR eingeführt.

Beim Aufruf von Programmen muss man berücksichtigen, dass ein Programm keinen Rückgabe-Wert, sondern allenfalls Ein-/Ausgabe-Parameter hat. Gleiches gilt für Prozeduren, die keinen Rückgabe-Wert besitzen und über einen verbundenen CALL (CallB oder mit Prototyp CALLP) aufgerufen werden.
Programme werden i.d.R. als Stored Procedures (CREATE PROCEDURE) registriert und mit dem SQL-Befehl CALL aufgerufen.
SQL kann keine Datenstrukturen verarbeiten, der entsprechende Parameter kann allenfalls als alphanumerischer String definiert, befüllt und übergeben werden.

Wie Baldur bereits gesagt hat, kann eine Wrapper-Funktion um das Programm bzw. die Prozedur ohne Rückgabe-Wert gebildet werden, in der der Ausgabe-Parameter als Rückgabewert definiert ist.

Mit UDTFs (User Defined Table Functions) kann zwar eine Tabelle von Rückgabe-Werten definiert werden, mit einem einfachen Registrieren eines Programms ist es jedoch nicht getan. Programme, die als UDTFs registriert werden, werden vom Datenbanken-Manager über Call-Back-Processing mindestens 3 Mal (OPEN, FETCH, CLOSE) aufgerufen und erfordern Parameter-Style DB2SQL. Abhängig vom Call-Type müssen im Programm unterschiedliche Aktionen ausgeführt werden.

Birgitta

Fuerchau
12-10-15, 11:23
Was die 1024 Parameter angeht so muss man ja bedenken, dass zu jedem noch ein NULL-Indicator übergeben wird.
Irgendwie steht das in Diskrepanz zu den max. 400 Parametern einer ILE-Prozedur (COBOL, RPG), oder auch hier wurde massiv erweitert.
Nichts desto trotz dienen solche Konstrukte eher den Generatoren als nutzvollen Komponenten.