57
GDI-SQL-Seminar 19.03.2018 Seite 1/57 SQL-Seminar Syntax, Beispiele, Zusatz-Informationen Stand: 19.03.2013

SQL Befehle 30 - gdi.de · SQL arbeitet im Gegensatz hierzu mengenorientiert. Man gibt an, welche Bedingung erfüllt sein muss, der Rest erledigt das System und man erhält die Ergebnismenge

  • Upload
    others

  • View
    7

  • Download
    0

Embed Size (px)

Citation preview

Page 1: SQL Befehle 30 - gdi.de · SQL arbeitet im Gegensatz hierzu mengenorientiert. Man gibt an, welche Bedingung erfüllt sein muss, der Rest erledigt das System und man erhält die Ergebnismenge

GDI-SQL-Seminar 19.03.2018 Seite 1/57

SQL-Seminar

Syntax, Beispiele, Zusatz-Informationen Stand: 19.03.2013

Page 2: SQL Befehle 30 - gdi.de · SQL arbeitet im Gegensatz hierzu mengenorientiert. Man gibt an, welche Bedingung erfüllt sein muss, der Rest erledigt das System und man erhält die Ergebnismenge

GDI-SQL-Seminar 19.03.2018 Seite 2/57

1. Strukturen und Elemente relationaler Datenbanken • 1.0 Einleitung S. 4

♦ 1.0.1 Datenbank S. 4

• 1.1 Tabellen und Beziehungen S. 4

♦ 1.1.1 Tabellen S. 4

♦ 1.1.2 Wichtige Beziehungstypen S. 5

2. SQL • 2.0 Einleitung S. 7

♦ 2.0.1 Voraussetzungen für die Anwendung von SQL S. 7

• 2.1 Syntax und Notation S. 8

• 2.2 Wo kann man SQL in der GDILine einsetzen? S. 9

• 2.3 Aufbau des Menüpunktes Zusatz | SQL-System S. 9

• 2.4 SQL-Syntax S .10

♦ 2.4.1 Übersicht über die SQL-Basis-Sprachelemente S. 10

♦ 2.4.2 Datentypen S. 11

♦ 2.4.3 Grundformat des SELECT-Statements S. 11

♦ 2.4.4. Selektieren ohne Bedingungen S. 12 - 13

♦ 2.4.5 Bedingte Selektion S. 14 - 19

♦ 2.4.5.1 Grundform der WHERE-KIausel S. 14

♦ 2.4.5.2 Vergleichsoperatoren S. 15

♦ 2.4.5.3 Wirkungsweise einer einfachen WHERE-Klausel S. 16 - 17

♦ 2.4.5.4 Wirkungsweise einer durch die Verwendung von logischen

Operatoren komplexeren WHERE-Klausel S. 18 - 19

♦ 2.4.6 Funktionen S. 20 - 30

♦ 2.4.6.1 Standardfunktionen S. 20 - 23

♦ 2.4.6.1.1 Die AVG- Funktion S. 20

♦ 2.4.6.1.2 Die SUM-Funktion S. 21

♦ 2.4.6.1.3 Die MAX-Funktion S. 21

♦ 2.4.6.1.4 Die MIN- Funktion S. 22

♦ 2.4.6.1.5 Die COUNT- Funktion S. 22

♦ 2.4.6.2 Spezielle Funktionen S. 24 - 27

♦ 2.4.6.2.1 Die BETWEEN... AND-Funktion S. 14

♦ 2.4.6.2.2 Die IN-Funktion S. 25

Page 3: SQL Befehle 30 - gdi.de · SQL arbeitet im Gegensatz hierzu mengenorientiert. Man gibt an, welche Bedingung erfüllt sein muss, der Rest erledigt das System und man erhält die Ergebnismenge

GDI-SQL-Seminar 19.03.2018 Seite 3/57

♦ 2.4.6.2.3 Die LIKE-Funktion S. 26

♦ 2.4.6.2.4 Die NULL-Funktion S. 27

♦ 2.4.6.3 Auswahl spezieller Character- Funktionen S. 28 - 30

♦ 2.4.6.3.1 Die LOWER-Funktion S. 28

♦ 2.4.6.3.2 Die UPPER-Funktion S. 29

♦ 2.4.6.3.3 Die SUBSTR-Funktion, die COPY-Funktion S. 30

♦ 2.4.7 Datentypenumwandlung mit CAST S. 31

♦ 2.4.8 Mathematische Bearbeitung S. 32

♦ 2.4.8. Datumsfunktionen S. 33

♦ 2.4.10 Gruppierungs-Funktion GROUP BY S. 34

♦ 2.4.11 Unter-Gruppierungs-Funktion HAVING S. 35

♦ 2.4.12 Verbinden von Tabellen S. 36 - 41

♦ 2.4.12.1 JOIN / OUTER JOIN S. 36 - 38

♦ 2.4.12.2 SUBQUERY / SUBSELECT S. 39

♦ 2.4.12.2.1 SUBSELECT ohne SUBSELECT - Operator S. 40

♦ 2.4.12.2.2 SUBSELECT mit SUBSELECT - Operator S. 40

♦ 2.4.13 Zusammenfügen von Ergebnissen mit UNION S. 42

♦ 2.4.14 Das CREATE Kommando S. 43

♦ 2.4.14.1 Erstellen von Tabellen S. 43

♦ 2.4.12.2 Erstellen von Indices S. 43

♦ 2.4.15 Das DROP Kommando S. 44

♦ 2.4.15.1 Löschen von Tabellen S. 44

♦ 2.4.15.2 Löschen von lndices S. 44

♦ 2.4.16 Das INSERT-Kommando S. 45

♦ 2.4.17 Das ALTER -Kommando S. 46

♦ 2.4.18 Das DELETE-Kommando S. 48

♦ 2.4.19 Das UPDATE-Kommando S. 48

• 2.5 SONSTIGES, Besonderheiten bei GDI S .51

• 2.6 Firebird-Besonderheiten S .52

♦ 2.6.1 Spezielle Funktionen bei FireBird S. 52

♦ 2.6.1.1 Teilergebnis-Datenmenge mit FIRST und SKIP S. 52

♦ 2.6.1.2 Bedingte Abfragen mit CASE WHEN-Anweisungen S. 52

♦ 2.6.1.3 Temporäre Proceduren per EXECUTE BLOCK S. 54

Page 4: SQL Befehle 30 - gdi.de · SQL arbeitet im Gegensatz hierzu mengenorientiert. Man gibt an, welche Bedingung erfüllt sein muss, der Rest erledigt das System und man erhält die Ergebnismenge

GDI-SQL-Seminar 19.03.2018 Seite 4/57

1. Strukturen und Elemente relationaler Datenbanken 1.0 Einleitung 1.0.1 Datenbank Eine Datenbank stellt eine Sammlung von Daten dar. Im Falle einer relationalen Datenbank sind dies von einander abhängige Datentabellen, in welchen jeweils bestimmte Daten gespeichert werden. Diese Daten sind von der eigentlichen Anwendung unabhängig. Desweiteren gehören zur Datenbank auch Module, welche die Datenbankverwaltung ermöglichen (Datenbankmanagementsystem (DBMS), Verwaltungsprogramme). Über diese Module wird das Speichern, Auffinden und Verwalten der Daten geregelt (Zugriffssteuerung, Backup und Restore, Erstellen, Ändern und Löschen von Objekten in der Datenbank, Kontrolle der Datenbankkonsistenz, Transaktionssteuerung....). 1.1 Tabellen und Beziehungen 1.1.1 Tabellen Die Daten werden in zweidimensionalen Tabellen abgelegt. Eine Tabelle besteht aus Zeilen (rows, Datensätze) und Spalten (columns, Datenfelder). Auch Verwaltungsdaten werden in (von aussen nicht einsehbaren) Systemtabellen abgelegt. Eine Datenzeile einer Tabelle muss mittels eines logischen Schlüssels eindeutig identifizierbar sein (Primärschlüssel). Jeder Wert ist also durch Angabe der Tabelle, Spaltenname, und Primärschlüssel identifizierbar. Der eindeutige Schlüssel (Index) kann aus einem Datenfeld oder mehreren Datenfeldern gebildet sein. Für den Aufbau der Tabellen gibt es Regeln ("Normalisierung" der Datenbank, Datenbank-Design), die hier jedoch nicht näher betrachtet werden sollen. Zur effektiven Arbeit mit der Datenbank notwendig ist jedoch die Kenntnis der Beziehungen der Tabellen zueinander, die aus diesen Regeln letztlich herrühren. Bevor wir uns deshalb mit der Funktionsweise von SQL überhaupt erst vertraut machen können, ist es notwendig, den Sinn, die Ziele und den Aufbau einer relationalen Datenbankstruktur begriffen zu haben.

DEFINITION:

Die zentrale Idee einer relationalen Datenbank besteht darin, daß die Daten in physisch voneinander unabhängigen Einheiten (Tabellen) gespeichert werden, wobei deren Beziehungen untereinander mit Hilfe der Daten selbst hergestellt werden. Das setzt die Beachtung bestimmter Regeln beim Erstellen einer Datenstruktur voraus.

Page 5: SQL Befehle 30 - gdi.de · SQL arbeitet im Gegensatz hierzu mengenorientiert. Man gibt an, welche Bedingung erfüllt sein muss, der Rest erledigt das System und man erhält die Ergebnismenge

GDI-SQL-Seminar 19.03.2018 Seite 5/57

1.1.2 Wichtige Beziehungstypen Zwischen den Datensätzen der verschiedenen Tabellen können verschiedene Beziehungen auftreten. Die wichtigsten sind in der nachfolgenden Tabelle aufgeführt: Beziehungsart Schreibweise Bemerkung Eins-zu-eins-Beziehung 1 : 1 Ein Datensatz in Tabelle A entspricht genau einem

Datensatz in Tabelle B Eins-zu-mehrfach-Beziehung 1 : m Zu einem Datensatz in Tabelle A gibt es einen oder

mehrere Datensätze in Tabelle B Mehrfach-zu-mehrfach-Beziehung

m : m Zu einem Datensatz in Tabelle A gibt es einen oder mehrere Datensätze in Tabelle B, aber auch umgekehrt (Überkreuz-Beziehungen). Solche beziehungen können in einer relationalen Datenbank nicht abgebildet werden. Es müssen zusätzliche Tabellen eingerichtet werden.

Eins-zu-eins-bedingte-Beziehung

1 : 1c Zu einem Datensatz in Tabelle A gehört nicht zwingend einen Datensatz in Tabelle B. Wenn in Tabelle B jedoch ein Satz existiert, so muss auch in A ein korrespondierender vorhanden sein.

Eins-zu-mehrfach-bedingte-Beziehung

1 : mc Zu einem Datensatz in Tabelle A gehört nicht zwingend ein oder mehrere Datensätze in Tabelle B. Wenn in Tabelle B jedoch ein Satz existiert, so muss auch in A ein korrespondierender Satz vorhanden sein.

Rekursive Beziehung Einträge in verschiedenen Spalten in unterschiedlichen Zeilen einer Tabelle sind untereinander abhängig. In einer relationalen Datenbank nicht zulässig

In relationalen Dantenbanken sind also die Beziehungsarten 1 : 1, 1 : m, 1 : 1c und 1 : mc erlaubt. Im Zusammenhang mit unserem SQL-Seminar (es geht nicht um Datenbankdesign, sondern in erster Linie um das "Auslesen" von Information) oder auch mit der Erstellung von Reports wichtig ist die Kenntnis, ob es zu einem interessierenden Datensatz in einer Tabelle A einen oder mehrere Datensätze in einer Tabelle B gibt, deren Information uns ebenfalls interessiert. Beispiele:

o Für einen Kunden können mehrere Belege im System existieren. Man findet also in der Belegtabelle keinen, einen oder mehrere Belege, welche im Feld Adressnr die Kundennummer besitzen (à 1 : m). Umgekehrt findet man, wenn man sich für genau einen Beleg interessiert genau einen Kundendatensatz in der Kundentabelle, aus welchem man zusätzliche Information erhalten kann (à 1 : 1)

o Im Kundenstamm wird einem Kunden eine Adressgruppe zugeordnet. Die Adressgruppe selbst ist in der Basisdatentabelle GDIDEF definiert. Die Adressgruppenbezeichnung findet man also in dieser Tabelle. Es gibt zu einem Kunden genau einen Datensatz in der GDIDEF, der die Adressgruppennummer beinhaltet (à 1 : 1). Umgekehrt kann es zu einem Adressgruppensatz in der Tabelle GDIDEF keinen, einen oder viele Kundendatensätze geben (à 1 : m)

Page 6: SQL Befehle 30 - gdi.de · SQL arbeitet im Gegensatz hierzu mengenorientiert. Man gibt an, welche Bedingung erfüllt sein muss, der Rest erledigt das System und man erhält die Ergebnismenge

GDI-SQL-Seminar 19.03.2018 Seite 6/57

o Zu einem Beleg gehören in der Regel mehrere Belegpositionen (à 1 : m). Umgekehrt gehören zu einer Belegposition genau ein Belegsatz (à 1 : 1). Die Verknüpfung erfolgt hier durch die Übereinstimmung mehrerer Datenfelder, nämlich Belegtyp, Belegart und Belegnr.

Auskunft über den Aufbau der Datenbank und die vorliegenden Verknüpfungen erhält man aus der Datei GDILINE.DBS (Text-Datei im Programmverzeichnis) im Falle einer GDIline 2.x bzw aus den *.META-Dateien im Falle der Bline 3.x. In diesen Dateien ist die Soll-Datenbank-Struktur definiert. Jede Tabelle ist durch die Abschnitte [Tabellenname.Felder] und [Tabellenname.Indizes] definiert. Die meisten Feldnamen sind "sprechend", im Falle der Tabelle GDIDEF liegen jedoch nicht-sprechende Feldnamen vor. An dieser Stelle sei auf die gesonderte Dokumentation aus dem Seminar I verwiesen.

Page 7: SQL Befehle 30 - gdi.de · SQL arbeitet im Gegensatz hierzu mengenorientiert. Man gibt an, welche Bedingung erfüllt sein muss, der Rest erledigt das System und man erhält die Ergebnismenge

GDI-SQL-Seminar 19.03.2018 Seite 7/57

2. SQL 2.0 Einleitung 2.0.1 Voraussetzungen für die Anwendung von SQL SQL (Structured Query Language) ist weder eine Programmiersprache im herkömmlichen Sinne noch eine bloße Abfragesprache, wie ihr Name suggeriert: Sie ist eine Sprache der vierten Generation (4 GL) und arbeitet nicht mehr auf Datensatz-, sondern auf Datenmengen-Niveau; außerdem enthält sie keine prozeduralen Elemente wie herkömmliche Programmiersprachen und ihr Anwender definiert nicht mehr den Weg zu seinem Ziel (das WIE), sondern das Ziel selbst (das WAS); nicht zuletzt deshalb kann SQL auch nur im Zusammenhang mit relationalen Datenbank-Managementsystemen verwendet werden. Den Unterschied zwischen prozeduraler (problemorientierter) Sprache und SQL soll anhand des folgenden - hypothetischen - Beispiels verdeutlicht werden: Aus der Tabelle Kunden sollen alle Kunden ausgegeben werden, deren Kreditlimit mehr als 10000 € beträgt. Problemorientierte Sprache (3 GL) SQL (4 GL) Open (Kunden) While not EOF(Kunden) Read(Kunden); If Kunden.KredLimit > 10000 then Print(Kunden.Kundennr, Kunden.Name1); Endwhile; Close(Kunden);

Select Kundennr, Name1 From Kunden Where KredLimit > 10000;

In einer problemorientierten Sprache muss die Tabelle zunächst geöffnet und danach alle Sätze der Tabelle expilizit gelesen werden. Für jeden Satz muss geprüft werden, ob er die Bedingung erfüllt. Außerdem darf nicht über das Ende der Tabelle gelesen werden (while not EOF). Die Verarbeitung erfolgt satzorientiert. SQL arbeitet im Gegensatz hierzu mengenorientiert. Man gibt an, welche Bedingung erfüllt sein muss, der Rest erledigt das System und man erhält die Ergebnismenge. Wie das System die Aufgabe erledigt, bleibt dem SQL-Interpreter überlassen. Da in SQL (SQL92) die prozeduralen Elemente fehlen, stellt sie keine vollständige Programmiersprache dar. (Man kann z.B. ein Pascal- Programm prinzipiell auch in Fortran schreiben und umgekehrt, nicht aber in SQL). Trotzdem ist die Abfragesprache sehr mächtig und ist gerade im Hinblick auf die Erstellung von Auswertungen und zur (mal schnellen) Datenbankbeauskunftung sehr gut einsetzbar. Letztlich zeigt sich die Leistungsfähigkeit dann, wenn SQL in Verbindung mit prozeduralen Sprachkonstruktionen eingesetzt wird. Dies ist in unserer GDILine z.B. in den Stored Procedures der Fall oder durch die Einbettung von SQL in den Delphi-Programmroutinen. Für den "Außenstehenden" wird dies durch die Verbindung von GDI-BASIC mit SQL möglich, so dass hier auch komplexe Aufgabenstellungen gelöst werden können.

Page 8: SQL Befehle 30 - gdi.de · SQL arbeitet im Gegensatz hierzu mengenorientiert. Man gibt an, welche Bedingung erfüllt sein muss, der Rest erledigt das System und man erhält die Ergebnismenge

GDI-SQL-Seminar 19.03.2018 Seite 8/57

2.1 Syntax und Notation

Zeichen Beispiel Bedeutung Fettschrift EXIT Text ist genau wie geschrieben einzugeben kursiv Spalte, Option oder Parameter Reservierte Worte / Worte mit besonderer Bedeutung

C Einzelner Buchstabe

Char Datentyp Character Date Datentyp Datum Ausdruck M Zahl N Zahl Number konstante Zahl Bedingung z.B.: where artikelnr = '4711' Text Character-Konstante mit oder ohne Anführungs-

zeichen Variable User - Variable [ ] Eckige Klammern

[NOT] optionale Eingabe - ohne Klammern

{} Geschweifte Klammern alternativ

{ON OFF } Einer der durch getrennte Parameter ist einzugeben – ohne Klammern und senkrechten Strich

Wiederholung n,n,... Beliebig wiederholbar ( ) Runde Klammern

SUM (variable) Runde Klammern ( ) schließen die Parameter einer Funktion ein

Unterstrichen Select {alldistinct} … Anzeige Standardwert

Page 9: SQL Befehle 30 - gdi.de · SQL arbeitet im Gegensatz hierzu mengenorientiert. Man gibt an, welche Bedingung erfüllt sein muss, der Rest erledigt das System und man erhält die Ergebnismenge

GDI-SQL-Seminar 19.03.2018 Seite 9/57

2.2 Wo kann man SQL in der GDILine 2.x/Bline 3.x einsetzen? Wo kann man innerhalb der GDILINE/BLine SQL-Anweisungen einsetzen?

• Klassischer Einsatzort: Menüpunkt Zusatz | SQL-System

• Reportdesigner/FastReporter: Erstellen von Reports auf Basis von SQLs ( SQL-Ergebnisstabellen)

• GDI-BASIC: Innerhalb von GDI-BASIC können SQL-Anweisungen durchgeführt werden, z.B.

Zusammenfassen von Daten zu Zwischenergebnissen, welche mit GDI-BASIC weiterverarbeitet

werden. à Kombination von prozeduralen Sprachelementen mit SQL. 2.3 Aufbau des Menüpunktes Zusatz | SQL-System GDILine 2.x:

Unter dem Menüpunkt Zusatz | SQL-System findet man eine Maske mit drei Karteireitern:

• Kartei "SQL": Beinhaltet oben eine ComboBox zur Auswahl von gespeicherten SQL-

Anweisungen. In der linken Hälfte Erfassungstabelle von Variablen, rechts Anzeige eines

Kommentartextes (Beschreibung).

• Kartei "Ergebnistabelle": Wird eine SQL-Abweisung ausgeführt, die als Ergebnis eine

Datenmenge zurückliefert (Ergebnistabelle), so wird nach Beendigung der SQL zu diesem

Karteireiter gewechselt und das Ergebnis angezeigt. Von hier aus kann ein Ausdruck oder eine

Übernahme in Excel erfolgen (Hinweis: CSV-Trenner in Systemdateneinstellungen einstellbar).

Man kann hier auch direkt die Originaltabellen öffnen und Daten beauskunften oder ändern

(Achtung. Direkte Datenmanipulation unter Umgehung von Sicherheitsabfragen etc....!)

• Kartei "SQL editieren": Die Erfassung und Verwaltung von SQL-Anweisungen erfolgt auf diesem

Karteireiter im Eingabefeld der linken Bildschirmhälfte. Rechts oben werden zur Information die

in der Datenbank vorhandenen Tabellen angezeigt, darunter – sofern man eine Tabelle markiert hat

– die in der Tabelle vorhandenen Datenfelder und ihre Feldtypdefinition. GDI-Business-Line 3.x:

Auch hier ist das SQL-System unter dem Menüpunkt Zusatz | SQL-System zu finden. Der Aufbau und

die Funktionen dieses (neuen) SQL-Systemes sind in der Datei "SQLSystem.pdf" im

Hilfeverzeichnis beschrieben.

Page 10: SQL Befehle 30 - gdi.de · SQL arbeitet im Gegensatz hierzu mengenorientiert. Man gibt an, welche Bedingung erfüllt sein muss, der Rest erledigt das System und man erhält die Ergebnismenge

GDI-SQL-Seminar 19.03.2018 Seite 10/57

2.4 SQL-Syntax 2.4.1 Übersicht über die SQL-Basis-Sprachelemente 1. Data-Manipulation-Language DML

• SELECT • INSERT • UPDATE • DELETE • LOCK • COMMIT • ROLLBACK 2. Data-Definition-Language DDL

• CREATE

• ALTER

• DROP • COMMENTON 3. Data-Control-Language DCL

• GRANT

• REVOKE

Im Rahmen dieser Schulung werden wir uns auf eine Auswahl dieser Kommandos be-schränken.

Page 11: SQL Befehle 30 - gdi.de · SQL arbeitet im Gegensatz hierzu mengenorientiert. Man gibt an, welche Bedingung erfüllt sein muss, der Rest erledigt das System und man erhält die Ergebnismenge

GDI-SQL-Seminar 19.03.2018 Seite 11/57

2.4.2 Datentypen • CHAR, VARCHAR Alphanumerische Daten • DATE Datumsformat (Datum plus Uhrzeit) • SMALLINT Ganzzahl, 16-bit, vorzeichenbehaftet, von +-32767 • INTEGER Ganzzahl, 32-bit, vorzeichenbehaftet, von +- 2147483647 • FLOAT Fließkommazahl Darüber hinaus sind noch weitere Datentypen vorhanden, die in unserem Zusammenhang jedoch nicht bzw. weniger von Bedeutung sind. z.B. MEMO, BLOB 2.4.3 Grundformat des SELECT-Statements SELECT [ALL DISTINCT] {* Tabellenname. Label.] Spaltenname Ausdruck

[,Tabellenname. Label.] Spaltenname Ausdruck,..]]} FROM Tabellenname [Label] [, Tabellenname [Label]...]. [WHERE Bedingung] [GROUP BY [Tabellenname. Label.] Spaltenname [,Tabellenname. Label.] Spaltenname,... ]] [HAVING Bedingung] [ORDER BY {[Tabellenname. Label.] Spaltenname Position [ASC DESC] [[Tabellenname. Label.] Spaltenname Position [ASC DESC...]};

DEFINITION:

Der SELECT- Befehl dient dazu, die in der Datenbank gespeicherten Daten nach bestimmten Kriterien auswerten zu können.

Die Anwendung seiner Befehlsstruktur setzt eine korrekte relationale Struktur der Datenbank voraus.

Merke: Mittels des SELECT-Befehls wird nur das WAS der Abfrage, nicht das WIE

definiert.

Als Ergebnis liefert der SELECT-Befehl eine Datenmenge!

Page 12: SQL Befehle 30 - gdi.de · SQL arbeitet im Gegensatz hierzu mengenorientiert. Man gibt an, welche Bedingung erfüllt sein muss, der Rest erledigt das System und man erhält die Ergebnismenge

GDI-SQL-Seminar 19.03.2018 Seite 12/57

2.4.4 Selektieren von Daten ohne Bedingungen

Beispiel 1

Selektion aller Spalten und aller Zeilen der Tabelle vertret;

SELECT * FROM vertret;

Beispiel 2

Selektion aller Adressnummern von der Tabelle adumsatz;

SELECT adressnr FROM adumsatz; Hierbei können die einzelnen Adressnummern mehrfach auftreten. Um dies zu vermeiden, muss das SELECT-Statement folgendermaßen formuliert werden:

Beispiel 3

SELECT DISTINCT adressnr FROM adumsatz;

Soll die Ausgabe darüberhinaus nach Adressnummern sortiert sein, muss weiter spezifiziert wer-den:

Beispiel 4

SELECT DISTINCT adressnr FROM adumsatz ORDER BY adressnr;

Beispiel 5

Die Werte der Felder adressnr und jahr werden folgendermaßen selektiert:

SELECT adressnr, jahr FROM adumsatz;

Page 13: SQL Befehle 30 - gdi.de · SQL arbeitet im Gegensatz hierzu mengenorientiert. Man gibt an, welche Bedingung erfüllt sein muss, der Rest erledigt das System und man erhält die Ergebnismenge

GDI-SQL-Seminar 19.03.2018 Seite 13/57

Soll die Ausgabe nach Adressnummer absteigend sortiert sein, lautet das SELECT-Statement: SELECT adressnr, jahr FROM adumsatz ORDER BY adressnr DESC; Alternativ möglich: SELECT adressnr, jahr FROM adumsatz ORDER BY 1 DESC; Man gibt also statt des Feldnamens (Spaltenname) die Spaltennummer in der "order by" -Klausel an. In den bisherigen Beispielen wurden die Spaltenbezeichnungen der Ergebnistabelle aus den Feldnamen gebildet. Bei Bedarf kann man eigene Spaltenbezeichnungen über die Angabe von sog. Alias-Bezeichnern vorgeben. In folgendem Beispiel wird daher die Spalte, welche die adressnr ausgibt, mit „Nummer“ bezeichnet sein: SELECT adressnr Nummer, jahr FROM adumsatz ORDER BY 1 DESC; oder auch: SELECT adressnr Nummer, jahr FROM adumsatz ORDER BY Nummer DESC; Hinweis zu älteren Firebird-Versionen (2.0.x und früher): Der Alias-Bezeichner durfte bei älteren FireBird-Versionen nicht in der "order by"-Klausel verwendet werden. Hier war entweder der Spaltenname oder die Spaltennummer anzugeben!

Natürlich können in einer SQL-Anweisung auch mehrere Sortierkriterien angegeben werden, z.B.

ORDER BY adressnr DESC, jahr... usw.

Page 14: SQL Befehle 30 - gdi.de · SQL arbeitet im Gegensatz hierzu mengenorientiert. Man gibt an, welche Bedingung erfüllt sein muss, der Rest erledigt das System und man erhält die Ergebnismenge

GDI-SQL-Seminar 19.03.2018 Seite 14/57

2.4.5 Bedingte Selektion Durch die WHERE-Klausel wird definiert, welchen Bedingungen die zu selektierenden Zeilen genügen müssen: 2.4.5.1 Grundform der WHERE-Klausel

DEFINITION:

Eine WHERE- Klausel besteht aus einer oder mehreren Bedingungen, die durch logische Operatoren miteinander verknüpft werden können und zwar in der Form: Bedingung [logischer Operator Bedingung] Logische Operatoren sind: AND, OR, NOT Dabei besteht eine Bedingung immer aus drei Elementen: Ausdruck Operator Ausdruck Ein Ausdruck selbst kann sein: a) ein Spaltenname b) eine numerische Konstante (z.B. 1000) c) eine alphanumerische Konstante (z.B. ,Ferdinand') d) eine Funktion (z.B. sum(umsatz)) e) ein arithmetischer Ausdruck (z.B. a * b) Oder ein weiterer SELECT- Befehl (SUBSELECT)

Page 15: SQL Befehle 30 - gdi.de · SQL arbeitet im Gegensatz hierzu mengenorientiert. Man gibt an, welche Bedingung erfüllt sein muss, der Rest erledigt das System und man erhält die Ergebnismenge

GDI-SQL-Seminar 19.03.2018 Seite 15/57

2.4.5.2 Vergleichs-Operatoren

Ausdruck Operator Ausdruck Bedeutung

a = b gleich a <> b ungleich a != b ungleich a ^= b ungleich a > b größer a >= b größer gleich a < b kleiner a <= b kleiner gleich 2.4.5.3 Wirkungsweise einer einfachen WHERE-Klausel

DEFINITION:

Im Gegensatz zur SELECT-Klausel, welche die horizontale Untermenge der zu selektierenden Spalten bestimmt, definiert die WHERE-Klausel die vertikale Untermenge der zu selektierenden Zeilen.

Beispiel 1 Selektion der Adress-Nummer, des jeweiligen Jahres und des Umsatzes der Periode 1 (i.d.R. Januar-Umsatz) pro Filiale aus der Tabelle ADUMSATZ der Adress-Nummer 10000. SELECT adressnr, jahr, Filiale, Umsatz1 FROM adumsatz WHERE adressnr = 10000; Beispiel 2 Selektion der Adress- Nummer, des jeweiligen Jahres und des Januar-Umsatzes pro Filiale aus der Tabelle ADUMSATZ der Adress- Nummern, die ungleich 10000 sind. SELECT adressnr, jahr, Filiale, Umsatz1 FROM adumsatz WHERE adressnr != 10000;

Page 16: SQL Befehle 30 - gdi.de · SQL arbeitet im Gegensatz hierzu mengenorientiert. Man gibt an, welche Bedingung erfüllt sein muss, der Rest erledigt das System und man erhält die Ergebnismenge

GDI-SQL-Seminar 19.03.2018 Seite 16/57

Beispiel 3 Selektion der Adress-Nummer, des jeweiligen Jahres und des Januar-Umsatzes pro Filiale aus der Tabelle ADUMSATZ der Adress-Nummern, die größer 10000 sind. SELECT adressnr, jahr, Filiale, Umsatz1 FROM adumsatz WHERE adressnr > 10000; Beispiel 4 Selektion der Adress-Nummer, des jeweiligen Jahres und des Januar-Umsatzes pro Filiale aus der Tabelle ADUMSATZ der Adress-Nummern, die größer gleich 10000 sind. SELECT adressnr, jahr, Filiale, Umsatz1 FROM adumsatz WHERE adressnr >= 10000; Beispiel 5 Selektion der Artikelnummer, der Artikelbezeichnung, des Skonto-Kennzeichens aller Artikel, für die gilt, dass das Skontokennzeichen gleich 0 ist. SELECT artikelnr, arttext, kzskonto FROM artikel where kzskonto = "0";

WICHTIG: Es werden hier nur Datensätze ausgegeben, die in dem Datenfeld den Wert "0" besitzen. Datensätze mit "leerem" Eintrag werden nicht erfasst. Man muss beachten, welchen Defaultwert ein Datenfeld besitzt. Diesen Wert besitzt das Datenfeld, wenn ein Datensatz neu im System angelegt wird. Auszug aus der Datei GDI_Domain.Meta. In dieser Datei sind u.a. die Datentypen der Bline definiert: CREATE DOMAIN GDI_CHAR1 AS CHAR(1) DEFAULT ''; -- CREATE DOMAIN GDI_CHAR2 AS VARCHAR (2) DEFAULT ''; -- CREATE DOMAIN GDI_CHAR3 AS VARCHAR (3) DEFAULT ''; -- ... ... -- CREATE DOMAIN GDI_CHAR255 AS VARCHAR(255) DEFAULT ''; -- CREATE DOMAIN GDI_CHAR400 AS VARCHAR(400) DEFAULT '';

Page 17: SQL Befehle 30 - gdi.de · SQL arbeitet im Gegensatz hierzu mengenorientiert. Man gibt an, welche Bedingung erfüllt sein muss, der Rest erledigt das System und man erhält die Ergebnismenge

GDI-SQL-Seminar 19.03.2018 Seite 17/57

-- CREATE DOMAIN GDI_CHAR2000 AS VARCHAR(2000) DEFAULT ''; -- CREATE DOMAIN GDI_CHAR8000 AS VARCHAR(8000) DEFAULT ''; -- CREATE DOMAIN GDI_CHAR32000 AS VARCHAR(32000) DEFAULT ''; -- CREATE DOMAIN GDI_MD5STR AS CHAR(32) DEFAULT ''; -- CREATE DOMAIN GDI_UUID AS CHAR(36) DEFAULT ''; -- CREATE DOMAIN GDI_SHORT AS SMALLINT DEFAULT 0 NOT NULL; -- CREATE DOMAIN GDI_LONG AS INTEGER DEFAULT 0 NOT NULL; -- CREATE DOMAIN GDI_FLOAT AS DOUBLE PRECISION DEFAULT 0 NOT NULL; -- CREATE DOMAIN GDI_DATE AS TIMESTAMP; -- CREATE DOMAIN GDI_MEMO AS BLOB SUB_TYPE 1 SEGMENT SIZE 2048; -- CREATE DOMAIN GDI_BINARY AS BLOB SEGMENT SIZE 2048; -- Besitzt ein Datenfeld keine Defaultwert-Definition, so würde das Datenfeld nach Neuanlage eines Datensatzes den Wert "null" (= "nichts") besitzen, und zwar bis zu dem Zeitpunkt, zu dem in dem Datenfeld ein konkreter Eintrag gespeichert würde. Bitte beachten Sie, dass

• nur bei numerischen Feldern neben der Defaultwertvorgabe noch die Zusatzbedingung "NOT NULL" angegeben ist.

• "null"-Werte durch (eigene) Datenimporte oder update-Anweisungen entstehen können Beispiel 6 Selektion der Artikelnummer, der Artikelbezeichnung, des Skonto-Kennzeichens aller Artikel, für die gilt, dass das Skontokennzeichen keinen Eintrag besitzt. SELECT artikelnr, arttext, kzskonto FROM artikel where kzskonto = "";

Beispiel 7 Selektion der Artikelnummer, der Artikelbezeichnung, des Skonto-Kennzeichens aller Artikel, für die gilt, dass das Skontokennzeichen den Wert "null" besitzt. Diesen Fall gibt es in der FireBird -Version der GDILine eigentlich nicht. SELECT artikelnr, arttext, kzskonto FROM artikel where kzskonto is null;

Page 18: SQL Befehle 30 - gdi.de · SQL arbeitet im Gegensatz hierzu mengenorientiert. Man gibt an, welche Bedingung erfüllt sein muss, der Rest erledigt das System und man erhält die Ergebnismenge

GDI-SQL-Seminar 19.03.2018 Seite 18/57

2.4.5.4 Wirkungsweise einer durch die Verwendung von logischen Operatoren komplexeren

WHERE-Klausel

DEFINITION:

1. Der AND-Operator

Es werden nur die Zeilen selektiert, die jede Bedingung des jeweiligen Ausdrucks erfüllen.

Beispiel: Selektion der Artikelnummer, der Artikelbezeichnung, des Provisions- und Skonto-Kennzeichens aller Artikel, für die gilt, dass sowohl das Provisions- und als auch das Skontokennzeichen gleich 0 sind. SELECT artikelnr, arttext, kzprov, kzskonto FROM artikel where kzprov = "0" and kzskonto = "0";

An dieser Stelle nochmals der Hinweis auf Defaultwerte (s o.)!

DEFINITION:

2. Der OR-Operator

Es werden nur die Zeilen selektiert, die mindestens eine Bedingung des jeweiligen Ausdrucks erfüllen.

Beispiel: Selektion der Artikelnummer, der Artikelbezeichnung, des Provisions- und Skonto-Kennzeichens aller Artikel, für die gilt, dass entweder das Provisions- oder das Lagerkennzeichen gleich 0 sind. SELECT artikelnr, arttext, kzprov, kzskonto FROM artikel where kzprov = "0" or kzlager = "0";

Page 19: SQL Befehle 30 - gdi.de · SQL arbeitet im Gegensatz hierzu mengenorientiert. Man gibt an, welche Bedingung erfüllt sein muss, der Rest erledigt das System und man erhält die Ergebnismenge

GDI-SQL-Seminar 19.03.2018 Seite 19/57

DEFINITION:

3. Kombinationen von AND und OR

Vorsicht: AND hat höhere Priorität als OR - deshalb immer richtig klammern!

Beispiel: Selektion der Artikelnummer, der Artikelbezeichnung, des Provisions- und Skonto-Kennzeichens aller Artikel, für die gilt, dass entweder das Provisions- und das Skontokennzeichen oder aber das Lagerkennzeichen gleich 0 sind. SELECT artikelnr, arttext, kzprov, kzskonto FROM artikel where (kzprov = "0" and kzskonto = "0") or kzlager = "0"; Wird die Klammerung etwas verändert, ergibt sich ein völlig anders Ergebnis: Selektion der Artikelnummer, der Artikelbezeichnung, des Provisions- und Skonto-Kennzeichens aller Artikel, für die gilt, dass das Provisionskennzeichen gleich 0 ist und entweder das Skontokennzeichen oder das Lagerkennzeichen gleich 0 sind. SELECT artikelnr, arttext, kzprov, kzskonto FROM artikel where kzprov = "0" and (kzskonto = "0" or kzlager = "0");

DEFINITION:

4. Der NOT-Operator

Mittels des NOT-Operators wird eine Bedingung verneint. Er ist zusammen mit allen Ausdrücken und Operatoren einsetzbar.

Beispiel: Selektion der Artikelnummer, der Artikelbezeichnung, des Provisions-, Skonto- und Lagerkennzeichens aller Artikel, für die gilt, daß entweder das Provisions- und das Skontokennzeichen gleich 0 oder das Lagerkennzeichen nicht gleich 0 ist. SELECT artikelnr, arttext, kzprov, kzskonto, kzlager FROM artikel where (kzprov = "0" and kzskonto = "0") or not kzlager = "0";

Page 20: SQL Befehle 30 - gdi.de · SQL arbeitet im Gegensatz hierzu mengenorientiert. Man gibt an, welche Bedingung erfüllt sein muss, der Rest erledigt das System und man erhält die Ergebnismenge

GDI-SQL-Seminar 19.03.2018 Seite 20/57

2.4.6 Funktionen 2.4.6.1 Standardfunktionen SQL kennt fünf Standardfunktionen: • AVG Durchschnitt

• SUM Summe

• MAX Maximum

• MIN Minimum

• COUNT Anzahl

DEFINITION:

Diese Funktionen können nur spaltenbezogen (d.h.: in der SELECT-Klausel) verwendet werden, weshalb sie in der WHERE-Klausel unzulässig sind, denn diese arbeitet ja auf Zeilenniveau.

Weitere als die im folgenden erläuterten Möglichkeiten ergehen sieh in Kombination mit der GROUP BY- und der HAVING-Klausel. (siehe Abschnitt 2.4.10)

2.4.6.1.1 Die AVG-Funktion Syntax: AVG(n)

DEFINITION:

Die AVG-Funktion ermittelt den Mittelwert eines numerischen Elements -dies gilt auch für Untermengen. Vorsicht bei Spalten, NULL-Werte enthalten, da diese ignoriert werden

Page 21: SQL Befehle 30 - gdi.de · SQL arbeitet im Gegensatz hierzu mengenorientiert. Man gibt an, welche Bedingung erfüllt sein muss, der Rest erledigt das System und man erhält die Ergebnismenge

GDI-SQL-Seminar 19.03.2018 Seite 21/57

Selektion des Durchschnitts aller Gesamtbeträge der Tabelle belegpos. SELECT AVG (gesamt) FROM belegpos; 2.4.6.1.2 Die SUM-Funktion Syntax: SUM(n)

DEFINITION:

Die SUM-Funktion ermittelt die Summe eines numerischen Elements - dies gilt auch für Untermengen. Vorsicht bei Spalten, die NULL-Werte enthalten!

Selektion der Summe aller Gesamtbeträge der Tabelle belegpos. SELECT SUM(gesamt) FROM belegpos; 2.4.6.1.3 Die MAX-Funktion Syntax: MAX(Spalte)

DEFINITION:

Die MAX-Funktion ermittelt den größten Wert in einer Spalte - dies gilt auch für Untermengen.

Selektion des größten Gesamtbetrages der Tabelle belegpos. SELECT MAX(gesamt) FROM belegpos;

Page 22: SQL Befehle 30 - gdi.de · SQL arbeitet im Gegensatz hierzu mengenorientiert. Man gibt an, welche Bedingung erfüllt sein muss, der Rest erledigt das System und man erhält die Ergebnismenge

GDI-SQL-Seminar 19.03.2018 Seite 22/57

2.4.6.1.4 Die MIN-Funktion Syntax: MIN(Spalte)

DEFINITION:

Die MIN-Funktion ermittelt den kleinsten Wert in einer Spalte - dies gilt auch für Untermengen.

Selektion des kleinsten Gesamtbetrages der Tabelle belegpos. SELECT MIN(gesamt) FROM belegpos; 2.4.6.1.5 Die COUNT-Funktion Syntax: COUNT(*Spalte)

DEFINITION:

Die COUNT- Funktion wird entweder auf ganze Tabellen oder einzelne Spalten und bestimmt die Anzahl der mit Werten belegten Felder der jeweiligen Spalte oder die Anzahl Zeilen in der Tabelle. Vorsicht bei Spalten, die NULL-Werte enthalten!

Drei Varianten sind möglich: 1. Zählen aller Zeilen der Tabelle belegpos: SELECT COUNT(*) FROM belegpos; 2. Zählen aller belegten Skontokennzeichen in der Tabelle artikel: SELECT COUNT(kzskonto) FROM artikel; 3. Zählen der Felder mit unterschiedlichen Werten in der Spalte kzskonto der Tabelle artikel. D.h. wie

viele verschiedene Werte kommen in dem Feld kzskonto vor. SELECT COUNT(DISTINCT kzskonto) FROM artikel;

Page 23: SQL Befehle 30 - gdi.de · SQL arbeitet im Gegensatz hierzu mengenorientiert. Man gibt an, welche Bedingung erfüllt sein muss, der Rest erledigt das System und man erhält die Ergebnismenge

GDI-SQL-Seminar 19.03.2018 Seite 23/57

An dieser Stelle ein kleines Beispiel zur Verdeutlichung der NULL-Wert-Problematik. (Siehe auch Kapitel 2.4.6.2.4 auf Seite 27): Zunächst ist folgende SQL abzusetzen: Select count(*), count(KZADRART) from kunden Bei einem ordentlichen Datenbestand ist der Wert in beiden Ergebnispalten gleich. Anschließend bei einem Datensatz bewusst ein NULL-Wert setzen: Dann die erste SQL nochmals laufen lassen: Select count(*), count(KZADRART) from kunden Die beiden Spalten zeigen nun unterschiedliche Ergebnisse/Zahlen an. Bei Bedarf kann man noch ein “where KzAdrArt is null“ ergänzen. Vorsicht bei folgendem Problem: Wieviele Sätze in kunden gibt es mit plz ,67480' ? Falsch: SELECT plz, count(*) FROM kunden

WHERE plz= "67480"; Richtig: SELECT MIN (plz), COUNT(*) FROM kunden WHERE plz= "67480"; Hintergrund: Werden neben den Spalten, auf die Funktionen angewendet werden auch "normale"

Spalten ausgegeben, so muss eine Gruppierung auf die "normalen" Spalten angewendet werden. Diese wird hier durch die Zuweisung einer Konstanten in der where-Klausel erreicht.

Vorgriff auf Kapitel 2.4.10: Ausgabe der unterschiedlichen Postleitzahlen im Kundenstamm und ihrer Anzahl: SELECT plz, COUNT(*) FROM kunden GROUP BY plz

Page 24: SQL Befehle 30 - gdi.de · SQL arbeitet im Gegensatz hierzu mengenorientiert. Man gibt an, welche Bedingung erfüllt sein muss, der Rest erledigt das System und man erhält die Ergebnismenge

GDI-SQL-Seminar 19.03.2018 Seite 24/57

2.4.6.2 Spezielle Funktionen

• BETWEEN...AND ersetzt a >= wert1 and a <= wert2

• IN u.a. zur Definition mehrerer Konstanten

• LIKE zur Bearbeitung einer Suchmaske

• NULL zur Bearbeitung leerer Felder

2.4.6.2.1 Die BETWEEN AND - Funktion Syntax: [NOT] BETWEEN x AND y (größer gleich x, kleiner gleich y)

DEFINITION:

Um die etwas umständliche Formulierung mittels der Kombination von <= und >= umgehen zu können, bietet SQL die Möglichkeit, statt dessen mit der BETWEEN... AND-Funktion zu arbeiten.

Beispiel: Selektion von Kundendaten aller Kunden, deren Postleitzahl größer oder gleich ,60000‘ und kleiner gleich ,70000‘ ist. Statt: SELECT Kundennr,Name1, Name2, Plz, Ort FROM kunden WHERE plz >= "60000" and plz <= "70000"; kann formuliert werden: SELECT Kundennr,Name1, Name2, Plz, Ort FROM kunden WHERE plz between "60000" and "70000";

Page 25: SQL Befehle 30 - gdi.de · SQL arbeitet im Gegensatz hierzu mengenorientiert. Man gibt an, welche Bedingung erfüllt sein muss, der Rest erledigt das System und man erhält die Ergebnismenge

GDI-SQL-Seminar 19.03.2018 Seite 25/57

2.4.6.2.2 Die IN - Funktion

Syntax:[NOT] IN

DEFINITION:

Auch die IN-Funktion ermöglicht es (u.a.), die WHERE-Klausel kürzer zu formulieren. Beispiel: Selektion von Kundendaten aller Kunden, deren Postleitzahl gleich ,76829‘ oder gleich ‚67480‘ oder gleich ,67483‘ ist. Statt: SELECT Kundennr,Name1, Name2, Plz, Ort FROM Kunden where plz = "67480" or plz = "67483" or plz = "76829"; kann mittels der IN-Funktion formuliert werden: SELECT Kundennr,Name1, Name2, Plz, Ort FROM Kunden where plz in ("67480","67483","76829");

Page 26: SQL Befehle 30 - gdi.de · SQL arbeitet im Gegensatz hierzu mengenorientiert. Man gibt an, welche Bedingung erfüllt sein muss, der Rest erledigt das System und man erhält die Ergebnismenge

GDI-SQL-Seminar 19.03.2018 Seite 26/57

2.4.6.2.3 Die LIKE - Funktion Syntax: LIKE ‚[_...%]Ausdruck[_...%]...‘

DEFINITION:

Außer der Möglichkeit, auf vollständige Übereinstimmung zu vergleichen, bietet SQL auch die Möglichkeit, auf Teilelemente von Feldern zu selektieren. Für die Maskierung sind folgende Zeichen reserviert: _ (Unterstrich) als Platzhalter für ein beliebiges Zeichen an dieser Stelle, % als Platzhalter für eine beliebige Menge von Zeichen (auch 0!). Die LIKE-Funktion arbeitet case-sensitiv, d.h. Klein-/Groß-Schreibung wird beachtet.

Beispiele: Selektion von Kundendaten aller Kunden, deren Postleitzahl mit einer 6 beginnt. SELECT Kundennr,Name1, Name2, Plz, Ort FROM kunden WHERE plz like "6%"; Selektion Kundendaten aller Kunden, deren Postleitzahl mit einer 6 beginnt und mit einer 0 endet. SELECT Kundennr,Name1, Name2, Plz, Ort FROM kunden WHERE plz like "6%0"; Selektion von Kundendaten aller Kunden, deren Postleitzahl an der dritten Stelle eine 4 aufweist. SELECT Kundennr,Name1, Name2, Plz, Ort FROM kunden WHERE plz like "__4%"; Hinweis: In FireBird gibt es als weitere Funktion die CONTAINING-Funktion. Diese ist universeller, wenn es darum geht, Datensätze zu selektieren, welche eine bestimmte Zeichenkette enthalten. Containing arbeitet im Gegensatz zu like nicht case-sensitiv. Zum Vergleich: SELECT * FROM Kunden WHERE name1 like "%Comp%" SELECT * FROM Kunden WHERE name1 containing "comp"

Page 27: SQL Befehle 30 - gdi.de · SQL arbeitet im Gegensatz hierzu mengenorientiert. Man gibt an, welche Bedingung erfüllt sein muss, der Rest erledigt das System und man erhält die Ergebnismenge

GDI-SQL-Seminar 19.03.2018 Seite 27/57

2.4.6.2.4 Die NULL - Funktion Syntax: IS [NOT] NULL

DEFINITION:

Der NULL-Operator ist zur Behandlung sogenannter NULL-Felder unerlässlich. Dabei bedeutet NULL weder 0 noch ein Leerzeichen, sondern vielmehr, dass im entsprechenden Feld nichts steht!

Wie bereits erwähnt, sollten NULL-Werte in der FireBird-Datenbank nicht vorkommen; im Zweifelsfalle sollte man aber immer eine Prüfung vornehmen, da solche auch durch (eigene) Datenimporte entstanden sein können. Beispiel Selektion des Kundennamens und des Länderkürzels aller Kunden, bei denen kein Eintrag im Feld Postfach vorhanden ist. SELECT name1, land FROM kunden where postfach IS NULL; Selektion des Kundennamens und des Länderkürzels aller Kunden, bei denen ein Eintrag im Feld Postfach vorhanden ist. SELECT name1,land FROM kunden where postfach IS NOT NULL; Vorsicht: Selektion des Kundennamens und des Länderkürzels aller Kunden deren Adressgruppe ungleich 200 ist - NULL-Werte werden bei Vergleichen nicht berücksichtigt, d.h. hier erscheinen nur Kunden, die im Feld Adressgrp einen Eintrag besitzen. SELECT name1, land FROM kunden where adressgrp != "200";

Page 28: SQL Befehle 30 - gdi.de · SQL arbeitet im Gegensatz hierzu mengenorientiert. Man gibt an, welche Bedingung erfüllt sein muss, der Rest erledigt das System und man erhält die Ergebnismenge

GDI-SQL-Seminar 19.03.2018 Seite 28/57

2.4.6.3 Auswahl spezieller Character- Funktionen SQL bietet im Standard Funktionen zum Bearbeiten von Zeichenketten (Strings). Darüber hinaus bieten die verschiedenen Datenbanksysteme "eigene" Funktionen an bzw. es gibt Möglichkeiten, eigene Funktionen zu ergänzen. In der GDI-Business-Line werden z.B. solche eigenen Funktionen über die Dateien GDI_UDF.dll und GDI_UDF3.dll (im Firebird-UDF-Verzeichnis) verwaltet. • LOWER (Standard) und LOWERCASE (GDI) • UPPER (Standard) und UPPERCASE (GDI) • SUBSTR (Standard) und COPY (GDI) 2.4.6.3.1 Die LOWER - Funktion, Die LOWERCASE - Funktion Syntax: LOWER (Text)

DEFINITION:

Die LOWER - Funktion ersetzt in einem Text Groß- durch Kleinbuchstaben. In dieser Standard-Funktion blieben Umlaute lange Zeit (bis etwa Firebird 2.1) unberücksichtigt, weshalb GDI die eigene LOWERCASE implementierte.

Beispiel:

Selektion des kleingeschriebenen Namens

select lower(name1) from kunden; Syntax: LOWERCASE (Text)

DEFINITION:

Die LOWERCASE - Funktion ersetzt in einem Text Groß- durch Kleinbuchstaben. Umlaute werden bei dieser GDI-eigenen Funktion umgesetzt.

Beispiel:

Selektion des kleingeschriebenen Namens

select lowercase(name1) from kunden;

Page 29: SQL Befehle 30 - gdi.de · SQL arbeitet im Gegensatz hierzu mengenorientiert. Man gibt an, welche Bedingung erfüllt sein muss, der Rest erledigt das System und man erhält die Ergebnismenge

GDI-SQL-Seminar 19.03.2018 Seite 29/57

2.4.6.3.2 Die UPPER - Funktion, Die UPPERCASE - Funktion Syntax: UPPER(Text)

DEFINITION:

Die UPPER - Funktion ersetzt in einem Text Klein- durch Großbuchstaben. In dieser Standard-Funktion blieben Umlaute lange Zeit (bis etwa Firebird 2.1) unberücksichtigt, weshalb GDI die eigene UPPERCASE implementierte.

Beispiel:

Selektion des großgeschriebenen Namens

select upper(name1) from kunden;

Syntax: UPPERCASE (Text)

DEFINITION:

Die UPPERCASE - Funktion ersetzt in einem Text Klein- durch Großbuchstaben. Umlaute werden bei dieser GDI-eigenen Funktion umgesetzt.

Beispiel:

Selektion des großgeschriebenen Namens

select uppercase(name1) from kunden;

Page 30: SQL Befehle 30 - gdi.de · SQL arbeitet im Gegensatz hierzu mengenorientiert. Man gibt an, welche Bedingung erfüllt sein muss, der Rest erledigt das System und man erhält die Ergebnismenge

GDI-SQL-Seminar 19.03.2018 Seite 30/57

2.4.6.3.3 Die SUBSTR - Funktion, die COPY - Funktion Syntax:

Funktion Syntax Bemerkung SubStr SUBSTR (Feld, Startposition, Endposition) Standard-Interbase-udf-Funktion Copy COPY (Feld, Startposition, Anzahl) GDI-eigene-Funktion

DEFINITION:

Diese- Funktion(en) ermitteln eine Teilzeichenkette (Teilstring) aus einer Zeichenkette (String). Sinnvoll ist der Einsatz der GDI-eigenen Funktion Copy. Diese wurde implementiert, um eine Analogie zwischen GDI-BASIC und SQLs zu erreichen.

Beispiele:

Selektion der ersten 10 Stellen des Namens aus der Kundentabelle select Name1, substr(Name1,1,10) from Kunden; oder select Name1, copy(Name1,1,10) from Kunden; Selektion der Zeichen 2 bis 5 der Postleitzahl aus der Kundentabelle select plz, substr(plz,2,5) from Kunden; oder select plz, copy(plz,2,4) from Kunden;

Page 31: SQL Befehle 30 - gdi.de · SQL arbeitet im Gegensatz hierzu mengenorientiert. Man gibt an, welche Bedingung erfüllt sein muss, der Rest erledigt das System und man erhält die Ergebnismenge

GDI-SQL-Seminar 19.03.2018 Seite 31/57

2.4.7 Datentypenumwandlung mit CAST SYNTAX: CAST(Feldname as Datentyp)

DEFINITION:

Die CAST - Funktion ermöglicht das Wandeln eines Datentyps in einen anderen (sofern möglich). Dies ist z.B. von Bedeutung im Zusammenhang mit dem Befehl UNION (Zusammenfassen mehrerer Ergebnismengen) oder beim Import/Export von Daten. Man kann die Funktion aber auch zur Ausgabeformatierung benutzen (z.B. in Zusammenhang mit Funktion wie SubStrEx, Copy, UpperCase...., welche i.d.R ein Char255 zurück liefern).

Beispiele:

Umwandeln des Namens in Großbuchstaben und Formatierung auf 40 Zeichen (uppercase liefert 255 zurück): select Cast(uppercase(name1) as VarChar(40)), name1 from kunden; Selektion der ersten 5 Zeichen des Namens und Formatierung auf 40 Zeichen (substrex liefert 255 zurück): select cast(copy(name1 ,1, 5) as VarChar(5)) from kunden; Umwandeln der Postleitzahl (alphanumerisches Feld) in eine Zahl und Multiplikation: Select Plz, Cast(Plz as integer) * 2 from kunden where PLZ <> ""; Hinweis: Die Bedingung where PLZ <> "" ist notwendig, da es sonst bei Datensätzen ohne PLZ zu einem Typkonvertierungsfehler kommt. An dieser Stelle sei auch auf die vielfältigen UDF-Funktionen verwiesen, welche den SQL-Funktionsumfang deutlich erweitern à siehe separate Dokumentation

Page 32: SQL Befehle 30 - gdi.de · SQL arbeitet im Gegensatz hierzu mengenorientiert. Man gibt an, welche Bedingung erfüllt sein muss, der Rest erledigt das System und man erhält die Ergebnismenge

GDI-SQL-Seminar 19.03.2018 Seite 32/57

2.4.8 Mathematische Bearbeitung

DEFINITION:

Der Begriff Ausdruck wurde bereits definiert: Er kann ein Spaltenname, eine Konstante, eine Funktion oder ein mathematischer Ausdruck sein. Ein mathematischer Ausdruck kann Summe, Differenz, Produkt oder Division sein, wobei gilt: + Addition - Subtraktion * Multiplikation

/ Division

Als Termen oder Faktoren eines mathematischen Ausdrucks können - analog zu einem Ausdruck - wiederum Spaltennamen, Konstanten, Funktionen oder mathematische Ausdrücke verwendet werden. Vorsicht bei Spalten die NULL-Werte enthalten ! Subtraktion und Addition können auch direkt auf Datumsfelder angewendet werden.

Beispiele: Selektion des Artikels, des Einzelpreises, der Menge und des doppelten Gesamtpreises: select artikelnr, epreis, menge, gesamt*2 from belegpos; Selektion des durchschnittlichen Gesamtwertes pro Belegposition: select sum(gesamt) / count(*) from belegpos; Selektion von verschiedenen Belegpositionswerten von Verkaufs-Rechnungspositionen und Ermittlung des Positionserlöses. select artikelnr, Belegnr, Datumpr, epreis, menge, Gesamt, Lagerpr, EKGesamt, (Lagerpr - EKgesamt) Erloes from belegpos where Belegtyp = "V" and Belegart = "RE" and Artikelnr <> ""; An dieser Stelle sei noch auf die GDI-eigene UDF-Funktion RUNDEN verwiesen. Mit dieser Funktion kann ein Ergebnis kaufmännisch gerundet werden. Beispiel: Select Artikelnr, (Laenge/Breite), Runden(Laenge/Breite,2) from Artikel where Breite <> 0; Ergänzung: Eine Zusammenfassung zweier Zeichenketten erfolgt in SQL über das doppelte Pipe-zeichen ("||"): Beispiel: select Kundennr, name1 || " " || name2 Adresse from Kunden;

Page 33: SQL Befehle 30 - gdi.de · SQL arbeitet im Gegensatz hierzu mengenorientiert. Man gibt an, welche Bedingung erfüllt sein muss, der Rest erledigt das System und man erhält die Ergebnismenge

GDI-SQL-Seminar 19.03.2018 Seite 33/57

2.4.9 DATUMSFUNKTIONEN Datumsfelder beinhalten (in der FireBird-Version) immer die Uhrzeit (DateTime). In vielen Fällen möchte man nur einen bestimmten Teil des Datums abgreifen. 2.4.9.1 GetDate Syntax: GetDate(Datumsfeld)

DEFINITION:

Die Funktion GetDate liefert aus einem Datumsfeld nur das Datum zurück. Die Zeitinformation wird "abgetrennt". Nur bei Interbase/FireBird.

Beispiel: Selektion der Verkaufsrechnungs-Belege eines Tages select * from beleg where Belegtyp = "V" and Belegart = "RE" and GetDate(Belegdat) = "03.06.2002"; Selektion aller Belege des aktuellen Tages select * from beleg where GetDate(Belegdat) = GetDate("NOW"); 2.4.9.2 EXTRACT Syntax: Extract(Year from Datumsfeld)

DEFINITION:

Die Funktion Extract liefert aus einem Datumsfeld nur das Datum zurück. Die Zeitinformation wird "abgetrennt". Standardfunktion.

Beispiel: select Belegdat, Extract(Year from Belegdat), Extract(Month from Belegdat), Extract(Day from Belegdat) from Beleg; Alternativ gibt es hierzu auch GDI-eigene Funktionen GetYear, GetMonth, GetDay (analog zu GetDate).

Page 34: SQL Befehle 30 - gdi.de · SQL arbeitet im Gegensatz hierzu mengenorientiert. Man gibt an, welche Bedingung erfüllt sein muss, der Rest erledigt das System und man erhält die Ergebnismenge

GDI-SQL-Seminar 19.03.2018 Seite 34/57

2.4.10 Gruppierungs-Funktion GROUP BY Syntax: SELECT – Klausel FROM – Klausel GROUP BY [Spaltenname,...]

DEFINITION:

Die GROUP BY - Funktion liefert einerseits a) einmalige Zeilen in der Ergebnistabelle (analog DISTINCT) und erlaubt es andererseits b) Funktionen auf Untermengen von Spaltenwerten anzuwenden.

Beispiel für a): Selektion der unterschiedlichen Postleitzahlen in der Kundentabelle select distinct plz from kunden; führt zum gleichen Ergebnis wie: select plz from kunden group by plz; Beispiel für b) Selektion der kumulierten Netto-Umsätze pro Artikel in Verkaufsrechnungen in Hauswährung: select artikelnr, sum(lagerpr) from belegpos where Belegtyp = "V" and Belegart = "RE" group by artikelnr oder: Selektion der unterschiedlichen Postleitzahlen im Kundenstamm und ihrer Anzahl select plz, count(plz) from kunden group by plz;

Page 35: SQL Befehle 30 - gdi.de · SQL arbeitet im Gegensatz hierzu mengenorientiert. Man gibt an, welche Bedingung erfüllt sein muss, der Rest erledigt das System und man erhält die Ergebnismenge

GDI-SQL-Seminar 19.03.2018 Seite 35/57

2.4.11 Unter-Gruppierungs-Funktion HAVING Syntax: SELECT – Klausel FROM – Klausel GROUP BY [Spaltenname,...] HAVING [Bedingung]

DEFINITION:

Die HAVING-Klausel selektiert Zeilen aus der Ergebnismenge, die durch die Anwendung der GROUP BY - Klausel entstanden ist.

Beispiel:

Selektion der kumulierten Umsätze pro Artikel mit mehr als 2000.- Umsatz

select artikelnr, sum(lagerpr) from belegpos where Belegtyp = "V" and Belegart = "RE" group by artikelnr having sum(lagerpr)> 2000;

Page 36: SQL Befehle 30 - gdi.de · SQL arbeitet im Gegensatz hierzu mengenorientiert. Man gibt an, welche Bedingung erfüllt sein muss, der Rest erledigt das System und man erhält die Ergebnismenge

GDI-SQL-Seminar 19.03.2018 Seite 36/57

2.4.12 Verbinden von Tabellen Sollen Daten aus mehreren Tabellen selektiert werden, so muß definiert werden, wie die Datensätze der Tabellen untereinander in Beziehung stehen. Gibt man die Beziehung nicht an, so wird als Ergebnis ein kartesisches Produkt (Kreuzprodukt) gebildet, d.h. jede Zeile der einen wird mit jeder Zeile der anderen Tabelle verknüpft. Dies ist meist nicht erwünscht und kann bei größeren Tabellen den Rechner lahmlegen! 2.4.12.1 JOIN / OUTER JOIN Syntax: SELECT [Ausdruck,...]

FROM [[Eigentümer.] Tabellenname [Alias],...] WHERE...

DEFINITION:

Um die Vorteile einer relationalen Datenbank auch vollständig nutzen zu können, ist es notwendig, Werte aus den unterschiedlichen Tabellen auch zusammenführen zu können. Als erstes (und zentrale) Werkzeug hierzu dient der JOIN. Der JOIN selbst ist nicht explizit als Befehl vorhanden, sondern er wird implizit durch die Verwendung der folgenden neuen Elemente im SELECT-Befehl vollzogen:

1. Der Zusatz eines ALIAS-Namens hinter dem Tabellennamen

2. Die Angabe einer Tabellenliste nach der FROM-Klausel

3. Die verpflichtende Angabe einer WHERE-Klausel Beispiel: Selektion der Kundennummer und der Postleitzahl der jeweiligen Bank (Version 1.8): select a.kundennr, b.plz from kunden a, blz b where a.blz = b.blz; Beispiel: Selektion der Adressnr, des Januar-Umsatzes über alle Filialen im Jahr 2011 und des Kunden-Namens select a.Adressnr, k.name1, a.jahr, sum(a.Umsatz1) from adumsatz a, kunden k where a.adressnr = k.kundennr and a.jahr = "2011" group by a.Adressnr, k.name1, a.jahr

Page 37: SQL Befehle 30 - gdi.de · SQL arbeitet im Gegensatz hierzu mengenorientiert. Man gibt an, welche Bedingung erfüllt sein muss, der Rest erledigt das System und man erhält die Ergebnismenge

GDI-SQL-Seminar 19.03.2018 Seite 37/57

WICHTIG: In der "Group By"-Klausel können bei Interbase/FireBird keine Aliasnamen bzw. Spaltennummern angegeben werden. Es müssen immer die Spaltennamen verwendet werden! Selektion von Daten aus Beleg und Belegpos-Tabelle. Hier bezieht sich die Join- Bedingung notwendigerweise auf drei Datenfelder: Select B.Belegnr, B.Adressnr, B.Name1, BP.Artikelnr, BP.Menge, BP.Epreis, BP.Gesamt From Beleg B, Belegpos BP Where B.Belegtyp = BP.Belegtyp and B.Belegart = BP.Belegart and B.Belegnr = BP.Belegnr and B.Belegtyp = "V" and B.Belegart = "RE"; Die where-Klausel wird in diesem Beispiel zur Definition der JOIN-Bedingung und wie in den bisherigen Beispielen zur Einschränkung der "Grunddatenmenge" (Filter) benutzt. Verschiedene Arten eines JOIN 1. Der EQUI-JOIN (INNER-JOIN)

Abfrage auf Gleichheit (meistgebrauchter JOIN, siehe obige Beispiele) 2. Der NON-EQUI-JOIN

Abfrage auf Ungleichheit 3. Der MULT1WAY-JOIN

Kombination von verschiedenen Bedingungen in einer Abfrage auf mehrere Tabellen

4. Der OUTER-JOIN Syntax:

SELECT [Ausdruck,...] FROM [ Tabellenname [Alias]] LEFT OUTER JOIN [ Tabellenname [Alias]]

ON... Where…

Um sinnvolle Ergebnisse beim Verknüpfen mehrerer Tabellen in SQL-Abfragen zu erhalten, muss die logische Verknüpfung zwischen den Tabellen angegeben werden. Dies erfolgt wie bereits gezeigt in einem sog. JOIN. In der Regel verwendet man den sog. INNER-JOIN, bei dem ausschließlich die innerhalb beider Tabellen vorhandenen Zeilen mit gleichem Schlüsselwert berücksichtigt werden. Zur Verdeutlichung nochmals ein Beispiel: Durch die nachfolgende SQL werden nur die Kunden ausgegeben, für die auch ein entsprechender Datensatz in der Adumsatz-Tabelle vorhanden ist. Kunden ohne Datensatz in der Adumsatz-Tabelle erscheinen in der Ergebnistabelle nicht (z.B. neu erfasste Kunden ohne Umsatz).

Page 38: SQL Befehle 30 - gdi.de · SQL arbeitet im Gegensatz hierzu mengenorientiert. Man gibt an, welche Bedingung erfüllt sein muss, der Rest erledigt das System und man erhält die Ergebnismenge

GDI-SQL-Seminar 19.03.2018 Seite 38/57

/*Kundenumsatz 2012 Periode 1-12*/ SELECT k.Kundennr, k.Adressgrp, k.name1, k.name2, k.Strasse, k.PLZ, k.Ort, a.jahr, a.filiale, a.umsatz1 + a.umsatz2 + a.umsatz3 + a.umsatz4 + a.umsatz5 +a.umsatz6 + a.umsatz7 + a.umsatz8 + a.umsatz9 + a.umsatz10 + a.umsatz11 + a.umsatz12 as Umsatz12 FROM kunden k, Adumsatz a WHERE k.kundennr = a.adressnr and a.Jahr = '2012' ORDER BY k.kundennr Neben dem inner-join gibt es den sog. OUTER-JOIN. Bei diesem ist zwischen der Haupttabelle und der nachgeordneten Tabelle zu unterscheiden. Von der Haupttabelle werden alle Datensätze ausgegeben, aus der nachgeordneten Tabelle werden (nur) die Datensätze genommen, bei denen eine Gleichheit durch die Join-Bedingung vorliegt. Je nach Daten-Konstellation und Join-Bedingung werden Datensätze der Haupttabelle heirbei "wiederholt" (wenn es in der nachgeordneten Tabelle mehrere "Treffer" gibt) oder "einmalig" (wenn es in der nachgeordneten Tabelle einen oder keinen "Treffer" gibt) ausgegeben. Gibt es in der nachgeordneten Tabelle keinen "Treffer", so enthält der Ergebnisdatensatz in den auf der nachgeordneten Tabelle basierenden Spalten Null-Werte. Wichtig sind die Schlüsselworte "left outer join" zwischen den Tabellen und die Einleitung der Join-Bedingung mit "on" statt "where". In der ON-Klausel müssen auf jeden Fall die sich entsprechenden Schlüsselfelder angegeben werden. Die where-Klausel steht für eine weitere Einschränkung (Filtern) außerhalb der Join-Bedingung. Beispiel: Durch die nachfolgende SQL werden alle Kunden der Kundentabelle ausgegeben, bei Kunden mit entsprechendem Datensatz aus der Adumsatz-Tabelle noch der dazugehörige Umsatzwert für 2012. /*Kundenumsatz 2012 Alle Kunden (outer join) Periode 1-12*/ SELECT k.Kundennr, k.Adressgrp, k.name1, k.name2, k.Strasse, k.PLZ, k.Ort, a.jahr, a.filiale, a.umsatz1 + a.umsatz2 + a.umsatz3 + a.umsatz4 + a.umsatz5 +a.umsatz6 + a.umsatz7 + a.umsatz8 + a.umsatz9 + a.umsatz10 + a.umsatz11 + a.umsatz12 as Umsatz12 FROM kunden k LEFT OUTER JOIN Adumsatz a ON k.kundennr = a.adressnr and a.Jahr = '2012' ORDER BY k.kundennr Anmerkung: Es wird zwischen Left- und Right-Outer-Join unterschieden, je nachdem welche Tabelle als Haupttabelle gelten soll. In der obigen Abfrage hätte man auch ... FROM Adumsatz a RIGHT OUTER JOIN Kunden k ON ... schreiben können (gleiches Ergebnis). Test: Testen Sie einmal das Verhalten bei (zusätzlichen) Bedingungen in der ON- und der WHERE-Klausel ! Z.B. zusätzlich die Filiale aus der Adumsatz-Tabelle einbeziehen oder einmal das Jahr aus der Adumsatz-Tabelle aus der ON-Klausel in die WHERE-Klausel stellen.

Page 39: SQL Befehle 30 - gdi.de · SQL arbeitet im Gegensatz hierzu mengenorientiert. Man gibt an, welche Bedingung erfüllt sein muss, der Rest erledigt das System und man erhält die Ergebnismenge

GDI-SQL-Seminar 19.03.2018 Seite 39/57

2.4.12.2 SUBQUERY / SUBSELECT (auch NESTED QUERY)

DEFINITION:

Eine SUBQUERY ist ein SELECT-Kommando, welches seinerseits Ergebnisse für ein übergeordnetes SELECT- Kommando liefert.

Syntax: SELECT [Ausdruck,...]

FROM [ [Eigentümer.] Tabellenname [Alias ],... ] WHERE Bedingung [,Bedingung...] {Vergleichsoperator Subselectoperator}

(SELECT....); Vergleichsoperatoren sind wie gehabt: = gleich != oder ˆ = ungleich > >= < <= größer, größer gleich, kleiner, kleiner gleich Subselectoperatoren sind: IN, NOT IN ANY, ALL EXISTS, NOT EXISTS

Page 40: SQL Befehle 30 - gdi.de · SQL arbeitet im Gegensatz hierzu mengenorientiert. Man gibt an, welche Bedingung erfüllt sein muss, der Rest erledigt das System und man erhält die Ergebnismenge

GDI-SQL-Seminar 19.03.2018 Seite 40/57

2.4.12.2.1 SUBSELECT ohne SUBSELECT-Operator

DEFINITION: Die Verwendung von Vergleichsoperatoren für ein SUBSELECT ist nur dann möglich, wenn das SUBSELECT lediglich einen Wert liefert! Beispiel: Selektion der Einzelposition mit dem höchsten Gesamtwert: select * from belegpos where gesamt =

(select max(gesamt) from belegpos);

2.4.12.2.2 SUBSELECT mit SUBSELECT-Operator

DEFINITION: Ein SUBSELECT-Operator liefert statt eines einzigen Wertes aus dem SUBSELECT eine

Menge von zutreffenden Werten. 1. Der IN-Operator im SUBSELECT Beispiele: select * from artikel where artikelnr in

(select artikelnr from belegpos where belegtyp = "E");

Page 41: SQL Befehle 30 - gdi.de · SQL arbeitet im Gegensatz hierzu mengenorientiert. Man gibt an, welche Bedingung erfüllt sein muss, der Rest erledigt das System und man erhält die Ergebnismenge

GDI-SQL-Seminar 19.03.2018 Seite 41/57

select * from artikel where artikelnr not in

(select artikelnr from belegpos where belegtyp = "E");

2. Der ALL- und ANY-Operator im SUBSELECT select * from liefer where liefernr > ALL

(select adressnr from bestell)

select * from liefer where liefernr < ANY (select adressnr from bestell) CORRELATED SUBQUERY und der EXISTS-Operator

DEFINITION:

Eine SUBQUERY kann mit dem übergeordneten SELECT mittels einer korrelierten SUBQUERY abgestimmt werden.

Beispiel: Selektion der Lieferanten, die in der Bestelltabelle nicht verwendet werden. select * from liefer a where not exists

(select * from bestell b where b.adressnr = a.liefernr);

EXISTS-Abfragen benötigen mehr Rechnerzeit und werden zweckmässigerweise durch IN-Abfragen ersetzt: select * from liefer where liefernr not in

(select adressnr from bestell)

Page 42: SQL Befehle 30 - gdi.de · SQL arbeitet im Gegensatz hierzu mengenorientiert. Man gibt an, welche Bedingung erfüllt sein muss, der Rest erledigt das System und man erhält die Ergebnismenge

GDI-SQL-Seminar 19.03.2018 Seite 42/57

2.4.13 Zusammenfügen von Ergebnissen mit UNION Mit Hilfe des UNION-Befehles lassen sich die Ergebnisse zweier SQL-Abfragen in eine

Ergebnistabelle zusammenfassen. Es ist zu beachten, daß beide SQL-Abfragen eine Ergebnistabelle gleicher Struktur liefern, da der Befehl sonst nicht angewendet werden kann. (à gleiche Feldanzahl, gleiche Feldtypen).

Beispiel: Zusammenfassen von Rechnungen und Gutschriften in einer Tabelle, wobei Rechnungswerte positiv und Gutschriftswerte negativ dargestellt werden.

/* Auswertung: Alle VK-Rechnungen und VK-Gutschriften eines bestimmten Belegdatums und einer bestimmten Zahlart einschließlich Gesamtsumme */ select Belegtyp, Belegart, Belegnr, Belegdat, Adressnr, Name1, Netto,

(Brutto - Netto) as MwSt, Brutto, EKPreis as Erloes, Waehrbez, Zahlart from beleg where Belegtyp = "V" and Belegart = "RE" and GetDate(Belegdat) = ::Belegdatum and Zahlart = ::Zahlart UNION select Belegtyp, Belegart, Belegnr, Belegdat, Adressnr, Name1, Netto * (-

1), (Brutto - Netto)*(-1) as MwSt, Brutto * (-1), EKPreis as Erloes, Waehrbez, Zahlart

from beleg where Belegtyp = "V" and Belegart = "GU" and GetDate(Belegdat) = ::Belegdatum and Zahlart = ::Zahlart; Anmerkungen: Es gibt zwei Varianten UNION à Im Ergebnis werden identische Zeilen der "Teil"-SQLs nur einfach ausgegeben, es findet praktisch

eine Gruppierung (ein Distinct) statt UNION ALL à jede Zeile der "Teil"-SQLs wird auch ausgegeben

Page 43: SQL Befehle 30 - gdi.de · SQL arbeitet im Gegensatz hierzu mengenorientiert. Man gibt an, welche Bedingung erfüllt sein muss, der Rest erledigt das System und man erhält die Ergebnismenge

GDI-SQL-Seminar 19.03.2018 Seite 43/57

2.4.14 Das CREATE-Kommando 2.4.14.1 Erstellen von Tabellen Syntax: CREATE TABLE Tabellenname

(Feldname (Datentyp [Länge],...)

DEFINITION:

Das CREATE-TABLE Kommando erstellt eine neue Tabelle. Beispiel: Erstellen einer Dummy-Tabelle als Basis für einen ‚Taschenrechner‘. CREATE TABLE dummy (Wert char(1)); CREATE TABLE dummy2 (Feld1 GDI_Char1, Feld2 GDI_Char5, Feld3 GDI_Long); à Nur bei InterBase/FireBird: Definition unter Verwendung der "GDI"-Feldtypen (in der Datei Domain.sql definiert). Siehe auch Info im Abschnitt 2.4.5.2 2.4.14.2 Erstellen von Indices Syntax: CREATE [UNIQUE] INDEX Indexname ON Tabellenname (Tabellen-Feldname,...)

DEFINITION:

Das CREATE-INDEX Kommando erstellt einen neuen Index.

Beispiel: Erstellen zweier Tuning-lndices auf die Felder blz für die Tabellen kunden und blz: CREATE INDEX blzblz ON BLZ (blz); CREATE INDEX kundenblz ON kunden (blz);

Page 44: SQL Befehle 30 - gdi.de · SQL arbeitet im Gegensatz hierzu mengenorientiert. Man gibt an, welche Bedingung erfüllt sein muss, der Rest erledigt das System und man erhält die Ergebnismenge

GDI-SQL-Seminar 19.03.2018 Seite 44/57

2.4.15 Das DROP-Kommando 2.4.15.1 Löschen von Tabellen Syntax: DROP TABLE Tabellenname

DEFINITION:

Das DROP-TABLE Kommando löscht eine Tabelle. Beispiel: DROP TABLE dummy; 2.4.15.2 Löschen von Indices Syntax in 2.0.x: DROP INDEX Indexname Syntax in 1.8.x: DROP INDEX Tabellenname.Indexname

DEFINITION:

Das DROP-INDEX Kommando löscht einen Index.

Beispiel: DROP INDEX blzblz; DROP INDEX BE_Artnr_desc;

Page 45: SQL Befehle 30 - gdi.de · SQL arbeitet im Gegensatz hierzu mengenorientiert. Man gibt an, welche Bedingung erfüllt sein muss, der Rest erledigt das System und man erhält die Ergebnismenge

GDI-SQL-Seminar 19.03.2018 Seite 45/57

2.4.16 Das INSERT-Kommando 2.4.16.1 Einfügen von Zeilen Syntax:

Format 1 INSERT INTO Tabellenname VALUES (Wert,...); Format 2 INSERT INTO Tabellenname (Feldname,...) VALUES (Wert,...) Format 3 INSERT INTO Tabellenname (Feldname,...)

SELECT Feldname,… FROM Tabellenname;

DEFINITION:

Das INSERT-Kommando fügt Zeilen ein. Beispiele: INSERT INTO dummy VALUES (,X'); à hier müssen für alle Felder der Tabelle dummy Werte angegeben werden. Es wird ein Datensatz angelegt. INSERT INTO dummy2 (Feld1, Feld2) VALUES ("V","RE"); à hier müssen nur Felder angegeben werden, in welche explizit ein Wert eingetragen werden soll. Es wird ein Datensatz angelegt. INSERT INTO blztest (blz, name, Ort, plz) SELECT blz, name, Ort, plz FROM blz; à hier werden so viele Sätze angelegt, wie aus der blz-Tabelle selektiert. Es müssen nicht alle Felder der blztest-Tabelle angegeben werden. INSERT INTO interess (Interessnr, Name1, Name2, Strasse, PLZ, Ort, Telefon, Handy, Email) SELECT Kundennr + 100000, Name1, Name2, Strasse, PLZ, Ort, Telefon, Handy, Email FROM kunden WHERE Kundennr NOT IN (select distinct adressnr from beleg where belegtyp ="V"); à hier werden Datensätze aus der Kundentabelle in die Interessenten-Tabelle übertragen, die Nummer wird dabei um 100000 hochgesetzt; Durch das eingesetzte subselect mit in-Operator (siehe oben unter Abschnitt 2.4.12.2.2) handelt sich um die Kunden, für welche bislang noch keine Belege geschrieben wurden. Mit einer weiteren SQL könnten diese anschließend aus der Kundentabelle "entfernt" werden.

Page 46: SQL Befehle 30 - gdi.de · SQL arbeitet im Gegensatz hierzu mengenorientiert. Man gibt an, welche Bedingung erfüllt sein muss, der Rest erledigt das System und man erhält die Ergebnismenge

GDI-SQL-Seminar 19.03.2018 Seite 46/57

2.4.17 Das ALTER -Kommando 2.4.17.1 Tabellenstruktur ändern mit ALTER TABLE ... ADD Syntax:

ALTER TABLE Tabellenname ADD Feldname FeldTyp,...;

DEFINITION:

Das ALTER-TABLE-Kommando mit ADD fügt neue Spalten ein. Beispiel: ALTER TABLE Artikel ADD Zusatz1 GDI_CHAR4; Hinweis: Als Feldtypen in der 2.x bitte nur die Datentypen der DOMAIN.SQL verwenden. 2.4.17.2 Tabellenstruktur ändern mit ALTER TABLE ... DROP Syntax:

ALTER TABLE Tabellenname DROP Feldname,...;

DEFINITION:

Das ALTER-TABLE-Kommando mit DROP löscht Spalten Beispiel: ALTER TABLE Artikel DROP Zusatz1;

Page 47: SQL Befehle 30 - gdi.de · SQL arbeitet im Gegensatz hierzu mengenorientiert. Man gibt an, welche Bedingung erfüllt sein muss, der Rest erledigt das System und man erhält die Ergebnismenge

GDI-SQL-Seminar 19.03.2018 Seite 47/57

2.4.17.3 Indices aktivieren / deaktivieren mit ALTER INDEX Syntax:

ALTER INDEX Indexname ACTIVE; bzw.

ALTER INDEX Indexname INACTIVE;

DEFINITION:

Das ALTER-INDEX-Kommando dient zur De-/Aktivierung von bereits vorhandenen Indizes

Beispiel: ALTER INDEX KU_Suchnam INACTIVE; ALTER INDEX KU_Suchnam ACTIVE; Mit folgender SQL kann überprüft werden, ob die Indizes auf den (GDI-) Tabellen aktiv sind oder nicht (eine "0" in der zweiten Spalte bedeutet active (= ok), eine "1" inactive (= nicht ok): select RDB$Index_Name, RDB$Index_Inactive from RDB$Indices where RDB$Index_Name not starting with "RDB$" order by 2 desc, 1 asc Hinweis: Durch eine Datenreorganisation wird der Status eines Index nicht verändert, inactive Indizes bleiben somit inactive!

Page 48: SQL Befehle 30 - gdi.de · SQL arbeitet im Gegensatz hierzu mengenorientiert. Man gibt an, welche Bedingung erfüllt sein muss, der Rest erledigt das System und man erhält die Ergebnismenge

GDI-SQL-Seminar 19.03.2018 Seite 48/57

2.4.18 Das DELETE-Kommando 2.4.18.1 Zeilen löschen Syntax:

DELETE FROM Tabellenname [WHERE Bedingung]

DEFINITION:

Das DELETE-Kommando löscht Zeilen. Beispiel: DELETE FROM blztest where blz = "50150030"; 2.4.19 Das UPDATE-Kommando

2.4.19.1 Feldeinhalte ändern

Syntax:

UPDATE Tabellenname

SET Feldname = Wert

[WHERE Bedingung]

DEFINITION:

Das UPDATE-Kommando verändert Werte in Spalten. Beispiel: UPDATE blztest set blz = "55550030" where blz = "50150030"; UPDATE artikel set rabattgr = wgr;

Page 49: SQL Befehle 30 - gdi.de · SQL arbeitet im Gegensatz hierzu mengenorientiert. Man gibt an, welche Bedingung erfüllt sein muss, der Rest erledigt das System und man erhält die Ergebnismenge

GDI-SQL-Seminar 19.03.2018 Seite 49/57

UPDATE und DELETE mit Unterabfragen Wie bereits gesehen dient die Update-Anweisung zum Aktualisieren, die Delete-Anweisung zum

Löschen von Datensätzen einer Tabelle, wobei die Syntax dieser Anweisungen sich einfach darstellt, sofern sich die SQL auf eine einzige Datentabelle bezieht (update-/delete-Anweisung und where-Klausel beziehen sich auf gleiche Tabelle).

Beispiele: update artikel set Kzbestell = "1" where wgr = "200"; delete from interess where .... Es ist aber auch möglich, Datensätze einer Tabelle in Abhängigkeit einer anderen Tabelle zu löschen

oder zu aktualisieren. Es verhält sich "relativ einfach" bei Anweisungen, die sich zwar auf zwei Tabellen beziehen, aber nur die Information der zu ändernden/löschenden Sätze aus der zweiten Tabelle bezogen wird. Hier haben wir eine SubQuery/SubSelect in der where-Klausel (siehe auch 2.4.12.2:

Beispiele: update artikel set KZLager = "1" where artikelnr in (select artikelnr from Inventur); update artikel set KZLager = "0" where artikelnr not in (select artikelnr from Inventur); delete from inventur where artikelnr not in (select artikelnr from artikel where KZLager ="1"); "Problematischer" wird es, wenn Werte aus einer Tabelle in eine andere übertragen werden sollen.

Hierzu muß man entsprechende Unterabfragen formulieren, deren Ergebnis jeweils genau einen Datensatz zurückliefert. Dabei liefert das SubSelect genau den zu setzenden Wert und befindet sich nicht in der where-klausel der übergeordneten update-Anweisung.

Beispiel: update belegpos set Belegpos.Kommnr = (select beleg.Kommnr from beleg where Belegpos.Belegtyp = Beleg.Belegtyp and Belegpos.Belegart = Beleg.Belegart and Belegpos.Belegnr = Beleg.Belegnr ) where Belegtyp = "V" and Belegart = "RE" and Adressnr = 15000; Ein zusätzliches Problem ergibt sich bei numerischen Feldern in der Datenbank. Diesen kann im Gegensatz zu alphanumerischen Feldern kein null-Wert zugewiesen werden (Stichwort: Definition in der GDI_Domain.Meta). Eine Anweisung wie z.B. Update artikel set KB_alt = null führt unweigerlich zur Fehlermeldung: Für das Feld ist ein Wert erforderlich. Validation error for column KB_ALT, value "***null***" Arbeitet man nun mit SubSelects und die Unterabfrage liefert keinen Datensatz zurück, so tritt genau dieser Fall auch ein. Bei alphanumerischen Feldern erzeugt man durch das update null-

Achtung: Die Einschränkung nach Belegtyp, Belegart und Adressnr darf nicht in die Unterabfrage integriert werden!

Page 50: SQL Befehle 30 - gdi.de · SQL arbeitet im Gegensatz hierzu mengenorientiert. Man gibt an, welche Bedingung erfüllt sein muss, der Rest erledigt das System und man erhält die Ergebnismenge

GDI-SQL-Seminar 19.03.2018 Seite 50/57

Werte, bei numerischen Feldern blockt die Datenbank. Die folgende Abfrage läuft nicht durch, wenn es für einen Artikel in der Arumsatz-Tabelle noch keinen Satz gibt: update artikel set KB_alt = (select MEK from arumsatz where Arumsatz.Artikelnr = Artikel.Artikelnr and Arumsatz.Jahr = "2007" and Arumsatz.Filiale = 0) where wgr = "500"; Umgehen lässt sich das Problem durch Hinzufügen einer "Sicherheits"-Unterabfrage in der äusseren where-Klausel: update artikel set KB_alt = (select MEK from arumsatz where Arumsatz.Artikelnr = Artikel.Artikelnr and Arumsatz.Jahr = "2007" and Arumsatz.Filiale = 0) where wgr = "500" and (select mek from arumsatz where Arumsatz.Artikelnr = Artikel.Artikelnr and Arumsatz.Jahr = "2007" and Arumsatz.Filiale = 0) is not null Eine Alternative zu dieser "Sicherheits"-Unterabfrage wäre die Verwendung der UDF-Funktion "Runden" bei der Wert-Zuweisung (siehe auch Abschnitt 2.4.8). Die Funktion Runden liefert nämlich bei einen null-Wert eine "echte" 0 zurück: update artikel set KB_alt = Runden( (select MEK from arumsatz where Arumsatz.Artikelnr = Artikel.Artikelnr and Arumsatz.Jahr = "2007" and Arumsatz.Filiale = 0),2) where wgr = "500"; Bei alphnumerischen Feldern (bei denen NULL-Werte zwar möglich, aber in der Regel dennoch unerwünscht sind) kann analog eine Sicherheits-Abfrage oder aber statt der UDF Runden die UDF TrimL verwendet werden. Die Funktion TrimL entfernt bei Zeichenketten voran- und nachstehende Leerzeichen, Zeilenumbrüche und Tabulatoren und liefert bei einem NULL-Wert ein Leerstring zurück. WICHTIG: Fehlerhafte Update- und Delete-Anweisungen können Datenbestände zerstören.

Im Zweifelsfalle vor der Ausführung immer eine DATENSICHERUNG erstellen!! An dieser Stelle noch zwei Hinweise: In vielen Fällen benötigen Update/Delete-Anweisungen mit Unterabfragen sehr viel Zeit bei der Ausführung. Desweiteren erfordern sie Erfahrung, um ungewollte Aktionen zu vermeiden. Erfahrungsgemäss ist bei solchen Anforderungen der Einsatz von GDI-BASIC kombiniert mit SQL zu empfehlen. Das Laufzeitverhalten kann durch parametrisierte SQLs erheblich gesteigert werden.

Page 51: SQL Befehle 30 - gdi.de · SQL arbeitet im Gegensatz hierzu mengenorientiert. Man gibt an, welche Bedingung erfüllt sein muss, der Rest erledigt das System und man erhält die Ergebnismenge

GDI-SQL-Seminar 19.03.2018 Seite 51/57

2.5 SONSTIGES, Besonderheiten bei GDI • Kommentar:

Bei der Erfassung des SQL-Statements im SQL-System auf der Karteiseite "SQL" können Kommentare gesetzt werden:

o Kommentarblock: Ein Kommentar wird durch die Zeichen "/*" und "*/" begrenzt. o Kommentarzeile: Eine einzige Zeile lässt sich über "--" auskommentieren.

• Einsatz von Parameter:

In einer SQL-Abfrage können auch Parameter eingesetzt werden. Ein Parameter wird durch einen dem Parameternamen vorangestellten Doppelpunkt definiert. Beispiel:

select a.Kundennr, a.name1, a.name2, a.plz, a.ort, a.strasse from kunden a where a.plz between :VonPLZ and :BisPLZ order by a.plz desc;

• Mehrere SQL-Abfragen kombinieren

Man kann im SQL-System mehrere Abfragen hintereinander absetzen (also praktisch ein "SQL-Batch" schreiben). Hierbei ist zu beachten:

• Jede SQL-Anweisung muss mit Semikolon (;) abgeschlossen werden. • Das Ergebnis jeder einzelnen Abfrage wird temporär im Speicher festgehalten. Dies

ermöglicht innerhalb des Batches den Zugriff auf die Ergebnistabelle einer vorausgegangenen Abfrage. Eine solche Ergebnistabelle kann unter dem Namen "&&SQLn" angesprochen werden. Das n steht hierin für die Nummer der SQL-Abfrage innerhalb des Batches.

Wichtig: Dies gilt nur für das SQL-System bzw. den ExecuteSQL-Befehl innerhalb von GDI-BASIC. Gilt beispielsweise nicht für SQLs innerhalb des FastReporters. Dort sind nur "einstufige" SQLs möglich.

• Heterogene Verbindungen: Der gleichzeitige Zugriff auf Tabellen unterschiedlicher

Datenbanksysteme ist nicht möglich, ebenso der Zugriff auf zwei Mandanten. Ein Anwendungsfall ist z.B. ein Datenexport aus Mandant A und anschließender Import in Mandant B. Unter FireBird wie folgt lösbar: - Mandant 1: select * from Artikel where ..... als Ergebnistabelle "E:\Temp\Artikel.dbf" angeben - Mandant 2: select * from "E:\Temp\Artikel.dbf"; insert into Artikel select * from "&&SQL1";

Page 52: SQL Befehle 30 - gdi.de · SQL arbeitet im Gegensatz hierzu mengenorientiert. Man gibt an, welche Bedingung erfüllt sein muss, der Rest erledigt das System und man erhält die Ergebnismenge

GDI-SQL-Seminar 19.03.2018 Seite 52/57

2.6 Firebird-Besonderheiten 2.6.1 Spezielle Funktionen bei FireBird 2.6.1.1 Teilergebnis-Datenmengen mit FIRST und SKIP Unter Interbase/FireBird gibt es die Möglichkeit, nur eine bestimmte Anzahl von Datensätzen einer Ergebnismenge auszugeben, z.B. für Erstellung einer "Hitliste" oder für die blockweise Ausgabe von Daten. Hierfür werden direkt nach dem select die Schlüsselwörter first und skip verwendet. select first n ... à es sollen n Sätze ausgegeben werden select first n skip nn ... à es sollen nn Sätze übersprungen und dann n Sätze ausgegeben werden Beispiele: Selektion der ersten zehn Kunden des Kundenstammes: Select first 10 Kundennr, name1, name2 from Kunden order by Kundennr Selektion der letzten zehn Kunden des Kundenstammes. Es gibt keinen "Last", aber die Anweisung "First" wird erst auf das Ergebnis angewendet: Select first 10 Kundennr, name1, name2 from Kunden order by Kundennr desc Selektion der Kunden 11 bis 15: Select first 5 skip 10 Kundennr, name1, name2 from Kunden order by Kundennr 2.6.1.2 Bedingte Abfrage mit CASE WHEN THEN-Anweisung Im SQL-Standard gibt es – wie mehrfach erwähnt – keine prozeduralen Sprachelemente. Seit FireBird 1.5 gibt es hier eine Möglichkeit der bedingten Abfrage. Das neue Sprachkonstrukt hat folgende Syntax: Select CASE WHEN Bedingung1 THEN Anweisung1 WHEN Bedingung2 THEN Anweisung2 ... ELSE AnweisungN END from Tabelle Beispiel: Ausgabe Belege, Beträge bei GU umkehren, als Betrag bei Lieferschein fiktiv 100 ausgeben (also nicht den Wert aus dem Lieferschein): select Belegtyp, Belegart, Belegnr, CASE WHEN Belegart = "GU" THEN (Brutto * -1) WHEN Belegart = "LI" THEN 100 /*fiktiv auf 100 gesetzt!*/ ELSE Brutto END Bruttobetrag from beleg where Belegdat >= "17.09.2008" Man kann also ohne Zusammenfügung mehrerer SQLs mit UNION eine Vorzeichenumkehr bei Gutschriften erreichen. Auch mit Summierung: select Belegtyp, Belegart, Sum(CASE WHEN Belegart = "GU" THEN (Brutto * -1) WHEN Belegart = "LI" THEN 100 ELSE Brutto END) Bruttobetrag from beleg where Belegdat >= "05.06.2006" group by Belegtyp, Belegart

Page 53: SQL Befehle 30 - gdi.de · SQL arbeitet im Gegensatz hierzu mengenorientiert. Man gibt an, welche Bedingung erfüllt sein muss, der Rest erledigt das System und man erhält die Ergebnismenge

GDI-SQL-Seminar 19.03.2018 Seite 53/57

Beispiel: Ausgabe Belege, Wenn Lieferadresse gefüllt , dann diese ausgeben, ansonsten die Belegadresse: select Belegtyp, belegart, Belegnr, Belegdat, CASE WHEN L_name1 <> "" THEN (L_Name1 || " " || L_Name2) ELSE Name1 || " " || Name2 END Adresse from beleg where Belegdat >= "17.09.2008"; oder: select Belegtyp, belegart, Belegnr, Belegdat, CASE WHEN L_name1 <> "" THEN (L_Name1) ELSE Name1 END AdrName1, CASE WHEN L_name1 <> "" THEN (L_Name2) ELSE Name2 END AdrName2 from beleg where Belegdat >= "17.09.2008"; Beispiel: Ausgabe von Monats-Umsätzen für zwei Jahre im Vergleich. Hier wurde korrekterweise nicht auf den Brutto-Wert der Belege zugegriffen, sondern auf die Felder Warenwert und NKWarenw (Nebenkosten-Warenwert). Diese sind immer "in Netto und in Hauswährung". (Das Ergebnis testweise mit der Tagesstatistik vergleichen). select getmonth(BelegDat), sum(case when Belegart = "RE" and GetYear(BelegDat) = 2010 then (Warenwert + NKwarenw) when Belegart = "GU" and GetYear(BelegDat) = 2010 then -(Warenwert + NKwarenw) else 0 end) Jahr1, sum(case when Belegart = "RE" and GetYear(BelegDat) = 2011 then (Warenwert + NKwarenw) when Belegart = "GU" and GetYear(BelegDat) = 2011 then -(Warenwert + NKwarenw) else 0 end) Jahr2 from Beleg where Belegtyp = "V" group by 1

Page 54: SQL Befehle 30 - gdi.de · SQL arbeitet im Gegensatz hierzu mengenorientiert. Man gibt an, welche Bedingung erfüllt sein muss, der Rest erledigt das System und man erhält die Ergebnismenge

GDI-SQL-Seminar 19.03.2018 Seite 54/57

2.6.1.3 Temporäre Prozeduren per EXECUTE BLOCK GDI verwendet den sog. EXECUTE BLOCK- Konstrukt in den Pivotauswertungen. Um solche Auswertungen erweitern zu können, sind daher Kenntnisse über diesen Konstrukt unabdingbar. Der Aufbau einer Execute Block- Anweisung entspricht nahezu dem Aufbau einer Stored Procedure. Sie unterscheiden sich in der Übergabe der Input-Parameter, die restliche Struktur und die möglichen Sprachkonstrukte im Prozedurrumpf sind identisch. Hiermit lassen sich wie durch Stored Procedures komplexere SQL's formulieren, welche komplett im SQL-Server ausgeführt werden, jedoch ohne dass man Proceduren per Reorganisation fest in die Datenbank bringen muss. Der gesamte Execute Block wird im Firebird Server abgearbeitet ohne dort gespeichert zu werden. Wichtig: Es ist mindestens eine Firebird-Server-Version 2.x (2.1.3 oder 2.5.0) erforderlich! Eine Execute Block- Anweisung hat folgende Syntax: EXECUTE BLOCK <Parameterliste> RETURNS <Rückgabewerte> AS <Lokale Variablen> BEGIN <Prozedurrumpf> END Auf die Schlüsselwörter EXECUTE BLOCK folgt in runde Klammern gesetzt die optionale Aufruf-Parameterliste. Diese stellt eine Liste von Variablen dar, die von außen an den Execute Block übergeben werden können/müssen. Diese Variablen können im Prozedurrumpf benutzt werden, um Operationen nur für bestimmte Datensätze (z.B. bestimmte Kunden) durchzuführen. Die Parameterliste hat folgenden Aufbau: (ParameterName1 DatenTyp = :VarName1, ParameterName2 DatenTyp = :VarName2, ... ParameterNameN DatenTyp = :VarNameN) Nach dem Schlüsselwort RETURNS folgt die Liste der Rückgabewerte, ebenfalls in runde Klammern gesetzt. Diese Rückgabewertliste besitzt folgenden Aufbau: (RückgabewertName1 DatenTyp, RückgabewertName2 DatenTyp, ... RückgabewertNameN DatenTyp) Als Datentyp ist jeder gültige FireBird-Datentyp zulässig, ausgenommen Array. Für Fliesskommazahlen verwenden Sie in der BLine bitte immer den Datentyp DOUBLE PRECISION. Bitte nicht die GDI-spezifischen Datentypen verwenden (GDI_CHAR10, GDI_FLOAT,...). Diese sind nur für die Anlage von Feldern in Datentabellen zu verwenden (Stichwort META-Dateien und Reorganisation). Nach der AS-Anweisung werden falls erforderlich lokale Variablen definiert. Diese sind zur Laufzeit des Execute Block verfügbar. Jede Variable muss mit DECLARE VARIABLE deklariert, die Anweisung mit Semikolon abgeschlossen werden: DECLARE VARIABLE var1 Datentyp; DECLARE VARIABLE var2 Datentyp; ... DECLARE VARIABLE varN Datentyp;

Page 55: SQL Befehle 30 - gdi.de · SQL arbeitet im Gegensatz hierzu mengenorientiert. Man gibt an, welche Bedingung erfüllt sein muss, der Rest erledigt das System und man erhält die Ergebnismenge

GDI-SQL-Seminar 19.03.2018 Seite 55/57

Nach dem anschließenden BEGIN folgt im Prozedurrumpf der eigentliche Prozedurcode, also die Liste der Anweisungen, welche die Prozedur ausführen soll. Dieser Teil wird durch ein END abgeschlossen. Hier wird kein Semikolon gesetzt. Innerhalb dieses Blockes gibt es verschiedene Sprachkonstrukte, die je nach Anwendungsfall eingesetzt werden können, z.B. FOR SELECT ... DO oder WHILE ... DO oder IF … THEN … ELSE. Dies sind die prozeduralen Elemente, die in Standard-SQL fehlen. Eine Referenz dieser Sprachelemente findet man in einem InterBase-Dokumentensatz (PDF-Dateien) unter http://www.gdi-software.com/download/progs/interbase/windows/interbase_Doku.zip An dieser Stelle ein paar kurze Hinweise: Wird im Prozedurrumpf eine SELECT-Anweisung verwendet, so endet diese mit der Übergabe der Parameter mittels einer INTO-Anweisung in die lokalen Variablen bzw. in die Rückgabeparameter: SELECT <Feld1>, <Feld2>,....,<FeldN> FROM ... WHERE ... GROUP BY ... INTO :var1, :var2, ..., :varN; Sollen mehrere Datensätze in einer Schleife abgearbeitet werden, so ist ein FOR SELECT … DO BEGIN … END - Konstrukt erforderlich. Die Select-Anweisung ist dabei wie im voranstehenden Abschnitt eine "normale" SQL mit zusätzlicher INTO-Anweisung (s.o.). Für jede Zeile, welche die Select-Anweisung liefert, werden die Anweisungen im DO-Teil ausgeführt. In GDI-BASIC würden solche Konstruktionen mit while-Schleifen erstellt werden: FOR SELECT ... DO BEGIN <Anweisung1>; <Anweisung2>; ... END Den Begriff der while –Schleife gibt es auch in Stored Procedures bzw. im Execute-Block. Mit einer solchen WHILE … DO BEGIN … END - Konstruktion ist im Gegensatz zu GDI-BASIC jedoch keine Schleife durch Daten(sätze) möglich, sondern nur Schleifen, welche keine Daten betreffen. Es gibt hier kein "Endwhile". WHILE <Bedingung> DO BEGIN <Anweisung>; <Anweisung2>; ... END Bedingte Abfragen werden wie in GDI-BASIC mit IF … THEN gebildet. Bei solchen Anweisungen ist im Gegensatz zum GDI-BASIC ein BEGIN erforderlich, wenn mehrere Anweisungen folgen. Zu jedem BEGIN gehört ein END (ohne Semikolon!). Dagegen gibt es kein "endif" am Ende dieses Abschnittes. Die Bedingungen müssen in runde Klammern gestellt sein. IF (<Bedingung>) THEN BEGIN <Anweisung1>; <Anweisung2>; ...

Page 56: SQL Befehle 30 - gdi.de · SQL arbeitet im Gegensatz hierzu mengenorientiert. Man gibt an, welche Bedingung erfüllt sein muss, der Rest erledigt das System und man erhält die Ergebnismenge

GDI-SQL-Seminar 19.03.2018 Seite 56/57

END ELSE BEGIN <Anweisung3>; <Anweisung3>; END Um die aktuellern Werte der Rückgabeparameter an die den Execute Block aufrufende Instanz (hier die Pivotauswertung) zu übergeben wird das Schlüsselwort SUSPEND benötigt. Mit jedem "abgearbeiteten" Suspend wird ein weiterer Datensatz in der Datenmenge der Pivotauswertung erzeugt: SUSPEND; Im Gegensatz zum GDI-BASIC erfolgen Zuweisungen von Werten an Variablen nicht durch ":=" sondern nur durch einfaches Gleichheitszeichen "=": Variable = Wert Der "vorzeitige" Abbruch der Verarbeitung kann durch ein EXIT in der Stored Procedure / im Execute Block erreicht werden. Im Falle des Execute Blocks bei Pivotauswertungen, bei denen es darum geht Datensätze für die Pivottabelle zu generieren, wird dies eher nicht benötigt (die Ergebnisdatenmenge bliebe leer). Im Bereich der Datenbank-Programmierung mit Triggern und Stored Procedures wird ein exit häufiger verwendet. Bei einem solchen Abbruch der Verarbeitung wird in der Datenbank der Ausgangszustand wiederhergestellt. Alle bisher durch die Prozedur "durchgeführten" Änderungen sind hinfällig (rollback). EXIT; Im Prozedurrumpf lässt sich bei Bedarf auch ein Aufruf einer Stored Procedure realisieren, welche selbst Rückgabewerte an den Execute Block liefert. Als Parameter lassen sich Konstanten, die Übergabeparameter oder die lokalen Variablen einsetzen: SELECT RWert1, RWert2, ... FROM ProcedurName(:Pwert1,...) INTO :var1, :var2,... Kommentare: Auszukommentierende Bereiche werden innerhalb einer Procedur durch die Zeichenfolgen /* und */ umschlossen/abgegrenzt. Terminatorzeichen ("Trennzeichen") Innerhalb der Stored Procedures / Execute Block- Anweisungen werden wie bei "normalen" SQLs Semikola als Trennzeichen für die einzelnen Anweisungen benötigt. Damit man Prozeduren in einem SQL-Script z.B. im SQL-System der Bline erstellen und in die Datenbank einbringen kann ist es notwendig, ein anderes Trennzeichen zu definieren, damit die Prozedur als Ganzes von den anderen SQL-Anweisungen unterschieden und interpretiert werden kann. Dies erfolgt über die vorausgestellten Schlüsselwörter SET TERM <Neues Terminatorzeichen > <Aktuelles Terminatorzeichen>. Nach der Prozedur schaltet man auf das übliche Trennzeichen zurück. Beispiel:

Page 57: SQL Befehle 30 - gdi.de · SQL arbeitet im Gegensatz hierzu mengenorientiert. Man gibt an, welche Bedingung erfüllt sein muss, der Rest erledigt das System und man erhält die Ergebnismenge

GDI-SQL-Seminar 19.03.2018 Seite 57/57

SET TERM ^; CREATE PROCEDURE /* bzw. Execute Block */ ... AS BEGIN ... END ^ à Das neue Termninatorzeichen zeigt also das Ende der Prozedur. SET TERM ;^ Hinweise: - Wird eine Stored Procedure über die Metadateien und einen Reorganisationslauf in das Datenbanksystem übernommen, so ist dort kein Terminatorzeichen notwendig. - Zur Ausführung von Execute Block- Anweisungen in den Pivotauswertungen wird kein Terminatorzeichen benötigt - Der Einsatz von Execute Block- Anweisungen im SQL-System der Bline (mit Terminatorzeichen) ist ab Version 3.1.2.196 möglich. Beispiel: Nachbildung der Stored Procedure GDI_OPHAUS als Execute Block-Konstrukt: set term #; execute block (AdressNr Integer = ::AdressNr) returns (OPHaus Double Precision) as declare variable FBelegArt VarChar(10); declare variable FOPHAUS Double Precision; declare variable FNK Integer; begin FNK = null; select first 1 StrToInt(Copy(ListValue(M1,'BELEG.NK'),1,1)) from GDIDEF where Satzart = 'FA1' into :FNK; if ((FNK is null) or (FNK = 0)) then FNK = 2; OPHaus = 0.0; for select BelegArt,OPHAUS from Beleg where AdressNr = :AdressNr and BelegArt in ('RE','GU') and OPBetrag <> 0.0 into :FBelegArt, :FOPHaus do begin if (FBelegArt = 'GU') then OPHaus = OPHaus - FOPHaus; else OPHaus = OPHaus + FOPHaus; end OPHaus = Runden(OPHaus,FNK); suspend; end # set term ;#