Pobieranie danych z tabeli zwróconej z funkcji

Odpowiedz Nowy wątek
2011-08-25 09:16
0

Witam wszystkich!
Mam problem z pobraniem zwracanej przez funkcję wartości z bazy danych. Zacznę od początku. Mam bazę danych w której mam przykładową funkcję:

CREATE OR REPLACE FUNCTION test()
  RETURNS INTEGER AS
$BODY$
DECLARE
    uid INTEGER;
BEGIN
    RETURN -3;
END;
$BODY$
  LANGUAGE plpgsql VOLATILE
  COST 100;

Wykonując zapytanie w bazie:

SELECT test()
 

Otrzymuję wynikową tabelę z wartością -3, takiej też wartości oczekiwałem.

Mam program którym chciałbym pobrać tę wartość. Fragment metody która to robi wygląda tak:

 
try {
    final PreparedStatement p = JDBCDAOFactory.getConnection().prepareStatement("SELECT test()");
    final ResultSet r = p.executeQuery();  
    if (r.next()) {
        int test = r.getInt(1);
            System.out.println(test);
    } else {
            System.out.println("Example");
             }
    } catch (SQLException e) {
            throw new DAOException(e);
    } catch (IOException e) {
            throw new DAOException(e);
    }

Niestety w tym przypadku otrzymuję zawsze 0.
Czy ktoś potrafi mi powiedzieć dlaczego tak się dzieje? Byłbym ogromnie wdzięczny za pomoc

Pozostało 580 znaków

2011-08-25 10:00
0

Nie wiem co jest źle ale wydaje mi się, że chodzi o wartość NULL w bazie jest ona domyślnie dla wartości int "rzutowana" na 0. Sprawdź jeszcze raz swój kod i tabelę.

  if (r.next()) {
        int test = r.getInt(1);
            System.out.println(test);
    } 

next() Moves the cursor down one row from its current position.
int getInt(String columnName)
Retrieves the value of the designated column in the current row of this ResultSet object as an int in the Java programming language.
isFirst()
Retrieves whether the cursor is on the first row of this ResultSet object.
Funkcja daje Ci wartość -3. W instrukcji warunkowej IF kursor jest ustawiony o jeden wiersz niżej. Potem pobierasz daną z kolumny o nazwie 1.

When a ResultSet.getXXX() method encounters a NULL in the database, it will convert it to a default value. For example, if NULL was encountered in a NUMBER field, ResultSet.getInt() will return 0. In order to determine whether or not the actual value is a NULL, wasNull() must be called. This method must be called immediately after the value is fetched from the result set.
http://download.oracle.com/ja[...]s/api/java/sql/ResultSet.html


Pozostało 580 znaków

2011-08-25 10:25
0

Dzięki za odpowiedź...
W takim razie jak pobrać tę wartość zwracaną przez funkcję?

spróbuj tak: SELECT test() AS wynik i po prostu potraktuj ta wartość tak jak kolumnę wynik - krwq 2011-08-25 12:20

Pozostało 580 znaków

2011-08-25 12:57
0
try {
            final PreparedStatement p = JDBCDAOFactory.getConnection().prepareStatement("SELECT jhrms_test() as wynik");
            final ResultSet r = p.executeQuery(); 
            if (r.next()) {
                int test = r.getInt("wynik");
                System.out.println("------------------> ID to: "+test);
                u.setId(test);
                return u;
            } else {
                System.out.println("------------------> ID to dupa");
                return null;
            }
        } catch (SQLException e) {
            throw new DAOException(e);
        } catch (IOException e) {
            throw new DAOException(e);
        }

Niestety to nie działa.
Jeżeli chodzi o funkcję w bazie jest ona nieco bardziej rozbudowana: jeżeli nie istnieje użytkownik to zwraca jego id i wtedy otrzymuję:
------------------> ID to: id_nowego_usera,
a wtedy kiedy użytkownik istnieje chciałbym przekazać -3 i wyświetlić JOptionPane, że user istnieje...

Ktoś ma jakiś inny pomysł czemu tak się dzieje?

Pozostało 580 znaków

2011-08-25 16:53
0
    -- PL/SQL procedure  
    CREATE OR REPLACE PROCEDURE get_resultset(  
          table_name IN VARCHAR2,  
          ret_cursor OUT SYS_REFCURSOR )  
    IS  
    BEGIN  
      OPEN ret_cursor FOR  
        'SELECT * FROM ' || table_name;  
    END;  
    /   
  public static void main(String[] args) throws SQLException, ClassNotFoundException {  
        OracleDataSource dataSource = new OracleDataSource();  
        dataSource.setURL("jdbc:oracle:thin:test/[email protected]:1521:irko");  
 
        Connection con = dataSource.getConnection();  
        OracleCallableStatement calStat = null;  
        ResultSet rs = null;  
 
        try {  
            calStat = (OracleCallableStatement) con.prepareCall("{call get_resultset( ?, ? )}");  
            calStat.setString(1, "scott.emp");  
            calStat.registerOutParameter(2, oracle.jdbc.OracleTypes.CURSOR);  
            calStat.execute();  
            rs = calStat.getCursor(2);  
 
            while (rs.next()) {  
                String name = rs.getString("ename");  
                String salary = rs.getString("sal");  
 
                System.out.format("%-10s / %10s\n", name, salary);  
            }  
        } finally {  
            try { rs.close(); } catch (Exception ex) {}  
            try { calStat.close(); } catch (Exception ex) {}  
            try { con.close(); } catch (Exception ex) {}  
        }  
    }

Tu masz kod, który znalazłem w sieci, może on Ci w czymś pomoże.


to dotyczy PROCEDURY, a nie FUNKCJI - Koziołek 2011-08-26 09:34

Pozostało 580 znaków

2011-08-26 09:51
0

na początek krótki kod:

Strign sql = "{ ? = call DELETE_INPUT_MESSAGE(?) }";
CallableStatement prepareCall = connection.prepareCall(sql);
prepareCall.registerOutParameter(1, OracleType.STYLE_INT);
prepareCall.setInt(2, 11);
boolean execute = prepareCall.execute();
Object ret = null;
//jeżeli false to zwrócona wartość nie może być rzutowana na ResultSet
if (execute) {
    ResultSet rs = (ResultSet) prepareCall.getObject(1);
    rs.next();
    ret = rs.getObject(1);
}else{
  ret = prepareCall.getObject(1);
}
 
// tu już w ret masz albo wartość zwróconą, albo liczbę (dla update/delete/insert) albo null

Przykład działa z Oracle.
linia 1. przygotowujesz zapytanie jako call;
linia 2. tworzysz CallableStatement na podstawie sqla
linia 3. rejestrujesz parametr wyjściowy.
linia 4. rejestrujesz wejście.
linia 5. wywołanie
linia 6. rezultat na null
linia 7. jeżeli wynik jest true to w pierwszym polu jest obiekt ResultSet. Jeżeli false to jest puste (no result) albo znajduje się int z liczbą dodanych/usuniętych/zaktualizowanych wierszy.

Reszta to już obróbka ResultSet.

// edit. Pamiętaj, że parametry funkcji mogą być IN/OUT i można zwrocić wynik przez parametr.

edytowany 1x, ostatnio: Koziołek, 2011-08-26 09:52

Pozostało 580 znaków

2011-08-26 10:10
0

Witam, dzięki za info...
Będę musiał nad tym posiedzieć, bo zerknąłem w logi i Middleware zwraca mi -3. Czyli taką wartość jak być powinna.
Powiem więcej (powinienem to napisać na samym początku), funkcja której ja używam jest rozbudowana o jeden warunek w którym jeżeli dany login nie istnieje w systemie to zwraca mi id nowego usera, jeżli login istnieje to zwraca mi -3.
Co ciekawe, jeżeli w programie dodam nowego usera to zmienna test przyjmuje wartosć nowego id, a jeżeli login istnieje to przyjmuje zawsze 0.
Kolokwialnie mówiąc pogrzebię w tym projekcie i dam znać jak mi poszło!

Dzięki wielkie za cenne informacje!

Pozostało 580 znaków

2011-08-26 11:38
0

Panowie, więc napisałem sobie przykładową klasę gdzieś poza projektem i rzeczywiście wasz kod działa dobrze. Co ciekawe, mój też działa dobrze, więc w czym jest problem.
Zacząłem szukać głębiej, zerknąłem na klasę do komunikacji która implementuje interfejs result set i napisana przez poprzedniego programistę wygląda następująco:

    public int getInt(int columnIndex) throws SQLException {
        final String value = getIth(columnIndex);
        if (value != null) {
            return (value.matches("[0-9]+") ? Integer.parseInt(value) : 0);
        } else {
            wasNull = true;
            return 0;
        }
    }
 

Powinienem od razu w to zerknąć, na drugi raz od tego zacznę.
Dzięki za pomoc mimo wszystko.

Pozostało 580 znaków

Odpowiedz
Liczba odpowiedzi na stronę

1 użytkowników online, w tym zalogowanych: 0, gości: 1, botów: 0