PDA

View Full Version : SQL-Precompiler Fehler gefunden ?



Seiten : [1] 2

Fuerchau
19-03-20, 16:11
In meiner aufgelösten SQL-Quelle habe ich was seltsames festgestellt:



//* exec sql select max(PLDAT), sum(PLMENG)
//* into :Wareneingangsdatum :Null1
//* ,:Wareneingangsmenge :Null2
//* from D060
//* where PLBBNR = :D242.BBNR
//* and PLABNR = :D242.BBABNR
//* and PLPONR = :D242.BBPONR
//* ;
SQL_00128 = D242.BBNR;
SQL_00129 = D242.BBABNR;
SQL_00130 = D242.BBPONR;
SQLER6 = -4;
SQLROUTE_CALL(
SQLCA
: SQL_00123
);
IF SQL_00126 = '1';
IF SQL_00132 >= 0;
EVAL WARENEINGANGSDATUM = SQL_00131;
ENDIF;
EVAL NULL1 = SQL_00132;
EVAL WARENEINGANGSMENGE = SQL_00133;
EVAL NULL2 = SQL_00134;
ENDIF;


Man beachte: Wenn der Nullanzeiger vom WARENEINGANGSDATUM >= 0 ist, nur dann wird das WARENEINGANGSDATUM gesetzt.
Warum wird dann das Feld WARENEINGANGSMENGE immer gesetzt?

SQL_00131 enthält nämlich dann den 01.01.0001.
Durch die NULL-Abfrage des Precompilers enthält aber WARENEINGANGSDATUM den vorherigen Wert, während WARENEINGANGSMENGE auf 0 gesetzt wird.

Seltsam....

B.Hauser
19-03-20, 18:37
Man sollte die Ausgabe-Felder immer zunächst initialisieren bzw. nach dem SQL-Statement zunächst die Indikator-Variablen prüfen und dann die Ausgabe-Felder entsprechend initialisieren.

Auszug aus der IBM Dokumentation:

Always test the indicator variable first. If the value of the indicator variable is less than zero, you know the value of the result column should not be used. When the database manager returns a null value, the host variable might or might not be set to the default value for the result column's data type (0 for numeric, blanks for fixed length character, etc).

Birgitta

Fuerchau
19-03-20, 18:41
Das ist mir schon klar, dass ich NULL-Indikatoren abfragen muss.
Ich finde nur die Ungleichbehandlung fragwürdig.

BenderD
19-03-20, 19:15
Das ist mir schon klar, dass ich NULL-Indikatoren abfragen muss.
Ich finde nur die Ungleichbehandlung fragwürdig.

... dir fehlts am Wohlwollen, statt begeistert zu sein, dass da was richtig gemacht wurde, mäkelst du rum, damit hat dich IBM nicht lieb.

D*B

RobertMack
20-03-20, 06:35
Das ist mir schon klar, dass ich NULL-Indikatoren abfragen muss.
Ich finde nur die Ungleichbehandlung fragwürdig.

Kein Mensch muss müssen...



exec sql select coalesce( max(PLDAT), '01.01.0001') ,
coalesce( sum(PLMENG), 0) ,
count(*)
into :Wareneingangsdatum
,:Wareneingangsmenge
,:Gefunden
from D060
where PLBBNR = :D242.BBNR
and PLABNR = :D242.BBABNR
and PLPONR = :D242.BBPONR

Fuerchau
20-03-20, 09:10
Dies funktioniert leider nicht, wenn der Select keine Daten findet;-).
Da die Felder selber kein NULL erlauben, ist das Coalesce hier sinnlos.

Wenn schon, dann muss man den Coalesce außerhalb machen, allerdings erlaubt ein scalarer Subselect nur 1 Ergebnisfeld, die Abfrage müsste also 2 Mal gemacht werden.

exec sql values(coalesce((select f1 ....), Default), coalesce((select f2 ....), Default)) into ...

Man könnte es auch als Left join machen:

with EinSatz as (
values (1)
)
select coalesce(f1, default), coalesce(f2, default) from EinSatz
left join (
select max(f1) f1, sum(f2) f2 from MyTable
where ...
) x on 1=1

Vielleicht hat Birgitta da noch mehr Ideen;-).

Klar kann ich vor dem SQL einen CLear machen. Allerdings läuft auf den SQL-Variablen ebenso ein Clear so dass der 1. Clear (Micro-Optimierung) unnötig ist.
Die NULL-Indikatoren werden doch nur benötigt um nicht haufenweise Joblogs zu produzieren die die Maschine vollmüllen (auch ohne Debugmodus!).

Bei obigem SQL sollte ein SQLCODE 100 eigentlich vollkommen ausreichen;-).

BenderD
20-03-20, 09:33
... wie wärs mit create view mit group by?

Fuerchau
20-03-20, 11:57
Da ich ja eine eindeutige Where-Klausel habe, brauche ich ja keinen Group By.
Außerdem löst das ebenso nicht das Problem bei No Data, ich bräuchte auch entsprechend mehr NULL-Inds.

BenderD
20-03-20, 12:04
Da ich ja eine eindeutige Where-Klausel habe, brauche ich ja keinen Group By.
Außerdem löst das ebenso nicht das Problem bei No Data, ich bräuchte auch entsprechend mehr NULL-Inds.

... die view tauscht dir die nullvalues gegen den sqlcode 100

D*B

Fuerchau
20-03-20, 12:10
Dann könnte das mit
select * from (select max....)
klappen.