PDA

View Full Version : SQL Programmierung - Feststellen, ob etwas gefunden wurde



Seiten : [1] 2 3

dschroeder
13-06-24, 10:51
Guten Tag,
ich habe eine (wahrscheinlich) triviale Frage:

Ich möchte eine SQL-Funktion (UDF) schreiben. In der Funktion lese ich mit einer select Anweisung einen Satz aus einer Tabelle.
Nach der select Anweisung möchte ich möglichst einfach feststellen, ob ein Datensatz gefunden wurde.

Wenn ich das in embedded SQL im RPGLE machen würde, könnte ich einfach den SQLCOD auf 100 abfragen. Das geht aber so nicht im reinen SQL, oder?

Hier mal ein ganz einfaches Beispiel:


declare resultBlob Blob(2G) default null;

select rb_blob into resultBlob from idmrepos where re_id = 4711;


Wenn ich jetzt einfach abfrage, ob das Feld resultBlob null ist, wüsste ich nicht, ob der Key (4711) falsch war oder ob der Key korrekt war, aber das Datenbankfeld rb_blob null war.

Gibt es eine einfache Methode, das abzufragen? Am liebsten so etwas wie ("if found()") oder so.

Dieter

Robi
13-06-24, 11:09
count(*) optimice for 1 row

Fuerchau
13-06-24, 11:13
Der SQLCODE gibt 0, wenn gefunden, 100 bei nicht gefunden zurück.
Bei Fehlern auch was anderes.

dschroeder
13-06-24, 11:24
Vielen Dank euch beiden. Aber ich fürchte, ihr habt die Fragestellung nicht richtig gelesen:



Zu Baldur:
Ich möchte das in SQL programmieren. NICHT in embedded SQL im RPG !!!
Deshalb habe ich die Variable SQLCOD gar nicht, oder gibt es die auch so im SQL?
Zu Robi:
Ich will nicht mit einer extra select count -Anweisung die Abfrage nochmal wiederholen. Ich habe eine Anweisung, die mit select Daten aus einem Datensatz holt. Ich will nur wissen, ob das geklappt hat.
Im RPG würde ich den SQLCOD 100 abfragen. Aber ich bin nicht im RPG!


Oder habe ich euch falsch verstanden?

Robi
13-06-24, 11:28
dann mußt du mehrere Felder holen mit mind. einem, das nicht null werden kann. z.B deine re_id

Fuerchau
13-06-24, 11:28
Du hast Recht, die IBM i DB2 macht das etwas anders:
https://www.ibm.com/docs/en/i/7.4?topic=procedures-defining-sql-procedure

<code class="hljs language-plaintext-ibm">DECLARE CONTINUE HANDLER FOR NOT FOUND
SET END_TABLE = 1;
DECLARE EXIT HANDLER FOR SQLEXCEPTION
SET DEPT_SALARY = NULL;</code>

dschroeder
13-06-24, 11:35
dann mußt du mehrere Felder holen mit mind. einem, das nicht null werden kann. z.B deine re_id

Genau das mache ich im Moment. Ich finde es aber unschön und dachte, es gibt etwas eleganteres. Ich mache das jetzt so:

select true, rb_blob
into gefunden, resultBlob where ...

Leider muss man dazu extra eine Variable deklarieren ("gefunden"), die man z.B. im RPG nicht benötigen würde.

dschroeder
13-06-24, 11:38
Du hast Recht, die IBM i DB2 macht das etwas anders:
https://www.ibm.com/docs/en/i/7.4?topic=procedures-defining-sql-procedure

<code class="hljs language-plaintext-ibm">DECLARE CONTINUE HANDLER FOR NOT FOUND
SET END_TABLE = 1;
DECLARE EXIT HANDLER FOR SQLEXCEPTION
SET DEPT_SALARY = NULL;</code>

Danke für das Beispiel. Aber das finde ich ziemlich kompliziert für so eine eigentlich einfache Sache.
Man kann sich wohl auch mit GET DIAGONOSTICS die Info besorgen. Aber das ist alles relativ viel Code für eine einfach found-Abfrage, finde ich.

Aber ich bin beruhigt: Eure Beispiele zeigen mir, dass ich da wohl keine triviale Lösung übersehen habe.

Nochmals Danke an euch beide.

Fuerchau
13-06-24, 11:45
Ob ich nun

<code class="hljs language-plaintext-ibm">DECLARE CONTINUE HANDLER FOR NOT FOUND
SET END_TABLE = 1;

oder

if SQLCODE <> 0
</code><code class="hljs language-plaintext-ibm">SET END_TABLE = 1;

kodiere, ist doch jetzt nicht der große Unterschied.</code>

dschroeder
13-06-24, 12:44
Ob ich nun

<code class="hljs language-plaintext-ibm">DECLARE CONTINUE HANDLER FOR NOT FOUND
SET END_TABLE = 1;

oder

if SQLCODE <> 0
</code><code class="hljs language-plaintext-ibm">SET END_TABLE = 1;

kodiere, ist doch jetzt nicht der große Unterschied.</code>

Dann habe ich deinen Code doch noch nicht verstanden. Ich mache mal ein kleines Besipiel:

In meiner Funktion will mehrere selects abschicken und jeweils wissen, ob es geklappt hat. Muss ich dann mehrmal den Continue Handler deklarieren?

Also z.B.



DECLARE CONTINUE HANDLER FOR NOT FOUND
SET END_TABLE = 1;

select ku_name from kunden into name;
if end_table = 1 then
erzeugeError(....)
else
macheWasGueltiges(name);
end if;


select pr_preis from artikel into preis;
if end_table = 1 then
erzeugeError(....)
else
macheWasGueltiges(preis);
end if;



Meinst du das?
Oder muss ich vor jedem select den declare und den set machen?