# Fehler bei mySQL Query



## jothemac (17. Sep 2012)

Hallo,

wenn ich folgende mysql query ausführe bekomme ich folgenden Fehler:

```
SELECT OPENCHANGEDAYBEFOREPERCENT FROM APP.FB WHERE DAY=2 LIMIT 0,10
java.sql.SQLSyntaxErrorException: Syntaxfehler: Encountered "LIMIT" at line 1, column 59.
```

So wie es aussieht liegt es am LIMIT befehl, ich habe im inet nachgeschaut da wird aber gesagt das die syntax so aussehen soll. 

joni8a


----------



## Evil-Devil (17. Sep 2012)

Versucht du einen FB SQL Querie an Facebook abzusetzen? Ich bin mir nicht sicher, aber unterstützen die überhaupt Limit?

Sonst rein von der Sytax her hast du da schon gültiges MySQL. Es empfiehlt sich allerdings nur Limit 10 zu sagen und fürs Paging mit alternativen Methoden zu arbeiten.


----------



## jothemac (17. Sep 2012)

Hallo,

ne ich versuche nicht an FaceBook zu senden 
Wenn ich nur mit limit arbeite bekomme ich den selben Fehler:

```
SELECT OPENCHANGEDAYBEFOREPERCENT FROM APP.FB LIMIT 10
java.sql.SQLSyntaxErrorException: Syntaxfehler: Encountered "10" at line 1, column 53.
```


----------



## gp (17. Sep 2012)

Und du  bist sicher, dass es eine MySql-Datenbank ist? Wie sieht dein Java denn genau aus? Grundsätzlich gehört ein ";" ans Ende jeder Anfrage. Geht es denn ohne Limit? Nur mal, um das Problem einzukreisen


----------



## jothemac (17. Sep 2012)

Ohne Limit geht es, der code sieht so ausJa bin mir sicher das es MYSQL ist  )

```
public void createNewQuery() throws SQLException
    {
        numberOfDays = Integer.parseInt(numberOfEntriesTf.getText());
        String query = "SELECT "+askedForVariable+" FROM APP."+stock.StockName.toUpperCase();
        
        if(day > 1)
        {
            query = query+ " WHERE DAY="+day;
        }
        if(numberOfDays > 0)
        {
            query = query + " LIMIT "+numberOfDays;
        }
        
        ResultSet rs = stock.askForData(query);
        while(rs.next())
        {
            System.out.println(rs.getString(1));
        }
    }
```


Hier ist der code der die anfrage sendet:

```
public ResultSet askForData(String valueQuery)
    {
        PreparedStatement ps = null;
        
        
        
        
        System.out.println("ASKED QUERY:"+valueQuery);
        
        ResultSet rs = null;
        try
        {
            ps = dbHelper.conn.prepareStatement(valueQuery,
                    ResultSet.TYPE_SCROLL_SENSITIVE, ResultSet.CONCUR_READ_ONLY);
            rs = ps.executeQuery();
        }
        catch(SQLException ex)
        {
            ex.printStackTrace();
        }
        
        return rs;
    }
```


----------



## gp (17. Sep 2012)

Ich könnte mir vorstellen, dass sich LIMIT nicht mit ResultSet.TYPE_SCROLL_SENSITIVE verträgt - versuch doch mal prepareStatement nur mit dem ersten Parameter.

Ich verstehe auch den Sinn der Kombination nicht: du willst READ-ONLY lesen aber ein veränderbares Ergebnis? TYPE_SCROLL_INSENSITIVE würde ich eher verstehen. Ich selbst verwende so was gar nicht, daher sind das alles mehr Vermutungen, mehr dazu hier.


----------



## Bernd Hohmann (17. Sep 2012)

Ich befürchte, dass Dein Problem im TYPE_SCROLL_SENSITIVE  |  CONCUR_READ_ONLY liegt weil es der Tabellentyp dahinter in MySQL nicht mit LIMIT kann.

Ist das MyISAM oder InnoDB? Du brauchst vermutlich InnoDB weil stabile Cursoren nur mit transaktionssicheren Engines gehen.

Bernd


----------



## Bernd Hohmann (17. Sep 2012)

gp hat gesagt.:


> Ich verstehe auch den Sinn der Kombination nicht: du willst READ-ONLY lesen aber ein veränderbares Ergebnis? TYPE_SCROLL_INSENSITIVE würde ich eher verstehen. Ich selbst verwende so was gar nicht, daher sind das alles mehr Vermutungen, mehr dazu hier.



Ich hatte viel mit IBM DB2 gemacht, die DB konnte ordentliche Transaktionen und hatte Cursors. Wenn ich mein Restwissen zusammenkratze passiert da folgendes:

1) Erst wird die Query durchgeführt und über das Ergebnis ein Cursor aufgemacht (also so ne Art ArrayList) den man vorwärts und rückwärts durchscrollen kann.

2) Man kann an jeder beliebigen Stelle die im Cursor enthaltenen Datensätze ändern

3) In der DB werden die Änderungen erst bei Transaktionsende für andere User sichtbar

4) Andere User können bis zum Transaktionsende in der Zwischenzeit keine Datensätze ändern, die im Cursor enthalten sind

Was dann wirklich passiert hängt stark von der DB ab - manche können weniger, manche mehr, manchmal ist es unmöglich die diversen Cursor-Stability-Modes korrekt auf die Vorgaben von JDBC umzusetzen (so war es jedenfalls mal).

Bernd


----------



## Lumaraf (17. Sep 2012)

Bist du dir da auch ganz sicher das du MySQL verwendest? Normalerweise müßte die Meldung bei einem Syntaxfehler so in der Art aussehen: [c]You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '' at line 1[/c]

Poste am besten mal wie du dich mit der Datenbank verbindest. Speziell Die JDBC-Url die an DriverManager.getConnection() übergeben wird wäre besonders hilfreich.


----------



## SlaterB (17. Sep 2012)

Derby/JavaDB scheint es zu sein,

FETCH/OFFSET soll es da geben, wird wohl zu finden sein


----------



## jothemac (18. Sep 2012)

Ok, sry erstmal. Ich dachte immer Java DB = MySQL, aber wohl weit gefehlt, danke für die aufklärung. Um das problem zu lösen schaut man nur auf diese website:
https://blogs.oracle.com/kah/entry/derby_10_5_preview_fetch


----------



## jothemac (18. Sep 2012)

Jaa ich noch mal, FETCH FIRST gibt mir immer x anzahl row´s wieder. Aber ich möchte das nur die ersten x rows durschaut werden. Heisst wenn ich 100 einträge habe, dann möchte ich nur die ersten 10 anschauen. Jetzt habe ich etwas geschaut und das TOP query gefunden, aber anscheinend funktioniert das query nicht: http://www.java-forum.org/datenbankprogrammierung/119643-select-top-statement-geht.html
Meine frage kann man mein ziel dennoch irgendwie erreichen, mit einem Query?


----------



## SlaterB (18. Sep 2012)

nochmal langsam, was macht FETCH und was möchtest du? 

> Heisst wenn ich 100 einträge habe, dann möchte ich nur die ersten 10 anschauen.

klingt genau nach den Beispielen im Link,  FETCH FIRST 3 ROWS ONLY liefert John, Anne und Sue von wer weiß wie vielen Personen

es ist mir zumindest nicht klar was du anderes haben willst, vielleicht hilft ein Beispiel,
eine Tabelle mit 10 statt 100 Daten, ein FETCH mit 3, was wird geliefert mit genau welcher Query, was willst du stattdessen haben?


----------



## jothemac (18. Sep 2012)

Beispiel Datenbank(APP.BD):
Tag | Sonnig | Temperatur
_______________________
Montag | JA  | 20
_______________________
Dienstag | NEIN  | 15
_______________________
Mittwoch | NEIN  | 13
_______________________
Donnerstag | JA  | 22
_______________________
Freitag | JA  | 25
_______________________
Montag | NEIN  | 21

Beispiel Query mit FETCH: 
SELECT Temperatur FROM APP.BD WHERE DAY=Montag FETCH FIRST 2 ROWS ONLY

Query liefert mir dann zurück:
20 und 21(Für die Temperatur der beiden Montage)

Ich möchte aber, dass das Programm bzw. das query sich nur auf die ersten beiden Einträge bezieht. Heisst er soll sich nur die ersten beiden einträge anschauen.
Das Query sollte mir also nur 20 zurück geben. Also nur für den einen Montag, denn unter den ersten beiden einträgen befindet sich nur ein Montag.


----------



## SlaterB (18. Sep 2012)

ohne Sortierung könnten theoretisch zwei beliebige Werte ausgewählt werden,
das als grundsätzlicher Hinweis, in deinem Beispiel vielleicht aus Einfachheit nicht dabei

der Logik nach ist die normale Lösung glaube ich Verschachtelung:

```
SELECT Temperatur FROM (SELECT * FROM APP.BD FETCH FIRST 2 ROWS ONLY) WHERE DAY=Montag
```
allerdings habe ich leicht in Erinnerung, dass es fragwürdig ist, ob das funktioniert,
mit ROWNUM in Oracle verschiebt sich die Einschränkung trotz Verschachtelung nach außen und ähnlich komisches,

aber einfach mal hoffen:
wenn dir dieser Weg praktikabel erscheint, funktionierts auch?


----------



## jothemac (18. Sep 2012)

QUERY:SELECT OPENCHANGEDAYBEFORENUMBER FROM(SELECT * FROM APP.FB FETCH FIRST 2 ROWS ONLY) WHERE DAY = 2
SCHWERWIEGEND: null
java.sql.SQLSyntaxErrorException: Syntaxfehler: Encountered "WHERE" at line 1, column 85.

Immer noch ein fehler, daran muss Oracle mal arbeiten, sollte nicht so schwer sein


----------



## SlaterB (18. Sep 2012)

helfen 1-2 Leerzeichen im Schmelz-Block "FROM(SELECT"?

ein grundsätzlicher Test, ob SubQuerys im FROM erlaubt sind, ist natürlich angebracht,
eine andere Schreibweise wäre in Richtung
[sql]
SELECT Temperatur FROM APP.BD
WHERE DAY=Montag 
  AND id in  (SELECT id FROM APP.BD FETCH FIRST 2 ROWS ONLY) 
[/sql]
aber vielleicht ist einfach FETCH im Inneren nicht erlaubt


----------



## jothemac (18. Sep 2012)

Ich habe noch etwas weiter geforscht und das hier gefunden:

```
SELECT * FROM (
    SELECT ROW_NUMBER() OVER() AS ROWNUM,
           TABLE1.* FROM TABLE1) AS T
WHERE ROWNUM <= 5
```
Auf dieser Seite:JavaDB(Derby)?LIMIT????ROWNUM - argius note
Ich habe so etwas auch auf der Oracle seite gefunden, nur nicht mehr wieder gefunden um den link zu posten...
Der Code liefert so die ersten 5 einträge wieder, nur weiss ich noch nicht wo ich WHERE DAY = MONTAG unterbringen soll...


----------



## SlaterB (18. Sep 2012)

Where rownum <= 5 and day = montag


----------



## jothemac (18. Sep 2012)

SO muss das query aussehen:
	
	
	
	





```
"SELECT OPENCHANGEDAYBEFORENUMBER FROM ( SELECT ROW_NUMBER() OVER() AS rownum, APP.FB.* FROM APP.FB) AS tmp WHERE DAY = 2 AND ROWNUM < 2";
```

So funktionierts, mein gott war das ne schwere geburt. Danke für all die Hilfe!


----------

