Nachhilfe bei einfachen SQL-Abfragen

Alles zum SQL-Dialekt

Moderator: Moderatoren

Antworten
peternmb
1000 working lines a day
1000 working lines a day
Beiträge: 525
Registriert: Mi, 01. Feb 2006 16:22
Wohnort: 06618 Naumburg

Nachhilfe bei einfachen SQL-Abfragen

Beitrag von peternmb »

Hallo,
ich möchte eine Xbase-Datenbank in einer Android-App als SQL-Tabelle anzeigen, durchsuchen und sortieren (nichts schreiben).

Das Umsetzen der Datenbank in eine SQL-Tabelle habe ich bereits so gelöst, dass mein Xbase-Programm alles in eine CSV-Datei packt die dann von der App in eine SQL-Tabelle eingelesen wird, es werden alle Daten dabei als Text-Felder eingelesen.

Ich möchte die angezeigten Datensätze, so wie ich es gewohnt bin durchskippen - da fangen jedoch meine Probleme an:
bei Xbase z.B.: index on name, seek "Meier"
wenn ich zurückblättere finde ich auch "Maier", beim vorblättern finde ich auch "Meyer"

bei SQL: SELECT * FROM table1 WHERE (Name = "Meier") ORDER BY UPPER(Name)
es werden nur die Meier beim Blättern angezeigt, wie kann ich alle Datensätze ansprechen?

Zum Sortieren ein dummes Beispiel:
ich sehe jetzt, dass der gefundene Herrn Meier in Hamburg wohnt, wie kann ich jetzt nach Ort sortieren um alle Hamburger durchzublättern?
Gibt es in SQL auch sowas recno() ?
Benutzeravatar
Martin Altmann
Foren-Administrator
Foren-Administrator
Beiträge: 16502
Registriert: Fr, 23. Sep 2005 4:58
Wohnort: Berlin
Hat sich bedankt: 111 Mal
Danksagung erhalten: 48 Mal
Kontaktdaten:

Re: Nachhilfe bei einfachen SQL-Abfragen

Beitrag von Martin Altmann »

Moin Peter,
schau Dir mal das LIKE-Statement (statt des =) an.
Sortiert kannst Du das Ergebnis zurück bekommen, indem Du ORDER BY ort oder wie auch immer Dein Feld heißt) an den Select anhängst.

Viele Grüße,
Martin
:grommit:
Webseite mit XB2.NET und ausschließlich statischem Content in Form von HTML-Dateien: https://www.altem.de/
Webseite mit XB2.NET und ausschließlich dynamischem Content in Form von in-memory-HTML: https://meldungen.altem.de/

Mitglied der XUG Osnabrück
Vorsitzender des Deutschsprachige Xbase-Entwickler e. V.
georg
Der Entwickler von "Deep Thought"
Der Entwickler von "Deep Thought"
Beiträge: 2823
Registriert: Fr, 08. Feb 2008 21:29
Hat sich bedankt: 95 Mal
Danksagung erhalten: 13 Mal

Re: Nachhilfe bei einfachen SQL-Abfragen

Beitrag von georg »

Hallo, Peter -


SELECT * FROM table1 WHERE Name LIKE 'Meier%' ORDER BY Name

Bei Verwendung von LIKE dient % als Wildcard;
SQL sortiert standardmässig case insensitive, d.h. das Upper ist m.E. nicht erforderlich.

In der Wissensbasis findest Du einige Beiträge von mir im Umgang mit SQL (bzw. MySQL), dort werden auch einige der hier gestellten Fragen beantwortet. Ich bitte Dich, dort auch mal reinzuschauen.

Grundsätzlich ist SQL nicht xBase. Punkt. Xbase ist "zeilenorientiert" und "betrachtet" immer den gesamten Datenbestand. SQL ist "result set" orientiert und betrachtet daher immer den Ausschnitt, der als Ergebnis ("result") eines Query geliefert wird. Wenn Du obiges Query an den SQL-Server schickst, bekommst Du aus einer Tabelle mit 10.000 Sätze vielleicht 500 zurück - Du bewegst Dich dann innerhalb dieses "result set", und kannst es weder "vorne" noch "hinten" verlassen: Du hast genau diese 500 Sätze angefordert. Willst Du "vor" oder "hinter" das "result set", musst Du ein neues anfordern.

Wenn Du "Hamburg" als Wohnort gefunden hast, und jetzt die "Meier" aus Hamburg haben willst:

SELECT * FROM table1 WHERE Name LIKE 'Meier%' AND Ort = 'Hamburg' ORDER BY Name

oder alle Kunden aus Hamburg:

SELECT * FROM table1 WHERE Ort = 'Hamburg' ORDER BY Name

Das mag im Moment "unpraktisch" erscheinen, aber man kann mit SQL genauso gut Browses darstellen wie mit DBF-Dateien. Ich habe eine entsprechende Klasse geschrieben, die von dem einen oder anderen Foren-Teilnehmer auch verwendet wird.

Kommen wir zum Abschluss noch auf die recno(). Auch dieses Konzept kennt SQL nicht. Die meisten Wrapper, mit denen man auf SQL result sets zugreifen kann, erzeugen für das jeweilige result set (!) ein Pseudo-Satznummer, da etliche Xbase-Funktionen ohne die nicht so richtig glücklich sind. Diese Nummer ist aber immer nur simuliert und auch nur für das jeweilige result set gültig.
Liebe Grüsse aus der Eifel,

Georg S. Lorrig
Redakteur der Wiki des Deutschprachigen Xbase-Entwickler e.V.
peternmb
1000 working lines a day
1000 working lines a day
Beiträge: 525
Registriert: Mi, 01. Feb 2006 16:22
Wohnort: 06618 Naumburg

Re: Nachhilfe bei einfachen SQL-Abfragen

Beitrag von peternmb »

vielen Dank für die Hinweise - ist leider nicht unbedingt das, was ich hören wollte :cry:

Bringt mich aber insofern weiter, weil ich jetzt zumindest sehe, dass ich das Konzept meines Xbase-Programmes nicht von DBF zu SQl 1:1 umsetzen kann.
georg
Der Entwickler von "Deep Thought"
Der Entwickler von "Deep Thought"
Beiträge: 2823
Registriert: Fr, 08. Feb 2008 21:29
Hat sich bedankt: 95 Mal
Danksagung erhalten: 13 Mal

Re: Nachhilfe bei einfachen SQL-Abfragen

Beitrag von georg »

Hallo, Peter -


Du bist nicht der einzige, dem das so ergangen ist. Darum verspricht Alaska ja mit der 2.0 auch eine relativ simple Migration, die aus meiner Sicht aber nicht realisierbar ist, ohne den SQL-Server in eine bessere DBF-Tabelle zu verwandeln.

Ich habe mich in den letzten Jahrzehnten so über manche Probleme der xBase-Datenhaltung geärgert, dass ich mich um endlich (!) eine Alternative zu haben, intensiver mit SQL auseinandergesetzt habe. Denn es gibt viele Lösungen, die SQL nutzen, und die man von der Oberfläche her nicht als solche erkennt. Und im Laufe der Zeit habe ich erkannt, dass "Nachteile" eigentlich auch "Vorteile" sein können, wenn man sie richtig nutzt.

Ein paar Gedanken dazu:

Code: Alles auswählen

SELECT count(*) FROM table1 WHERE Name = 'Meyer' => nNumTarget
SELECT count(*) FROM table1 WHERE Name < 'Meyer' => nNumBefore
SELECT count(*) FROM table1 WHERE Name > 'Meyer' => nNumAfter
Die Summe dieser drei Querys ergibt die Anzahl Zeilen in der Tabelle.

Code: Alles auswählen

SELECT * FROM table1 WHERE Name = 'Meyer' ORDER BY Vorname
(Browse des result set)
Nun will der Anwender "1 Seite" zurück. Sagen wir, eine Seite hat 20 anzeigbare Zeilen.

Code: Alles auswählen

SELECT * FROM table1 ORDER BY Name, Vorname LIMIT nNumBefore - 20, 20
Dieses result set liefert Dir die 20 Einträge "vor" Meier.

Code: Alles auswählen

SELECT * FROM table1 ORDER BY Name, Vorname LIMIT nNumBefore + nNumTarget + 1, 20
Dieses result set liefert Dir die 20 Einträge "nach" Meier.

Du siehst, dass man mit wenigen Anweisungen flott eine Satznummer simulieren kann, und dass LIMIT durch die Offset, Anzahl Struktur fantastisch geeignet ist, das Ergebnis wie gewünscht einzugrenzen.
Liebe Grüsse aus der Eifel,

Georg S. Lorrig
Redakteur der Wiki des Deutschprachigen Xbase-Entwickler e.V.
Benutzeravatar
AUGE_OHR
Marvin
Marvin
Beiträge: 12903
Registriert: Do, 16. Mär 2006 7:55
Wohnort: Hamburg
Hat sich bedankt: 19 Mal
Danksagung erhalten: 44 Mal

Re: Nachhilfe bei einfachen SQL-Abfragen

Beitrag von AUGE_OHR »

peternmb hat geschrieben:Gibt es in SQL auch sowas recno() ?
nope ... aber du kannst ja intern ein Field "_Record" anlegen z.b. als AutoIncrement (MySQL) oder Sequence (PostgreSQL).

nun arbeite man selten mit der natürlichen Reihenfolge sondern hat eine Sortierung mit ORDER BY.
Für MySQL gibt es nun die (MySQL) Function ROWID() und für PostgreSQL ROWNUMBER() die man in ein SELECT mit einbauen kann.
Damit erhältst du eine extra Spalte (Column) welche entsprechend der Sortierung nummeriert ist.

was nun das Browsen vor/zurück angeht : Incrementell d.h. er zeigt bei jedem Tastendruck ein Ergebnis der "Menge"
gruss by OHR
Jimmy
Benutzeravatar
Martin Altmann
Foren-Administrator
Foren-Administrator
Beiträge: 16502
Registriert: Fr, 23. Sep 2005 4:58
Wohnort: Berlin
Hat sich bedankt: 111 Mal
Danksagung erhalten: 48 Mal
Kontaktdaten:

Re: Nachhilfe bei einfachen SQL-Abfragen

Beitrag von Martin Altmann »

Moin Jimmy,
AUGE_OHR hat geschrieben:
peternmb hat geschrieben:Gibt es in SQL auch sowas recno() ?
nope ... aber du kannst ja intern ein Field "_Record" anlegen z.b. als AutoIncrement (MySQL) oder Sequence (PostgreSQL).
ganz so einfach ist das leider nicht - klar bleibt die so festgelegte Nummer zwar aufsteigend, aber sie weißt durchaus Lücken auf - gerade beim Löschen einzelner Sätze!
Die Recno(), wie wir sie kennen, ist ja die physikalische Datensatznummer! Sie ändert sich immer dann, wenn ein DbDelete() (mit anschließendem DbPack()) auf einzelne Sätze angewandt wird - in Deinem Beispiel würden die anderen in _Record hinterlegten Nummern unverändert bleiben!
Um das zu erreichen, müsste man in den Datenbanken entsprechende Trigger definieren, die sich um diese Anpassungen kümmern (als Beispiel eine Delete-Trigger und ein Insert-Trigger - ersterer macht jeweils ein Update auf das Feld aller Datensätze und schreibt dort den neuen Wert - beginnend bei 1 - hinein, letzterer hinterlegt dort Max( _Recno ) + 1 (kann man sich vorab mittels select geben lassen).
Beim Neudurchnummerieren (delete-trigger) ist darauf zu achten, dass die Neunummerierung in der alten Reihenfolge der Feldinhalte erfolgt! Aus Performancegründen sollte man das nicht nach jedem Delete machen, sondern nur nach Abschluß einer entsprechenden Transaktion - wenn also mehrere Datensätze in einem Rutsch gelöscht werden (Bulk-Delete), dann sollte das nach dem Löschen des letzten Datensatzes passieren.
Aber dazu kann sich Georg sicherlich noch ausführlicher äußern.

Viele Grüße,
Martin
:grommit:
Webseite mit XB2.NET und ausschließlich statischem Content in Form von HTML-Dateien: https://www.altem.de/
Webseite mit XB2.NET und ausschließlich dynamischem Content in Form von in-memory-HTML: https://meldungen.altem.de/

Mitglied der XUG Osnabrück
Vorsitzender des Deutschsprachige Xbase-Entwickler e. V.
georg
Der Entwickler von "Deep Thought"
Der Entwickler von "Deep Thought"
Beiträge: 2823
Registriert: Fr, 08. Feb 2008 21:29
Hat sich bedankt: 95 Mal
Danksagung erhalten: 13 Mal

Re: Nachhilfe bei einfachen SQL-Abfragen

Beitrag von georg »

Hallo,


wie allgemein bekannt, verwende ich Hector Peroza's MySQL Wrapper.

Das MyResult()-Objekt reicht (immer nach Geschmack, Ausstattung des PCs und der Leitungsqualität) bei kleineren Dateien (und das können schon mal auch zehn- oder zwanzigtausend Sätze sein) zum Browsen aus:

Code: Alles auswählen

	oCon := GetMySQLConnection()
	oBoard := MyResult():new(oCon, , "Board")
	cSelect := "SELECT * FROM Board ORDER BY BDID"
	oBoard:openRecord(cSelect)
    ...
	oBro := XbpBrowse():new(oStatic, oStatic, aPos, aSize):create()
	oBro:tabStop := .T.
	oBro:skipBlock     := {|n| oBoard:Skipper(n)}
	oBro:goTopBlock    := {| | oBoard:dbGoTop()}
	oBro:goBottomBlock := {| | oBoard:dbGoBottom()}
	oBro:phyPosBlock   := {| | oBoard:Recno()}
	oBro:posBlock      := {| | oBoard:DbPosition()}
	oBro:goPosBlock    := {|n| oBoard:GoPosition(n)}
	oBro:lastPosBlock  := {| | 100}
	oBro:firstPosBlock := {| | 0}
Wären die ersten vier Zeilen nicht, würde jeder es für ein normales Browse einer DBF halten. Die Tabelle in diesem Beispiel hat nur ein paar Felder, die auch fast alle angezeigt werden. Andernfalls lohnt es sich, im SELECT-Statement nur die Felder zu benennen, die auch angezeigt werden sollen.

Es gibt aber trotzdem einen gravierenden Unterschied: in diesem Browse bewegt man sich IMMER im Result Set, d.h. neue Sätze werden NICHT angezeigt, wie es z.B. bei einem DBF-Browse der Fall ist. Das kann man durch eine Abfrage im Event-Loop regeln, dass man dort nach n Sekunden/Minuten/Tagen einen refresh auf das Result Set macht.

Wenn man es mit ein paar Millionen Datensätzen zu tun hat, wird dieses Vorgehen nicht mehr funktionieren, da alleine das Bereitstellen des Result Set dann schon mal ein paar Sekunden brauchen kann. Aber auch solche Tabellen lassen sich gut im XbpBrowse verwenden:

Code: Alles auswählen

   aFields := {"ABTitle", "ABKey", "ABYear", "ABProduced", "ABDuration", "ABBitRate", "ABIntro", "ABLinks", "ABCover", "ABRecID"}
	aSortOrder := {"ABTitle", "ABAuthor", "ABRecID"}
	oAudioHist := SQLBroClass():new("AudioHist", oCon)
	oAudioHist:Select({}, aSortOrder, aFields)

	oBro := XbpBrowse():new(oStatic, oStatic, aPos, aSize):create()
	oBro:tabStop := .T.
	oBro:skipBlock     := {|n| oAudioHist:Skipper(n)}
	oBro:goTopBlock    := {| | oAudioHist:dbGoTop()}
	oBro:goBottomBlock := {| | oAudioHist:dbGoBottom()}
	oBro:phyPosBlock   := {| | oAudioHist:Recno()}
	oBro:posBlock      := {| | oAudioHist:DbPosition()}
	oBro:goPosBlock    := {|n| oAudioHist:DbGoPosition(n)}
	oBro:lastPosBlock  := {| | 100}
	oBro:firstPosBlock := {| | 0}
Sieht immer noch aus wie ein Standard-DBF-Browse, wären die ersten vier Zeilen nicht ...

SQLBroClass ist eine Klasse, die im Endeffekt ein MyResult() Objekt zur Verfügung stellt. Der Clou ist einfach, dass diese Klasse nur eine bestimmte Anzahl Sätze aus der Tabelle liest (sagen wir mal, 5000). SQLBroClass verwaltet ein Fenster auf die Tabelle. Entsprechend der angeforderten Bewegungen im Browser wird dieses Fenster nach oben oder unten verschoben. Solange die Bewegungen im Browse innerhalb des Result Set erfolgen (5000 Sätze sind eine Menge!), geht das ratz-fatz. Andernfalls ermittelt SQLBroClass, welches Fenster jetzt benötigt wird und passt das Result Set entsprechend an.


Allerdings wollte Peter die Daten in einer Android-App anzeigen, und da weiss ich nicht, welche Sprache und welcher (embedded) SQL-Server zum Einsatz kommen. Meine Ausführungen beziehen sich auf native Xbase++.
Liebe Grüsse aus der Eifel,

Georg S. Lorrig
Redakteur der Wiki des Deutschprachigen Xbase-Entwickler e.V.
peternmb
1000 working lines a day
1000 working lines a day
Beiträge: 525
Registriert: Mi, 01. Feb 2006 16:22
Wohnort: 06618 Naumburg

Re: Nachhilfe bei einfachen SQL-Abfragen

Beitrag von peternmb »

Code: Alles auswählen

SELECT * FROM table1 WHERE Name < 'Meyer'
SELECT * FROM table1 WHERE Name >= 'Meyer' 
Ich müsste es eigentlich so lösen können, dass ich mir mit diesem Code 2 Datenbanksegment erstelle und das jeweilige, jenachdem ob ich vor oder zurückblättern will einsetze. Mir war nur nicht klar, dass ich auch bei Textfeldern mit < und > arbeiten kann.

Ich erhalte mit meiner Android-Funktion ein Array mit den selektierten Datensätzen, sollte dann also eigentlich kein Problem sein :)

Danke für den Denkanstoss =D>
Benutzeravatar
Jan
Marvin
Marvin
Beiträge: 14641
Registriert: Fr, 23. Sep 2005 18:23
Wohnort: 49328 Melle
Hat sich bedankt: 21 Mal
Danksagung erhalten: 87 Mal
Kontaktdaten:

Re: Nachhilfe bei einfachen SQL-Abfragen

Beitrag von Jan »

Das Hauptproblem besteht doch darin, das im Kopf zu trennen. Wenn man auf SQL umsteigt kann man eben in vielen Fällen nicht einfach das langjährig gewohnte Prozedere mehr verwenden. Weil eben nicht mehr satzorientiert gearbeitet wird in SQL. Wie wir es aber tief in unseren Denkstrukturen implementiert haben. Und DAS umzustellen, die Herangehensweise an Probleme in unseren Denkweisen zu ändern, ist wohl schwieriger als irgendeine SQL-Syntax zu lernen.

Jan
Mitglied der XUG Osnabrück
Mitglied der XUG Berlin/Brandenburg
Mitglied des Deutschsprachige Xbase-Entwickler e. V.
peternmb
1000 working lines a day
1000 working lines a day
Beiträge: 525
Registriert: Mi, 01. Feb 2006 16:22
Wohnort: 06618 Naumburg

Re: Nachhilfe bei einfachen SQL-Abfragen

Beitrag von peternmb »

Code: Alles auswählen

SELECT * FROM table1 WHERE Name < 'Meyer'
SELECT * FROM table1 WHERE Name >= 'Meyer' 
Kann es ein, dass >= nicht funktioniert?
Gibt es das in SQL einfach nicht oder mache ich da was falsch :banghead:
Benutzeravatar
brandelh
Foren-Moderator
Foren-Moderator
Beiträge: 15688
Registriert: Mo, 23. Jan 2006 20:54
Wohnort: Germersheim
Hat sich bedankt: 65 Mal
Danksagung erhalten: 33 Mal
Kontaktdaten:

Re: Nachhilfe bei einfachen SQL-Abfragen

Beitrag von brandelh »

hilfreich wäre zu erwähnen wo dein Problem liegt de.
Funktion ergibt Syntax Fehler oder das Ergebnis ist unerwartet.
Gruß
Hubert
georg
Der Entwickler von "Deep Thought"
Der Entwickler von "Deep Thought"
Beiträge: 2823
Registriert: Fr, 08. Feb 2008 21:29
Hat sich bedankt: 95 Mal
Danksagung erhalten: 13 Mal

Re: Nachhilfe bei einfachen SQL-Abfragen

Beitrag von georg »

Hallo, Peter -


hilfreich ist viel mehr: welcher SQL-Server? Welche Version?

MySQL in der 5.5 interpretiert >= korrekt, während => zu einer Fehlermeldung führt. Die für MySQL gültigen Operatoren findet man z.B. hier:

http://dev.mysql.com/doc/refman/5.6/en/ ... y-ref.html

< bzw. > sind alphabetisch und greater und less einsortiert.


Ansonsten: probiere die SELECT Anweisung doch einfach mal in der entsprechenden Konsole des SQL-Servers, da sind die Fehlermeldungen meist aussagekräftiger.
Liebe Grüsse aus der Eifel,

Georg S. Lorrig
Redakteur der Wiki des Deutschprachigen Xbase-Entwickler e.V.
peternmb
1000 working lines a day
1000 working lines a day
Beiträge: 525
Registriert: Mi, 01. Feb 2006 16:22
Wohnort: 06618 Naumburg

Re: Nachhilfe bei einfachen SQL-Abfragen

Beitrag von peternmb »

brandelh hat geschrieben:hilfreich wäre zu erwähnen wo dein Problem liegt de.
Funktion ergibt Syntax Fehler oder das Ergebnis ist unerwartet.
Das Problem ist ein unerwarteter Syntaxfehler 8)

Da Georg das so geschrieben hat vermute ich, dass es nur so funktioniert - ich hatte mich schon gewundert warum er nicht <= verwendet

Code: Alles auswählen

SELECT count(*) FROM table1 WHERE Name = 'Meyer' => nNumTarget
SELECT count(*) FROM table1 WHERE Name < 'Meyer' => nNumBefore
SELECT count(*) FROM table1 WHERE Name > 'Meyer' => nNumAfter
peternmb
1000 working lines a day
1000 working lines a day
Beiträge: 525
Registriert: Mi, 01. Feb 2006 16:22
Wohnort: 06618 Naumburg

Re: Nachhilfe bei einfachen SQL-Abfragen

Beitrag von peternmb »

georg hat geschrieben: hilfreich ist viel mehr: welcher SQL-Server? Welche Version?
Das weiss ich leider nicht, die DB läuft lokal unter Android.
georg hat geschrieben: MySQL in der 5.5 interpretiert >= korrekt, während => zu einer Fehlermeldung führt. Die für MySQL gültigen Operatoren findet man z.B. hier:
schön dann weiß ich zumindest, dass es funktionieren kann.
georg hat geschrieben: Ansonsten: probiere die SELECT Anweisung doch einfach mal in der entsprechenden Konsole des SQL-Servers, da sind die Fehlermeldungen meist aussagekräftiger.
werde ich mal ein bißchen rumspielen, soviele Möglichkeiten gibt es ja nicht.
Antworten