# Keine ResultSet bei if in StoredProcedure



## K-Man (8. Nov 2010)

Hallo zusammen
Ich habe ein seltsames Problem. Ich habe auf meinem SQLServer 2005 eine StoredPrecedure. Darin einen if-Block und 2 select-Befehle. Je nachdem, was man als Parameter übergibt (1 oder 2), wird eine der beiden select ausgeführt (Einfaches select *).
Wenn ich die Methode direkt im SQL Server teste, dann bekomm ich eine schöne Tabelle zurück, sowohl mit dem Parameter 1 und 2. Wenn ich die Methode aber über Java aufrufe, dann bekomme ich die Fehlermeldung "java.sql.SQLException: The executeQuery method must return a result set"

Das Seltsame. Sobald ich die if-Blöcke in der StoreProcedure entferne, geht alles ohne Probleme. Aber wenn ich über einen if-Block den Select-Befehl steuere, kommt diese Fehlermeldung. Was muss ich machen, damit ich die Methode über Java aufrufen kann?

Schon mal vielen Dank
Stefan


----------



## Gast2 (8. Nov 2010)

Wie wäre es mit etwas Code? Also wie rufst du die StoredProcedure auf und wie sieht diese genau aus?


----------



## K-Man (9. Nov 2010)

Also die StoredProcedure sieht so aus:

```
PROCEDURE [dbo].[spCheck]
	@OMS		int,
	@Oligos		xml,
	@ok			int output,
	@message	varchar(100) output
AS
BEGIN
	SET NOCOUNT ON;
begin try
DECLARE @idoc int

EXEC sp_xml_preparedocument @idoc OUTPUT, @Oligos

DECLARE @OligoTable TABLE (Anchor char(5), Volume float) 

insert into @OligoTable
SELECT *
  FROM OPENXML(@idoc, '/Oligos/Oligo',2)
  WITH (Anchor      char(5),
        Volume			float)  
                

if @OMS = 1
begin       
SELECT * FROM OMS1
 INNER JOIN @OligoTable p ON OMS1.Anchor = p.Anchor where OMS1.Volume < p.Volume
 end
else if @OMS = 2
begin
SELECT * FROM OMS2
INNER JOIN @OligoTable p ON OMS2.Anchor = p.Anchor where OMS2.Volume < p.Volume
end
		set @ok = 1
		set @message = 'Oligocheck erfolgreich'
		return
	end try
	begin catch
		set @ok = 0
		set @message = 'Fehler bei Oligocheck.'
		return
	end catch
END
```

Die Prozedur rufe ich so auf.

```
CallableStatement pre = con.prepareCall("{call spCheck(?,?,?,?)}");
pre.setInt(1, 1);
pre.setString(2, "<Oligos><Oligo><Anchor>A0001</Anchor><Volume>151.0</Volume></Oligo><Oligo><Anchor>A1965</Anchor><Volume>101.0</Volume></Oligo></Oligos>");
pre.registerOutParameter(3, java.sql.Types.INTEGER);
pre.registerOutParameter(4, java.sql.Types.CHAR);
ResultSet rs = pre.executeQuery();
```


Wie gesagt. Da kommt die Fehlermeldung. Wenn ich die IF-Blöcke aus der StoredProcedure rausnehme und nur eine der beiden select aufrufe, dann geht alles Wunderbar. Nur mit den Blöcken nicht mehr.

Vielen Dank
Stefan


----------



## K-Man (9. Nov 2010)

Die Frage ist wohl auch, warum gibt eine StoredProcedure keine ResultSet zurück, wenn der select in einer if-Schleife ist? Kann das das Problem sein? Und wenn ja, wie kann ich es umgehen?


----------



## SlaterB (9. Nov 2010)

if-schleife.de

baue ein finales else ein oder logge als aller erstes, was denn @OMS für einen Wert hat (bestimmt 0), oder schreibe den Wert in deine DB-Tabelle

> Sobald ich die if-Blöcke in der StoreProcedure entferne, geht alles ohne Probleme. 

bedeutet also nicht, dass der gesamte Code optional ist, sondern dass du dann immer noch irgendein SELECT drin hast?
immer genau die Details beachten..


----------



## K-Man (9. Nov 2010)

Du hast recht. Ich hab bei der 2. If-Abfrage das If weggelassen und nur ein else geschrieben. Schon klappt es.
Man braucht also immer ein finales else MIT einem select, damit die StoredProcedure eine ResultSet liefert? Die Frage ist dann natürlich, schaffe ich es auch ohne? Ich will halt, dass die select nur bei einer 1 oder 2 durchgeführt werden.

Aber schon vielen Dank, bin schon etwas weiter mit meinem Problem


----------



## SlaterB (9. Nov 2010)

ich weiß wenig von StoredPrecedures, nur mit dem else ist es kaum getan, es sei denn die Unterscheidung 1/2 funktioniert jetzt?
die ersten Probleme klangen ja eher danach als wenn der Parameter 1 gar nicht ankam, deswegen keines der ifs durchlaufen wurde,

Java selber kann die Prozedure kaum analysieren, das Problem muss ja in der DB gewesen sein, dass wirklich kein ResultSet zurück kam, eben weil anscheinend der Parameter falsch war,

vielleicht läßt sich die Fehlermeldung an sich umgehen, wenn du aus Java executeUpdate() statt executeQuery() aufrufst,
dann ist es für Java ok, dass kein ResultSet zurückkommt,
aber das löst ja das Problem nicht, dass die Stored Precedure was anderes macht als du willst weil der Parameter vielleicht nicht stimmt


----------



## K-Man (9. Nov 2010)

Ich wollte es jetzt so regeln, dass ich ein zusätzliches else einbaue, falls weder 1 noch 2 gewählt wurden.

```
if @OMS=1
begin       
SELECT * FROM OMS1
 INNER JOIN @OligoTable p ON OMS1.Anchor = p.Anchor where OMS1.Volume < p.Volume
 		set @ok = 1
		set @message = 'Oligocheck successful'
		return
 end
else if @OMS=2
begin
SELECT * FROM OMS2
INNER JOIN @OligoTable p ON OMS2.Anchor = p.Anchor where OMS2.Volume < p.Volume
		set @ok = 1
		set @message = 'Oligocheck successful'
		return
end
else
begin
		set @ok = 0
		set @message = 'Incorrect database OMS'+char(@OMS)
end
```
Das komische ist. Er geht immer in den finalen else-Block. Obwohl @OMS = 1 ist. Ist an dem IF-Block was falsch? Wenn ich den letzten else-Block weglasse und dafür beim 1. else das if @OMS=2 weglasse. Also eine ganz normale if-else. Dann geht es.


----------



## SlaterB (9. Nov 2010)

-->


SlaterB hat gesagt.:


> logge als aller erstes, was denn @OMS für einen Wert hat (bestimmt 0), oder schreibe den Wert in deine DB-Tabelle


<--

was der Grund dafür ist kann ich nicht sagen, werden andere Parameter von Java korrekt übertragen?
Index-Zählung beginnend bei 0/1 sollte eigentlich kein Problem sein, dennnoch großflächig testen:

10 Input-Parameter, 5x int, 5x String,
Übergabe 1, 2, 3, 4, 5, "a", "b", "c", "d", "e",
alle 10 Werte loggen/ in eine DB-Tabelle schreiben

was kommt an auf welcher Position, was fehlt? wenn nur String oder XML oder was auch immer funktioniert und anderes nicht, dann eben vorerst nur String verwenden,
genaues kann ich dazu aber nicht sagen, 

aus der allgemeinen-Weisheiten-Kiste:
bei allem was man (strukturell neues) tut erst funktionierende Beispiele im Internet (StoredProcedute + Java-Aufruf + int-Parameter) suchen,
wenn diese nicht gehen dann hat man einen sinnvollen Vergleich für andere (Forum),
wenn man keine Beispiele hat kann man nur raten wie es richtig funktionieren könnte, sich aber nie sicher sein, ob das überhaupt möglich ist


----------



## K-Man (9. Nov 2010)

Die Parameter werden richtig übergeben. Wenn ich mit @OMS ausgeben lasse, dann sagt mir auch SQL, dass es 1 ist. Trotzdem geht er in meinem Block nicht in das if mit @OMS=1, sondern in den finalen else-Block


----------



## SlaterB (9. Nov 2010)

da bist du dir sicher? 
> char(@OMS)
wie ich jetzt sehe, ist nicht irgendwas komisches was aus ASCII-Code 49 den Char '1' macht oder ähnlich schräges?
ASCII-Tabelle

ein if auf 49 bzw. alle Zahlen von 0-1000 wäre ein kleiner Strohhalm, um das festzustellen
(den SQL-Code dazu mit Copy/Paste oder Java-Schleife erstellen),
oder zielführender: mit größer/kleiner-Vergleichen den Wertebereich einschränken, so vielleicht den tatsächlich interpretierten Wert finden


----------



## K-Man (9. Nov 2010)

Du hattest recht. Der Fehler lag wirklich an der Übergabe. Java hat 49 und nicht 1 übergeben. Vielen Dank.
Jetzt muss ich nur noch schauen, dass ich die Blöcke so hinbekomme, dass es wie anfangs gedacht funktioniert.

Danke aber schon mal.


----------



## K-Man (9. Nov 2010)

Hat sich jetzt alles erledigt. Klapp wunderbar. Vielen Dank


----------



## SlaterB (9. Nov 2010)

verrückt


----------



## K-Man (9. Nov 2010)

Das war ganz komisch. Ich hab nämlich aus einem String den int auslesen lassen. Hab ich den String bei Java ausgegeben, dann hat er mir 1 ausgegeben. Aber beim Casten in int hat er mir aber aus 1 die 49 gemacht.
char b = charAt(x) => 1
Sysout auch 1
Integer.parseInt(b) => 49


----------



## SlaterB (9. Nov 2010)

nun, das ist weniger verrückt, charAt() aus einem String ist was ganz anderes als
> CallableStatement pre = con.prepareCall("{call spCheck(?,?,?,?)}");
> pre.setInt(1, 1);
wie am Anfang geschrieben

ein String enthält den char '1', ein Zahlwert 49, ob System.out.println den nun als Zahl oder char ausgibt..

char c = ..;
System.out.println((int) c);


----------



## K-Man (9. Nov 2010)

Irgendwie hat bei mir aber pre.setInt(1, 1); auch nicht wirklich geklappt und er ist nicht in den if-block rein. Ich weiß jetzt auch nicht warum, oder was falsch war. Jedenfalls hab ich es Dank deiner Hilfe lösen können und bin dir sehr dankbar


----------

