# SQL Exception "Weiterleiten der Egebnissmenge"



## rh-spirit (5. Jan 2006)

Hallo Leute,

überraschenderweiße bekomme ich bei sonst so oft verwendeten Code nun plötzlich eine SQL-Exception
"Ungültiger Vorgang bei Nur-Weiterleiten-Ergebnismenge: isLast"

Folgendes Vorgehen: Aufrufen einer StoredProcedure (2Inputparemeter,1Outputparemetr), auslesen ResultSet (Eine Spalte: Zeile für Zeile solange bis Ende).
Dann soll eigentlich das ResultSet wieder auf die erste Zeile zurück, da eine neue Spalte ausgelesen werden soll.
Dann tritt aber der FEhler auf.. Ich glaube das errinnert mich daran, wenn man das ResultSet auf Type_Fetch_Foward oder ähnliches stellt, dann geht natürlich kein rs.first();



```
CallableStatement cs =con.prepareCall("{call procedurexxx?,?,?)}",ResultSet.TYPE_SCROLL_INSENSITIVE,ResultSet.CONCUR_READ_ONLY);

cs.setInt(1,a_integer);
cs.setInt(2,a_integer);       
cs.registerOutParameter(3,oracle.jdbc.OracleTypes.CURSOR);

cs.execute();
ResultSet rs = (ResultSet)cs.getObject(3);

//Action:
while (rs.next(){
....
}

rs.first();  //hier tritt EXC auf

//Action2:
while (rs.next()){
....
}
```

DAs ganze muss wohl irgendwas mit dem Thema StoredProcedures auf sich haben.
Aber laut JavaApiDoc kann man die ResultSetconfig in dem Constructor .prepareCall einsetzen.
Ob das aber das richtige ist weiss ich nicht. Denn das ausführen des Statement liefert einen Parameter mit nur einem Inhalt zurück. (Oracle Cursor) Aus diesen kann ich ein ResultSet "ClassCasten". Doch welche eigenschaften hat dieses ResultSet?


Für jeden Hinweis,Idee,Hilfe dankbar.


----------



## rh-spirit (5. Jan 2006)

Ich meine natürlich den Fehler:

"Ungültiger Vorgang bei Nur-Weiterleiten-Ergebnismenge: first"


----------



## Bleiglanz (5. Jan 2006)

```
ResultSet rs = (ResultSet)cs.getObject(3); //?

// und warum nicht:
ResultSet rs = cs.executeQuery();

// und ResultSet.TYPE_SCROLL_INSENSITIVE verträgt sich nicht mit
rs.first();  //hier tritt EXC auf
```


----------



## Bleiglanz (5. Jan 2006)

ach ja


> Dann soll eigentlich das ResultSet wieder auf die erste Zeile zurück, da eine neue Spalte ausgelesen werden soll.


warum liest du nicht in einem durchgang alle relevanten spalten?


----------



## rh-spirit (5. Jan 2006)

Beim Debuggen ist mir aufgefallen, wenn nach der while-Schleife das letzte rs.next() abgefragt wurde, wird automatisch irgendwie beim ResultSet der Parameter "closed" auf "true" gesetzt.

Na dann kanns ja nichts werden!!

Ich nehme an das hat was mit dem Typ des REsultSets zu tun. Scheinbar nimmt er meine Konfiguration, die ich bei prepreCall angehangen habe, nicht an?


----------



## rh-spirit (5. Jan 2006)

Bleiglanz hat gesagt.:
			
		

> ach ja
> 
> warum liest du nicht in einem durchgang alle relevanten spalten?



Das ganze dient zum erstellen einer XML-Datei.
Da ich diese quasi "seriell" mit dem FileWriter schreibe, erledige ich meine Aufgaben auch "seriell".


Erstmal wollte ich aus Performancegründen keine RS erst in ein Array oder sonstwas speichern und dann
das Array später so auslesen wie es in die Datei geschrieben werden soll. Also den Zwischenschritt will ich mir sparen.
Natürlich ist das die Notlösung wenn nichts geht.


----------



## Guest (5. Jan 2006)

Bleiglanz hat gesagt.:
			
		

> ```
> ResultSet rs = (ResultSet)cs.getObject(3); //?
> 
> // und warum nicht:
> ...



// welcher Typ denn dann? Bzw. welche Methode läßt mich dann ohne Exception das REsultSet wieder auf die erste //Zeile setzen?


----------



## Bleiglanz (5. Jan 2006)

> // welcher Typ denn dann? Bzw. welche Methode läßt mich dann ohne Exception das REsultSet wieder auf die erste //Zeile setzen?


darf ich hier mal ein RTFM anbringen? lies die API zu java.sql.*



> Erstmal wollte ich aus Performancegründen keine RS erst in ein Array oder sonstwas speichern und dann
> das Array später so auslesen wie es in die Datei geschrieben werden soll. Also den Zwischenschritt will ich mir sparen.
> Natürlich ist das die Notlösung wenn nichts geht.


das iterieren durch ein scrollbares resultset ist vermutlich viel langsamer als du vielleicht meinst (erfordert ja u.U Netzwerkzugriff)

lies alles in ein Array und bastel dir hinterher dann offline dein XML daraus (natürlich nur, wenn der Speicherbedarf im Rahmen bleibt)


----------



## rh-spirit (5. Jan 2006)

Wegen der Api: die kenne ich ja fast auswendig. 
Deswegen bin ich ja der Meinung: Auf RS vom Typ: "scroll" sind Methoden wie first,last,absolut(int) usw. anwendbar, da sich sich in beliebiege Richtung bewegen können. Der Defaulttyp Type_Forward_only kann das natürlich alles nicht. Bin ich da am Zeileende kann man quasi nichts mehr machen. 

Ich hatte nur danach gefragt, weil du sagtest das sich das mit first() nicht verträgt. 

Wegen der Performance:
Die Anwendung ist Serverseitig und arbeitet mit Zeitreihen.
Aber wenn hier keiner eine Lösung postet, dann werde ich mir das Temporäre Array eben bauen müssen.


----------



## Bleiglanz (5. Jan 2006)

schreib einfach TYPE_SCROLL_SENSITIVE und verwende executeQuery und schon funktioniert dein Code????


----------



## rh-spirit (5. Jan 2006)

Nein er funktiniert dann nicht. 
Die Prozedur erstellt Ergebnisse und gibt diese an einen Outputparameter aus.
Das ResultSet der Prozedur an sich wäre nur dann nur der eine Parameter.(Rs hat eine Spalte, eine Zeile). 

Der Outputparameter ist vom Typ Oracle.Cursor (Ergebniss ist eine Tabelle)

Darum mache ich ja auch das ganze mit cs.getObject(3,Typ) nach dem executeQuery().
Denn den Datentyp Resultset bzw. OracleCursor kann ich ja nicht aus einen Resultset herausrausziehen.
(würde dann wohl so in der Art aussehen: 
 >>>rs.getResultSet(Spalte1,Zeile1)


----------



## rh-spirit (5. Jan 2006)

Solangsam wird mir auch deutlich, daß das ganze nichts wird.

Die ResultSetTypangaben in prepareCall beziehen sich auf das zurückgelieferte Resultset der Prozedur. Meine Prozedur liefert aber nur ein Parameter zurück. Man könnte sich auf einfach vorstellen dieser Parameter sei ein String oder so.

ABER: Es ist vom Typ OracleCursor. Um diesen Cursor in Java zu verwenden bzw. anzuschauen, kann ich ihn in ein ResultSet "ClassCasten" / "ClassForwarden" (wie man auch immer das nennt). So, aber für dieses Objekt vom Typ ResultSet sind ja natürlich noch keine Angaben zum Typ (ob scroll oder forward) gemacht wurden.  Ich weiss auch nicht, wo ich das machen soll. ResultSet bietet selber keine Methoden im Nachhinein. Wenn dann sagt man dass ja dem Statement.

Hast du jetzt verstanden was ich meine?


----------



## Bleiglanz (5. Jan 2006)

ja verstanden schon aber nicht begriffen

also nochmal langsam

Ergebnis ist eine Tabelle = für Java ein Resultset, ganz normal?!

also einfach executeQuery machen und auf den Outparameter verzichten?

wozu willst du unbedingt den Oracle-Cursor haben? wie schaut denn die StoredProc aus


----------



## rh-spirit (5. Jan 2006)

Der Prozedurkopf sieht so aus:

 procedure XXX(a_int pls_integer, a_int pls_integer, a_cursor in out defs.t_fplzrnns_cursor);

Der zurückgelieferte Parameter ist also ein Cursor.
(Prozedur erstellt aus DB eine bestimmte Tabelle, ähnlich der Art und Weiße eines Views)

Ich übergebe also Werte, execute das callableStatement und kann meine Outputparameter anzeigen lassen.
(ResultSet = cs.excuteQuery() liefert nur ein Resultset von zurückgegebenen Paramtern zurück)
Natürlich kann ich den Parameter aus den Resultsetholen. Wenn es ein String ist kann ich ihn gleich mit rs.getString anzeigen lassen. Aber wie gesagt hier haben wir den Datentyp Cursor.
Also mache ich rs.getObject. ( oder ich kann gleich den CallableStatement x.ten OutParameter "fangen", wie in meinen Quellcode). 
Hier taucht die erste SChwierigkeit auf: Wie gehe ich mit dem Cursor in Java um? Bisweilen hatte ich nix gefunden, außer das man den Cursor auf die Klasse REsultset casten kann. ( ResultSet ergebnis = (ResultSet)rs.getObject().
Dann kann ich wie gewohnt mit den Methoden eines REsultSets mir den CursorInhalt ausgeben lassen.

Und hier liegt mein Problem: Dieses Resultset "ergebnis" ist scheinbar nur defaultmäßig "forward_only". Ich habe keine Ahnung wo ich das ändern kann. Die Typenangabe bei cs.prepareCall bezieht sich auf das REsultSet der Procedur (hier: auf das REsultSet rs quasi) Und das interesiiert ja mehr oder weniger nicht.

Bist du hinterhergekommen?


----------



## Bleiglanz (5. Jan 2006)

ja, und es geht nicht



> REF CURSORs returned from Stored Procedures lose scrollability
> 
> "An Oracle Stored Procedure returns a REF CURSOR to client Java code as a java.sql.ResultSet. The problem is that the scrollability of the ResultSet is lost - it becomes a TYPE_FORWARD_ONLY ResultSet."
> 
> ...


----------



## rh.spirit (5. Jan 2006)

Cool, wo hastn du das her?
Manchmal ist es echt eine Kunst, aus den Flut der Googleergebnisse das richtige herauszupicken, bzw. überhaupt gekonnt die richtige Anfrage zustellen.

Vielleicht weiss man das aber auch als "Experte".. demnach gehöre ich also nicht dazu .. lol

Allerdings ziemlich schade das das net geht.
Mittlerweile habe ich aber alles auf TemporäresArray umgestellt.

Trotzdem danke für die Lösung.. man lernt halt immer dazu


----------

