2016-03-30 3 views
1

Ich möchte Bereich oder Zeilen aus PostgreSQL-Tabelle auswählen. Ich habe versucht, diesen Code:Wählen Sie einen Bereich von Zeilen aus PostgreSQL-Tabelle

public List<CustomersObj> list(int firstRow, int rowCount, String sortField, boolean sortAscending) throws SQLException 
     { 

      String SqlStatement = null; 

      if (ds == null) 
      { 
       throw new SQLException(); 
      } 

      Connection conn = ds.getConnection(); 
      if (conn == null) 
      { 
       throw new SQLException(); 
      } 

      int countrow = firstRow + rowCount; 
      String sortDirection = sortAscending ? "ASC" : "DESC"; 

// Oracle 
    //  SqlStatement = "SELECT A.* " 
    //   + " FROM (SELECT B.*, ROWNUM RN " 
    //   + " FROM (SELECT Y.COMPONENTSTATSID, Y.NAME, Y.SERIALNUMBER, Y.WEIGHTKG, Y.ZONECAGE, Y.POWERWATT, Y.MANIFACTURECOMPANY, Y.UFORM, " 
    //   + " Y.STATUS, Y.LOCATION, Y.HEATEMISIONSBTU, Y.PRODUCTIONENVIRONMENT, Y.STANDARTLIFETIME, Y.OPERATINGHAMIDITYRANGE, " 
    //   + " Y.OPERATINGSYSTEM, Y.DATEDEPLOYED, Y.INTERFACETYPE, Y.TYPE, Y.COOLINGCAPACITYBTU, Y.DATEADDED, Y.DESCRIPTION " 
    //   + " FROM COMPONENTWEIGHT X, COMPONENTSTATS Y WHERE X.COMPONENTSTATSID = Y.COMPONENTSTATSID AND Y.COMPONENTTYPEID = 3300 " 
    //   + " ORDER BY %S %S) B " 
    //   + " WHERE ROWNUM <= ?) A " 
    //   + " WHERE RN > ?"; 
// postgresql 
      SqlStatement = "SELECT * FROM CUSTOMERS ORDER BY %S %S offset ? limit ? "; 

      String sql = String.format(SqlStatement, sortField, sortDirection); 

      PreparedStatement ps = null; 
      ResultSet resultSet = null; 
      List<CustomersObj> resultList = new ArrayList<>(); 

      try 
      { 
       conn.setAutoCommit(false); 
       boolean committed = false; 

       ps = conn.prepareStatement(sql); 
       ps.setInt(1, countrow); 
       ps.setInt(2, firstRow); 

       resultSet = ps.executeQuery(); 
       resultList = ProcessorArrayList(resultSet); 

       conn.commit(); 
       committed = true; 

      } 
      finally 
      { 
       ps.close(); 
       conn.close(); 
      } 

      return resultList; 
     } 

Aber wenn ich die Paginierung verwende ich unterschiedliche Anzahl oder Zeilen erhalten. Wenn ich die Abfrage von Oracle verwende, funktioniert es gut. Aber wenn ich die Abfrage von PostgreSQL verwenden möchte, bekomme ich auf jeder paginierten Seite ein unterschiedliches Ergebnis. Kannst du ein Ergebnis geben, wie ich das beheben kann?

Antwort

1

Die Parameter OFFSET und LIMIT in PostgreSQL sind im documentation wie beschrieben:

The LIMIT clause consists of two independent sub-clauses:

LIMIT { count | ALL } OFFSET start 

count specifies the maximum number of rows to return, while start specifies the number of rows to skip before starting to return rows. When both are specified, start rows are skipped before starting to count the count rows to be returned.

Dies bedeutet, dass diese Zeile:

int countrow = firstRow + rowCount; 

wahrscheinlich falsch ist. Der Parameter, der an LIMIT übergeben wird, ist die tatsächliche Zeilenanzahl, nicht die nächste Zeile.

Die zweite wichtige Sache ist, dass in Ihrer Erklärung, das Fragezeichen für den Offset ist ersten, und das Fragezeichen für die Grenze ist zweiten. Aber Sie die Parameter wie folgt aus:

  ps.setInt(1, countrow); 
      ps.setInt(2, firstRow); 

Die erste ist die (sehr schlecht) „count“, und das zweite ist die „Offset“. Dies sollte umgekehrt sein.

Schließlich ist der OFFSET Wert die Anzahl der Zeilen zu überspringen, nicht die Nummer der ersten Zeile. Wenn Sie also firstRow für die erste Seite mit 1 erwarten, sollten Sie firstRow - 1 als Offset verwenden.

Also, sollten Sie die setInt Linien mit ersetzen:

  ps.setInt(1, firstRow - 1); 
      ps.setInt(2, rowCount); 
+0

ich org.postgresql.util.PSQLException: ERROR: OFFSET nicht negativ sein muss –

+0

@Peter also überprüfen, ob die 'firstRow' wirklich von 1 startet Wenn es bei Null beginnt, brauchen Sie nicht die subtrahieren 1. – RealSkeptic

+0

ist es 1. Aus irgendeinem Grund funktioniert es nicht richtig. Next-Button und Back funktionieren nicht richtig. –

0

die zusammen Lassen Sie stellen die wichtigsten Sätze

int countrow = firstRow + rowCount; 
SqlStatement = "SELECT * FROM CUSTOMERS ORDER BY %S %S offset ? limit ? "; 
ps = conn.prepareStatement(sql); 
ps.setInt(1, countrow); 
ps.setInt(2, firstRow); 

Das Argument LIMIT in PostgreSQL ist für folgende Einzelheiten enthält die maximale Anzahl der Zeilen abgerufen werden , die Anzahl der Zeilen pro Seite.

Das Argument OFFSET bestimmt, welche die erste Zeile ist, die abgerufen werden soll.

Angenommen, Sie möchten 50 Zeilen pro Seite.

To retrieve the first page -> `LIMIT 50 OFFSET 0` [rows 0 to 49] 

    To retrieve the second page -> `LIMIT 50 OFFSET 50` [rows 50 to 99] 

    ... 

    To retrieve the nth page -> `LIMIT 50 OFFSET (n - 1)*50` 

Wenn Ihr rowCount die Gesamtanzahl der Zeilen enthält abzurufen, muss auf LIMIT und Ihre firstRow zu OFFSET zugeordnet werden. Und können Sie Variable countrow verwerfen, wenn Sie PostgreSQL verwenden.

UPDATE: Just ändern

ps.setInt(1, firstRow); // Assign firstRow to OFFSET 
ps.setInt(2, rowCount); // Assign rowCount to LIMIT 

Ich habe Angst, dass ich mit RealSkeptic zustimmen: - 1 als Offset "wenn Sie firstrow für die erste Seite erwarten 1 zu sein, sollten Sie firstrow verwenden ." Wenn Sie eine negative Zahl als erstes Argument zu erhalten, der einzige Grund ist, weil Ihre 0 als Startzeile verwendet.

Es macht Sinn, wenn man bedenkt, dass erste Zeile in Oracle hat ROWNUM = 1

.

https://docs.oracle.com/cd/B14117_01/server.101/b10759/pseudocolumns008.htm

Ihre Anfrage gültig für Oracle steht, dass RN> 0 für die erste Seite.

erste Reihe in PostgreSQL mit einem OFFSET = 0 erhalten wird, so ...

YES -> ps.setInt(1, firstRow); 
    NO -> ps.setInt(1, firstRow - 1); 
+0

Können Sie mir ein Beispiel geben, wie ich den Code umgestalten muss, weil es nicht sehr klar ist? –

+0

@PeterPenzov Ich habe aktualisiert. Hoffnung ist klarer – RubioRic

+0

Ich benutze diesen Code http://balusc.omnifaces.org/2008/10/effective-datatable-paging-and-sorting.html Sieht aus wie das Problem ist die Abfrage. Es ist für diese Abfrage konzipiert: "SELECT-ID, Name, Wert von MyData ORDER BY% s% s LIMIT?,?"; Im Moment funktioniert der nächste Button nicht gut. Nach der zweiten Seite funktioniert es nicht. –