Avatar billede martinm Nybegynder
15. august 2003 - 11:56 Der er 11 kommentarer og
1 løsning

CallableStatement mod MS SQL Server 2000

Hej,

Jeg har installeret en MS SQL Server 2000 lokalt på min maskine og har oprettet tabeller og stored procedures.

Men har følgende problem med denne kode:

  public ResultSet testStoredProcedure() {
        CallableStatement cs = null;
        ResultSet rs = null;
        String command = "{?=call dbo.CustOrderHist (?) }";
        try {
            cs = con.prepareCall( command );
            cs.setString( 1, "ANTON" );
            cs.registerOutParameter( 2, Types.VARCHAR );
            cs.registerOutParameter( 3, Types.VARCHAR );
            rs= cs.executeQuery();
        }
        catch ( SQLException e ) {
            e.printStackTrace();  //To change body of catch statement use Options | File Templates.
        }
        return rs;
    }

Jeg får en exception:

java.lang.ArrayIndexOutOfBoundsException
    at com.microsoft.jdbc.base.BaseParameters.set(Unknown Source)
    at com.microsoft.jdbc.base.BaseCallableStatement.registerOutParameter(Unknown Source)
    at SQLParserTest.testStoredProcedure(SQLParserTest.java:127)
    at SQLParserTest.main(SQLParserTest.java:108)
Exception in thread "main" Process terminated with exit code 1

Proceduren returnerer to rækker og tager en streng som input.

Hvorfor denne exception?
Avatar billede arne_v Ekspert
15. august 2003 - 12:01 #1
Du angiver en SQL sætning med 1 argument:

String command = "{?=call dbo.CustOrderHist (?) }";

og så sætter du typen for parameter 2 og 3.

Det skal gå galt !
Avatar billede arne_v Ekspert
15. august 2003 - 12:02 #2
En out parameter er et argument til SP som returnerer en værdi.

Et result set som returneres fra en SP er noget helt andet.
Avatar billede arne_v Ekspert
15. august 2003 - 12:03 #3
Så mit gæt er at du skal droppe de 2 registerOutParameter
og bare fiske data ud fra ResultSet.
Avatar billede martinm Nybegynder
15. august 2003 - 12:07 #4
Hvis jeg ændrer det til:
  public ResultSet testStoredProcedure() {
        CallableStatement cs = null;
        ResultSet rs = null;
        String command = "{call dbo.CustOrderHist (?) }";
        try {
            cs = con.prepareCall( command );
            cs.setString( 1, "ANTON" );
      //      cs.registerOutParameter( 2, Types.VARCHAR );
      //      cs.registerOutParameter( 3, Types.VARCHAR );
          rs= cs.executeQuery();
        }
        catch ( SQLException e ) {
            e.printStackTrace();  //To change body of catch statement use Options | File Templates.
        }
        return rs;
    }
Virker det.
Læg mærke til, at ? foran =call er væk, men burde ? ikke være med, nu når proceduren returnerer noget?
Avatar billede arne_v Ekspert
15. august 2003 - 12:10 #5
? =

er SP'ens return value.

En SP kan både:
  - have out parametre
  - returnere en værdi
  - producere result sets

Den ? = skal du nok have defineret en type for med cs.registerOutParameter
på index 0.

[ikke helt sikker - det er lang tid siden jeg har leget med SP fra Java]
Avatar billede martinm Nybegynder
15. august 2003 - 12:21 #6
Jeg er ikke interesseret i at få svar tilbage i et resultset. Har læst lidt på http://www.geocities.com/joao_kramer/documents/doc_20000919_1.htm
og det ser ud til, at der ikke skal ?= med ved procedures??
Jeg har prøvet med cs.registerOutParameter og det giver mig en ArrayOutOf..... exception.
Avatar billede arne_v Ekspert
15. august 2003 - 12:26 #7
Hvis du skal hente retur værdien skal skal der ? = på.

Men det er muligt at typen af retur værdien ikke skal registereres
men at du bare kan get'e den efter execute.
Avatar billede arne_v Ekspert
15. august 2003 - 12:27 #8
Hvis du skal have mere en en værdi tilbage skal du vel returnere et resultset !?

(det er da også det din test metode gør)
Avatar billede martinm Nybegynder
15. august 2003 - 12:38 #9
Ja, min testmetode gør det, men det var blot for at lege med det. Der findes en metode, der hedder getString( int i ), som man kan kalde på sit CallableStatement, og derved trække info. ud af det. Det skal bruges til, at brugeren får præsenteres response som et XML doc, der skal have en bestemt syntaks.
Avatar billede arne_v Ekspert
15. august 2003 - 12:43 #10
Ja.

Men getString(3) henter det tredie output argument og getString(0) henter
en string retur værdi.

Men så vidt jeg ved kan man ikke returnere flere rækker på den måde.

For at gøre det skal du returnere et eller flere ResultSet.
Avatar billede arne_v Ekspert
15. august 2003 - 21:46 #11
Jeg prøvede lige at lave et lille eksempel.

Spørgsmåls tegnene nummereres fra 1 af uanset om det først er result.

Desværre Sybase fordi SQLServer og NT Security var ikke lige i humør til at
lege med JDBC idag.

Men det er stort set det samme.

Stored procedure:

CREATE PROCEDURE TEST_MULTIOUT
@inarg INTEGER,
@outarg INTEGER OUTPUT
AS
SELECT @outarg = 123
SELECT * FROM T1
SELECT * FROM T1
RETURN -@inarg

så vi har et in argument og et out argument, vi returnerer en
result værdi og vi returnerer 2 result sets. Så der er lidt af det hele !

import java.sql.CallableStatement;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.Types;

public class UseSP {
    public static void main(String[] args) throws Exception {
        Class.forName("com.sybase.jdbc2.jdbc.SybDriver");
        Connection con = DriverManager.getConnection("jdbc:sybase:Tds:arnepc2:5000", "sa", "");
        con.setCatalog("Test");
        CallableStatement cstmt = con.prepareCall("{? = CALL TEST_MULTIOUT(?,?)}");
        cstmt.registerOutParameter(1, Types.INTEGER);
        cstmt.setInt(2, 5);
        cstmt.registerOutParameter(3, Types.INTEGER);
        cstmt.execute();
        while(cstmt.getMoreResults()) {
            ResultSet rs = cstmt.getResultSet();
            while(rs.next()) {
                System.out.println(rs.getInt(1) + " " + rs.getString(2));
            }
        }
        System.out.println("return value = " + cstmt.getInt(1));
        System.out.println("out parameter = " + cstmt.getInt(3));
        cstmt.close();
        con.close();
    }
}

output:

1 A
2 BB
3 CCC
1 A
2 BB
3 CCC
return value = -5
out parameter = 123

og så er det bare at vælge hvad du har brug for !
Avatar billede martinm Nybegynder
19. august 2003 - 18:03 #12
Glimrende! Lige det der fik de sidste brikker til at falde på plads!
Avatar billede Ny bruger Nybegynder

Din løsning...

Tilladte BB-code-tags: [b]fed[/b] [i]kursiv[/i] [u]understreget[/u] Web- og emailadresser omdannes automatisk til links. Der sættes "nofollow" på alle links.

Loading billede Opret Preview
Kategori
Kurser inden for grundlæggende programmering

Log ind eller opret profil

Hov!

For at kunne deltage på Computerworld Eksperten skal du være logget ind.

Det er heldigvis nemt at oprette en bruger: Det tager to minutter og du kan vælge at bruge enten e-mail, Facebook eller Google som login.

Du kan også logge ind via nedenstående tjenester