Anmelden

View Full Version : SQL0811



Seiten : [1] 2

tarkusch
13-09-12, 11:06
Hallo,

habe den Sql-Fehler erhalten

Nachrichten-ID . . . . : SQL0811 Bewertung . . . . . . : 30 Nachricht . . . : Ergebnis der Anweisung enthält mehr als eine Zeile.
Ursache . . . . : Die Ergebnistabelle einer Anweisung SELECT INTO, einer
Unterabfrage oder einer Unterauswahl einer Anweisung SET enthält mehr als
eine Zeile. Es handelt sich um Fehlerart 1. Bei Fehlerart 1 wurde von einer
Anweisung SELECT INTO versucht, mehr als eine Zeile zurückzugeben. Bei
Fehlerart 2 wurde durch eine Unterauswahl eines Basisprädikats mehr als eine
Zeile erstellt. Es ist nur eine Zeile zulässig.
Fehlerbeseitigung: Die Auswahl so ändern, dass nur eine Ergebniszeile
zurückgegeben wird, und die Anforderung wiederholen. Zur Verarbeitung
mehrerer Ergebniszeilen müssen die Anweisungen DECLARE CURSOR, OPEN und
FETCH verwendet werden. Für eine Unterabfrage können die Prädikate IN,
EXISTS, ANY und ALL verwendet werden, um mehrere Ergebniszeilen zu


Bei den SUM Funktionen habe ich einen Indikator angegeben.

Meine Vermutung ist es, das der Fehler bei diesem Statement auftritt:

c/exec sql
C+ SELECT Feld1 INTO :W1feld1 FROM file WHERE ....
C+ ....
c/end-exec


Fall ich den Fehler abfangen möchte, würde das so funktonieren?

C Monitor
c/exec sql
C+ SELECT Feld1 INTO :W1feld1 FROM file WHERE ....
C+ ....
c/end-exec
C on-Error *ALL
C Endmon
C ENDSR

In welcher Zeile, der Sql-Fehler auftritt, sehe ich aus der Nachricht nicht oder?

Dank im Voraus

Gruß

Tarki

mk
13-09-12, 11:28
Hallo,

mit dem Debugger das Programm nach den SQL Statements anhalen
und das Feld SQLCODE anzeigen. Darin ist der Status
enthalten.


Im RPG kann an den Status dann abfragen
IF SQLCODE =
Endif


gruß
Michael

tarkusch
13-09-12, 11:31
mein Problem ist es das der spezielle Fall sporadisch vorkommt.
Falls ich es Teste funktioniert alles so wie es sollte.

Fuerchau
13-09-12, 11:41
SQL-Fehler können nicht mit Monitor abgefangen werden, dafür ist der SQLCODE zuständig.

Dein Problem ist wohl, dass die Where-Klausel ab und zu eben mehr als einen Datensatz liefert.
In diesem Fall schlägt der SQL fehl und liefert lieber keine Daten.

Du hast mehrere Möglichkeiten:

select ....
fetch first 1 rows only

Damit wird einfach nur der 1. Datensatz gelesen, egal ob es mehrere gibt.

Select Min(Feld1) into ...

nimm halt den kleinsten Wert, alternativ geht natürlich auch MAX/SUM/AVG/...

Oder prüfe die Daten besser, warum ggf. mehr da ist als du erwartest.

tarkusch
13-09-12, 11:53
Aber wie kann vorher schon prüfen/abfangen ob der Sqlfehler auftritt?
Wie ist da so die Vorgehensweise?

andreaspr@aon.at
13-09-12, 12:20
Kleiner Tipp am Rande:
Wenn du das SQL Statement öfters aufrufst (vielleicht sogar innerhalb einer Schleife) solltest du lieber einen Cursor verwenden. Auch wenn du nur einen Satz lesen willst.
Dadurch bleibt ab dem 2ten mal lesen, der ODP vorhanden und muss nicht neu erstellt werden.

Du könntest es mit einem Select count(*) Into :v1 ... prüfen.
Wobei das nicht das eigentliche Problem löst.
Wenn du nur 1 Satz haben willst, musst du feststellen, welche Kriterien zutreffen müssen (WHERE-Klausel). Wenn hin und wieder doch mehrere Sätze vorkommen, dann sind die Kriterien nicht ausreichend und du musst das Konzept neu überdenken.

Lass ein Monitor für diese Abfrage eingegränzt laufen. Dann siehst du bei welchen Kriterien mehrere Sätze gefunden werden.

lg Andreas

tarkusch
13-09-12, 12:27
Ich habe mir die Daten angesehen und es sind defintiv mehrere Sätze zu einem Statement.

Wie lasse ich eigentlich einen Monitor laufen? Da stehe ich völlig auf dem Schlauch.

lg
Tarki

andreaspr@aon.at
13-09-12, 12:42
Wie lasse ich eigentlich einen Monitor laufen? Da stehe ich völlig auf dem Schlauch.

iSeries Navigator --> Datenbanken --> deine Datenbank --> SQL Performance Monitors
Rechts-Klick --> Neu --> usw.

Oder im Green-Screen: STRDBMON

Wichtig bei beiden ist den Monitor auch wieder manuell zu Beenden. Da er sonst "ewig" läuft.

B.Hauser
13-09-12, 13:46
Kleiner Tipp am Rande:
Wenn du das SQL Statement öfters aufrufst (vielleicht sogar innerhalb einer Schleife) solltest du lieber einen Cursor verwenden. Auch wenn du nur einen Satz lesen willst.
Dadurch bleibt ab dem 2ten mal lesen, der ODP vorhanden und muss nicht neu erstellt werden.



Das stimmt so nicht! SELECT ... INTO oder VALUES ... INTO führen im Hintergrund einen DECLARE, OPEN, FETCH und CLOSE aus! Die ODPs bleiben ab dem 2. Mal öffen, sofern sie wiederverwendbar sind.

Birgitta

B.Hauser
13-09-12, 13:52
Aber wie kann vorher schon prüfen/abfangen ob der Sqlfehler auftritt?
Wie ist da so die Vorgehensweise?

Du prüfst nicht vorher oder hinterher.
Sofern mehrere Datensätze zurückkommen können und Du z.B. nur wissen willst ob mindestens ein Datensatz vorhanden ist, musst Du, wie Baldur vorgeschlagen hat einfach FETCH 1 ROW ONLY hinzufügen und schon wird entweder kein oder genau 1 Datensatz ausgegeben:


/Free
Clear isFound;
Exec SQL
Select 1 into :isFound
From AuftrPos
where AutrNr = :HstAuftrag
and Status < 70
Fetch First Row Only;
If SQLCODE < *Zeros and SQLCODE <> -811;
//Fehler
ElseIf SQLCODE = 100 or isFound = *Zeros;
//Kein Satz gefunden
Else;
//Satz vorhanden
Endif;

Birgitta