1 Themenübersicht
Für die Kommunikation mit den Datenbanken verwenden verschiedene Hersteller unterschiedliche Schnittstellen beziehungsweise diverse SQL-Dialekte. Um diese Kommunikation zu vereinheitlichen, wurde eine Object-Query-Language (OQL) implementiert, die auf objektorientierten und relationalen Konzepten basiert. Die Comarch-ERP-Enterprise-OQL ist angelehnt an den SQL-Standard. Bei einem ähnlichen Funktionsumfang wie in SQL, wird die OQL für alle aufgeführten Datenbank-Managementsysteme unterstützt. Aus Sicht des Anwendungsentwicklers spielen somit SQL-Dialekte keine Rolle mehr.
Die Abfragesprache OQL ist in Comarch ERP Enterprise eingebettet. Bei ihrer Übersetzung werden unter anderem, entsprechend den Namensraumkonventionen, die spezifischen Comarch-ERP-Enterprise-Namen in technische Datenbanknamen umgewandelt. Damit werden eindeutige Bezüge zu den Objekten hergestellt und Namenskollisionen in einem System ausgeschlossen. Der Anwendungsentwickler verfügt mit dem Object-Manager über eine einfache Möglichkeit auf Daten zuzugreifen. Er stellt dem Entwickler die Einzeloperationen Lesen, Einfügen, Ändern und Löschen auf Business Objects zu Verfügung. Zudem kann der Anwendungsentwickler in diesem Zusammenhang OQL-Statements nutzen, um gleichzeitig eine Menge von Business-Object-Instanzen zu bearbeiten. OQL und der Object-Manager bilden für den Anwendungsentwickler die Schnittstelle zu den Datenbanken. Beide verwenden intern das plattformunabhängige JDBC™-Protokoll. Die verschiedenen JDBC™-Treiber sind in der Regel mit zusätzlichen herstellerspezifischen Parametern versehen, welche teilweise von Comarch ERP Enterprise genutzt werden, um von den Besonderheiten der Datenbank-Managementsysteme profitieren zu können und mögliche Leistungsgewinne auszuschöpfen.
2 Zielgruppe
- Anwendungsentwickler
- Administratoren
- Benutzer mit technischem Hintergrundwissen
3 Begriffsbestimmung
Business Object
Das Datenmodell basiert auf Business Objects. Sie enthalten ausschließlich Daten und werden deshalb auch als Datencontainer bezeichnet. Die Bearbeitung dieser Daten wird mithilfe der Anwendungslogik realisiert, die Zustandstransformationen auf den Daten durchführt. Mit den Business Objects wurden unter weitestgehender Berücksichtigung der dritten Normalform die relevanten Ausschnitte der Realität modelliert, das heißt die Einheiten wurden möglichst redundanzfrei erstellt, woraus eine Vielzahl an Business Objects resultiert.
Ein Business-Object-Typ ist die Definition einer betriebswirtschaftlichen Klasse (Namespace als Packagename, Name als Klassenname), die im Dictionary abgelegt wird und deren Instanzen persistent gemacht werden können. Eine Business-Object-Instanz ist damit die Größe, die der Persistenzdienst lesen, speichern und löschen kann. Oftmals liegen Business-Object-Typen in normalisierter Form vor. Dabei kann die eigentliche betriebswirtschaftliche Größe durch mehr als ein Business-Object-Typ beschrieben werden. Jedoch besteht immer nur ein Haupt-Business-Object-Typ. Daher werden Business-Object-Typen zu einem Business Entity oder zu einem Sub-Entity gruppiert, bei denen ein besonders gekennzeichneter Business-Object-Typ als Repräsentant der Gruppe auftritt. Dieser Repräsentant wird mit seiner Gruppe zum Business Entity.
Object-Query-Language
Die Object-Query-Language (OQL) dient zum Formulieren von Anfragen an eine Datenbank-Instanz. OQL ist eine Erweiterung zu SQL, die anstatt mit einer Tabelle mit einem Business Object oder jeweils mehreren arbeitet.
Object-Manager
Der Object-Manager ist für jeden Zugriff auf Business-Object-Instanzen zuständig. Der Zugriff kann entweder über einen eindeutigen Schlüssel oder über ein OQL erfolgen.
4 Voraussetzungen
Grundlagen des Persistenzdienstes von Comarch ERP Enterprise und SQL-Kenntnisse.
5 Konventionen
Die Syntax der Object Query Language wird in diesem Dokument mithilfe von Syntax-Diagrammen erklärt. Ein Syntaxdiagramm setzt sich aus wenigen Grundelementen zusammen und wird gemäß der Pfeilrichtung von links nach rechts und von oben nach unten gelesen. Können Elemente mehrfach in einem OQL-Ausdruck erscheinen, so führt ein Pfeil wieder zurück bis vor das entsprechende Element.
Die Kästchen mit abgerundeten Ecken stehen für einfache Zeichenfolgen (Terminale). Sind diese Kästchen nicht mit kursiver Schrift beschriftet, so symbolisieren sie die Schlüsselwörter oder Operatoren von OQL. Bei den Schlüsselwörtern wird nicht zwischen Groß- und Kleinschreibung unterschieden. Sind die abgerundeten Kästchen kursiv beschriftet, stehen diese Symbole für Benutzereingaben. Folgende Symbole dieser Art bestehen:
Element | Erläuterung |
PATH | Das Element steht für zwei oder mehrere ID-Elemente, welche jeweils durch ein „.“ getrennt sind. Zum Beispiel beschreibt dieses den Aufbau des Namens eines Business Objects: com.cisag.app.general.obj.Item. |
ID | Dieses Element steht für einen Namen. Es wird für unterschiedliche Elemente verwendet. Es kann für den Namen eines Business Objects stehen, für ein Attribut eines Business Objects oder für einen Namensraum, je nach Kontext. Der Name muss mit einem Buchstaben anfangen. Danach dürfen in beliebiger Reihenfolge Buchstaben, Zahlen oder die Zeichen „_“, „$“ und „#“ verwendet werden. |
QUOTEDPATH | Dieses Element steht für eine ID oder einen PATH, das in doppelten Anführungszeichen gesetzt ist. Wenn ein Name wie ein OQL-Schlüsselwort geschrieben wird, muss es in doppelte Anführungszeichen gesetzt werden. |
STRING_LITERAL | Symbol für eine Zeichenkette. Die Zeichenkette muss einfache Anführungszeichen am Anfang und am Ende haben. |
INTEGER_LITERAL | Symbol für eine ganze Zahl. |
FLOATINGPOINT_LITERAL | Symbol für eine Fließkommazahl. |
EOF | Dies symbolisiert das Ende des OQL-Ausdrucks. |
Die eckigen Kästchen stehen für syntaktische Ausdrücke (Nicht-Terminal), die als Symbol für einen komplexeren Teilausdruck stehen. Diese Symbole werden später gesondert beschrieben.
6 Beschreibung
Die OQL bietet zum einen die Möglichkeit, abfragen zu stellen, um bestimmte Daten von der Datenbank zu lesen. Des Weiteren besteht die Möglichkeit über OQL Business Objects auf der Datenbank zu erstellen, zu ändern oder zu löschen. Der Object-Manager (com.cisag.pgm.appserver.CisObjectManager) bietet mehrere Methoden, die unter anderem einen OQL-Ausdruck als Übergabeparameter erwarten:
- getObjectIterator
- getResultSet
- getUpdateStatement
6.1 Kommentare
Es ist möglich, in einer OQL-Anweisung Kommentare zu verwenden. Diese können beispielsweise zur Dokumentation der OQL-Anweisung verwendet werden. Es gibt zwei Möglichkeiten, um einen Kommentar anzugeben:
- in einer eigenen Zeile, die mit der Kennzeichnung „–“ beginnen muss
- über Kennzeichnung mit Kommentarbeginn „/*“ und Kommentarende „*/“
6.2 Abfragen
Um an Daten von Business Objects zu gelangen, werden zwei verschiedene Wege angeboten: Die Methode getObjectIterator liefert einen Iterator mit Instanzen von Business Objects und die Methode getResultset liefert die im OQL-Ausdruck angegebenen Spalten.
6.2.1 Einfache Abfrage über getObjectIterator
Die Methode getObjectIterator liefert einen Iterator von Business-Object-Instanzen eines bestimmten Business-Object-Typs. Im OQL-Ausdruck kann dabei bestimmt werden, ob alle Instanzen des Business Objects zurückgeliefert werden sollen, oder nur Instanzen, welche bestimmte Bedingungen erfüllen. Die Syntax für den OQL-Ausdruck, den diese Methode akzeptiert, hat folgende Struktur:
Syntax des OQL-Ausdrucks für getObjectIterator
Weil die Methode getObjectIterator Instanzen von Business Objects zurückliefert, darf im Gegensatz zu SQL zwischen den Schlüsselwörtern „SELECT FROM“ keine Attributauswahl stehen.
PATH
An der Position für PATH muss das gewünschte Business Object mit voll qualifizierten Namen angegeben werden, z. B. com.cisag.app.general.obj.Item.
Durch Zusatz der OQL-Schlüsselwörter ACTIVE_TABLE für die aktive Datenbanktabelle und CONVERTED_TABLE für die temporäre Datenbanktabelle mit den konvertierten Daten können Sie bestimmen, aus welcher Tabelle die Daten gelesen werden.
Normalerweise müssen Sie keinen Zusatz angeben, in diesem Fall werden die Daten aus der Tabelle gelesen, zu der die geladenen Business-Object-Mapper des Application-Servers passen.
Beispiel:
Der Inhalt der aktiven Tabelle des Business Objects Item wird ausgelesen.
SELECT FROM com.cisag.app.general.obj.Item ACTIVE_TABLE o
ID
Das in PATH genannte Business Object muss mit einem Alias versehen werden. Der Alias muss mit einem Buchstaben anfangen und darf danach Buchstaben, Zahlen und die Zeichen “_”, “$”, “#” enthalten.
QUOTEDPATH
Das Synax-Element QUOTEDPATH steht für Syntax-Elemente vom Typ PATH oder ID, welche zwischen doppelten Anführungsstrichen geschrieben stehen. Attribute von Business Objects können denselben Namen haben wie ein Schlüsselwort von OQL. In diesem Fall müssen die Attribute im OQL-Ausdruck in doppelten Anführungszeichen stehen.
Beispiel:
Das fiktive Business Object Boxy hat ein Attribut mit dem Namen select. Wenn dieser Name in einem OQL-Ausdruck verwendet werden soll, so muss es in Anführungszeichen stehen.
SELECT FROM com.cisag.app.general.obj.Boxy bo WHERE bo:“select“ IS NOT NULL
Als Alias kann ein OQL-Schlüsselwort gewählt werden. In diesem Fall muss der Alias in doppelten Anführungszeichen gesetzt werden.
Beispiel:
SELECT FROM com.cisag.app.general.obj.Item ”SELECT”
Der Verständlichkeit halber sollte die Verwendung von OQL-Schlüsselwörtern als Alias nicht angewendet werden.
Die restlichen Syntax-Elemente sind optional. Mit den bisher beschriebenen Elementen können alle Instanzen eines Business Objects abgefragt werden.
Beispiel:
Folgender OQL-Ausdruck liefert alle Instanzen vom Business Object Item:
SELECT FROM com.cisag.app.general.obj.Item item
WHERE LogExpression
Optional kann mit dem Schlüsselwort „WHERE“ gefolgt von der Bedingung die Menge der Instanzen im Iterator eingeschränkt werden. Das Element „LogExpression“ hat folgende Struktur:
Struktur des Syntax-Elements LogExpression
Damit ist also möglich, mehrere Bedingungen anzugeben, welche logisch mithilfe der Schlüsselwörter „NOT“, „AND“ und „OR“ verknüpft werden.
CompareExpr
„CompareExpr“ hat folgende Struktur:
Struktur des Syntax-Elements CompareExpr
Demnach steht das Symbol CompareExpr für drei Teilausdrücke.
IsClause
Mit der IsClause kann geprüft werden, ob Attribute eines Business Objects den Wert null bzw. nicht den Wert null besitzen:
Struktur des Syntax-Elements IsClause
Beispiel:
Folgender Ausdruck liefert alle Instanzen des Business Objects Item bei denen das Attribut originalItem den Wert null enthält:
SELECT FROM com.cisag.app.general.obj.Item item WHERE item:originalItem IS NULL
AttributeRef
Das Element AttributeRef beschreibt, wie ein Attribut eines Business Objects in OQL adressiert wird.
Struktur des Syntax-Elements AttributeRef
Das erste Element ID steht für den Alias des Business Objects aus dem FROM-Teil des Ausdruckes. Nach dem Doppelpunkt wird das gewünscht Attribut benannt.
Im einfachsten Fall wird an der Position des Elements ID der Name des Attributes geschrieben.
Beispiel:
SELECT FROM com.cisag.app.general.obj.Item item WHERE item:originalItem IS NOT NULL
Wenn das gewünschte Attribut Teil eines Parts ist, so muss der vollständige Pfad zum Attribut an der Position des Elements PATH angegeben werden. Über den Namen des Part-Attributs kann als Boolean abgefragt werden, ob das Part-Attribut null ist. Wenn das Part-Attribut nicht null ist, so ist der Boolean TRUE.
Beispiel:
In dem folgenden Ausdruck wird das Part-Attribute indexOfGoodsNumber des Parts intrastat des Business Objects Item adressiert:
SELECT FROM com.cisag.app.general.obj.Item item WHERE item:intrastat=TRUE AND
item:intrastat.indexOfGoodsNumber IS NULL
Ist das gewünschte Attribut ein Array-Attribut, so muss in eckigen Klammern noch der gewünschte Index angegeben werden.
Beispiel:
SELECT FROM com.cisag.app.inventory.obj.InventoryItem item WHERE item:uom[2] IS NOT NULL
Wenn das Array-Attribut vom Typ Part ist, dann wird das Attribut des Parts wie folgt adressiert:
Beispiel:
SELECT FROM com.cisag.app.inventory.obj.InventoryItem item WHERE item:uomConversionFactor[0].denominator IS NOT NULL
ExistsClause
Die ExistsClause ergibt true, wenn das SubSelect einen Wert zurückliefert und false wenn kein Wert zurückgeliefert wird.
Struktur des Syntax-Elements ExistsClause
SubSelect ist ein Select-Ausdruck mit der Syntax wie sie die Methode getResultSet erwartet (siehe Kapitel 6.2.2).
TermExpr
Das Syntax-Element TermExpr steht für einen OQL-Teilausdruck in dem Syntax-Elemente vom Typ Term mit arithmetischen Operatoren verknüpft werden können. Die arithmetischen Operatoren +, -, *, / werden mit ihrer üblichen Bedeutung unterstützt.
Struktur des Syntax-Elements TermExpr
Term
Der OQL-Teilausdruck Term steht für folgende OQL-Audrücke:
Struktur des Syntax-Elements Term
Die Syntax-Elemente AttributeRef und LogExpression wurden oben schon erläutert.
Literal
Struktur des Syntax-Elements Literal
STRING_LITERAL, INTEGER_LITERAL und FLOATINGPOINT_LITERAL sind oben schon beschrieben. Die Schlüsselwörter TRUE und FALSE besitzen ihre übliche Bedeutung. Das Schlüsselwort ZEROGUID steht für eine GUID, die aus Nullen besteht. Die Funktion TOGUID wandelt das in Klammern geschriebene STRING_LITERAL in eine GUID um. Die restlichen Elemente betreffen Zeit und Datum und werden in Kapitel 6.4 beschrieben.
Function
Das Syntax-Element hat folgende Struktur:
Struktur des Syntax-Elements Function
Die Schlüsselwörter AVG, MAX, MIN, SUM und COUNT sind Aggregatfunktionen mit der gleichen Bedeutung wie in SQL. Das Syntax-Element TermExpr wurde oben schon beschrieben.
Das Syntax-Element UPPER schreibt das Ergebnis des Ausdrucks TermExpr in Großbuchstaben.
SYSTEMTIME
Der Ausdruck SYSTEMTIME liefert die aktuelle Systemzeit des Datenbankservers.
Das Syntax-Element „?“
Das Fragezeichen (?) dient als Platzhalter für Teilausdrücke, welche erst zur Laufzeit bekannt sind. Die Klasse CisObjectIterator besitzt mehrere Methoden, mit denen die Symbole „?“ durch Werte ersetzt werden. Ein OQL-Ausdruck kann mehrere ?-Symbole enthalten. Den Methoden, welche die Symbole ersetzen sollen, muss jeweils die Position mitgegeben werden. Die Symbole werden mit 1 beginnend aufsteigend durchnummeriert.
Beispiel:
Der folgende Quelltextauszug lädt die Instanzen des Business Objects Item, denen eine bestimmte Maßeinheit (Business Object UnitOfMeasure) zugeordnet ist. Deren Primärschlüssel vom Typ GUID wird als Parameter am Iterator über die setGuid()-Methode gesetzt. Die Methode bekommt als Parameter die Position im OQL-Statement und die GUID.
byte[] uomGuid = … ;
CisObjectIterator iter = om.getObjectIterator(
”SELECT FROM com.cisag.app.general.obj.Item i WHERE i:uom=?”);
iter.setGuid(1, uomGuid);
LikeClause
Die LIKE-Bedingung dient zum einfachen Mustervergleich zwischen Zeichenketten.
Struktur des Syntax-Elements LikeClause
Wie aus SQL bekannt, können die Zeichen % und _ verwendet werden. Das Zeichen % steht für eine beliebige Zeichenfolge aus 0 oder mehr Zeichen. Der Unterstrich _ steht für genau ein Zeichen.
Beispiel:
Folgender Ausdruck liefert alle Business Objects von Item, bei denen das Attribut description mit F anfängt oder nur „F“ als Wert besitzt:
SELECT FROM com.cisag.app.general.obj.Item item WHERE item:description like ‘F%’
Über die Methode setString der Klasse CisObjectIterator kann dem Ausdruck auch zur Laufzeit ein berechneter Wert zum Mustervergleich übergeben werden:
String pattern = ‘%Schraube%’;
CisObjectIterator iter = om.getObjectIterator(
“SELECT FROM com.cisag.app.general.obj.Item i WHERE i:description like ?”);
iter.setString(1, pattern);
InClause
Die InClause dient dazu, nur die Instanzen von Business Objects zu erhalten, deren zuvor im Ausdruck definiertes Attribut (Position TermExpr) mit einem Wert aus der in Klammern angegebenen Liste von Werten übereinstimmt.
Struktur des Syntax-Elements InClause
Um in den Klammern eine Liste von Werten anzugeben, gibt es zwei Möglichkeiten: SubSelect (Syntax entspricht „getResultSet“) steht für einen SELECT-Ausdruck mit dem die Werte ermittelt werden. Die zweite Möglichkeit steht für eine mit Kommas getrennte Liste von TermExpr.
Beispiel:
Folgender Quelltextauszug ermittelt die Instanzen von Item, bei denen das Attribut description den Wert null, den Wert der Variable pattern1 oder pattern2 besitzt.
String pattern1=…;
String pattern2=…;
CisObjectIterator iter = om.getObjectIterator(
”SELECT FROM com.cisag.app.general.obj.Item i WHERE i:description IN (?,?)”);
iter.setString(1, pattern1);
iter.setString(2,pattern2);
BetweenClause
Mit der BetweenClause werden nur die Business Objects ermittelt, bei denen die Werte der zuvor in TermExpr definierten Attribute innerhalb eines bestimmten Wertebereiches liegen (bzw. nicht liegen bei der Verwendung von NOT). Die Grenzen des Wertebereiches werden mit dem Syntax-Element TermExpr definiert, welches oben schon beschrieben wurde.
Struktur des Syntax-Elements BetweenClause
CompareOpExpr
Die Vergleichsoperationen =, <>, >, <, >=, <= haben die gleiche Bedeutung wie in SQL.
Struktur des Syntax-Elements CompareOpExpr
ORDER BY
Wie in SQL so gibt es auch in der OQL die Möglichkeit, die Ergebnismenge sortieren zu lassen.
Struktur der ORDER BY-Klausel
Nach den Schlüsselwörtern ORDER BY werden die Attribute, nach denen sortiert werden soll, durch Komma getrennt aufgelistet. Nach jedem Attribut der Liste kann optional angegeben werden, ob nach dem Attribut aufsteigend (Schlüsselwort ASC) bzw. absteigend (Schlüsselwort DESC) sortiert werden soll. Wenn keine Sortierreihenfolge angegeben wurde, wird absteigend sortiert.
Beispiel:
Folgender Ausdruck gibt die Liste aller Business Objects vom Typ Item zurück, aufsteigend sortiert nach dem Attribut description:
SELECT FROM com.cisag.app.general.obj.Item item ORDER BY item:description
Folgender Ausdruck hat dieselbe Bedeutung:
SELECT FROM com.cisag.app.general.obj.Item item ORDER BY item:description ASC
6.2.2 Abfrage über getResultSet
Diese Methode liefert ein Objekt vom Typ com.cisag.pgm.appserver.CisResultSet. Hier können die im OQL bestimmten Attribute von einem oder mehreren Business Objects ausgelesen werden. Die Syntax für den OQL-Ausdruck, den diese Methode akzeptiert, hat folgende Struktur:
Syntax des OQL-Ausdrucks für getResultSet
Attributauswahl
Zwischen den Schlüsselwörtern SELECT und FROM müssen ein oder mehrere Attribute ausgewählt werden. Optional kann nach SELECT das Schlüsselwort DISTINCT folgen. Dieses sorgt dafür, dass bei der Auswahl von Attributen, welche in der Tabelle mehrfach gleiche Werte haben können, in der Ergebnisliste nur einmal vorkommen. Wenn mehrere Attribute abgefragt werden sollen, so müssen diese durch Komma getrennt angegeben werden. Die Attribute können optional mit dem Schlüsselwort AS gefolgt von einem Namen mit Aliassen versehen werden. Der Alias eines Attributs wird in OQL-Views verwendet, um den Attributnamen einer Rückgabespalte des Views zu definieren. Der Alias kann nicht innerhalb des OQL-Ausdrucks verwendet werden.
Object
Der Attributauswahl folgt das Schlüsselwort FROM. Zwischen dem Schlüsselwörtern FROM und WHERE werden die gewünschten Tabellen aufgelistet. Im einfachsten Fall werden nur Attribute einer Tabelle benötigt.
Beispiel:
SELECT item:number, item:description FROM com.cisag.app.general.obj.Item item
Wenn die Tabellennamen durch Komma getrennt aufgelistet werden, so wird ein Cross-Join ausgeführt.
Die Verwendung von Tabellennamen bzw. Joins können mit Klammern geschachtelt werden.
Struktur des Syntax-Elements Object
JoinClause
Unterschieden wird zwischen zwei Arten von Joins: Joins von Business Objects und Joins von dynamischen Business Objects.
Struktur des Syntax-Elements JoinClause
BusinessObjectJoin
Die Schlüsselwörter INNER, LEFT, RIGHT, FULL und OUTER haben die gleiche Bedeutung wie in SQL.
Struktur des Syntax-Elements BusinessObjectJoin
An der Position des Syntax-Elements LogExpression muss die Join-Bedingung erscheinen.
Beispiel:
Folgender Ausdruck liefert zu einer gegebenen JobDescription-GUID die Benutzer, die der JobDescription zugeordnet sind:
SELECT ua:user FROM com.cisag.app.general.obj.JobAssignment ja JOIN com.cisag.app.general.obj.UserAssignment ua ON ja:partner=ua:partner WHERE ja:jobDescription=?
DynamicBusinessObjectJoin
Mit dem Schlüsselwort DYNAMIC_OBJECT vor JOIN können die dynamischen Business Objects an Business Objects gejoint werden.
Struktur des Syntax-Elements DynamicBusinessObjectJoin
Das „Id“ unmittelbar hinter dem JOIN muss der Name des dynamischen Business Objects sein. Das „Id“ vor dem ON steht für den Alias des dynamischen Business Objects. Das „Id“ in Klammern kann optional den Namen eines mehrwertigen Attributes enthalten. Die Elemente von „Id“ in der ON-Klausel stehen einmal für den Alias des dynamischen Business Objects und den Alias des Business Objects, an dem das dynamische Business Object gejoint werden soll.
Beispiel:
Im folgenden OQL-Ausdruck wird das dynamische Business Object EXTItem an das Business Object com.cisag.app.general.obj.Item gejoint:
SELECT item:number FROM com.cisag.app.general.obj.Item item DYNAMIC_OBJECT JOIN EXTItem ei ON ei=item
Id
Das Syntax-Element Id steht für die schon beschriebenen Elemente „ID“ und „QUOTEDPATH“.
Struktur des Syntax-Elements Id
GROUP BY
In der FROM-Klausel des SELECT-Ausdruckes können die aus SQL bekannten Aggregatfunktionen verwendet werden. Wenn in der FROM-Klausel auch Attribute stehen, welche nicht in Aggregatsfunktionen verwendet werden, dann müssen diese Attribute in der GROUP BY-Klausel stehen.
Beispiel:
Im folgenden OQL-Ausdruck wird auf das Attribut count des Business Objects Boxy die Aggregat-Funktion COUNT angewendet. Das Attribut number wird nicht in einer Aggregat-Funktion verwendet und muss somit in der GROUP BY-Klausel erscheinen.
SELECT bo:number,COUNT(bo:amount) FROM com.cisag.app.general.obj.Boxy bo GROUP BY bo:number
HAVING
Die HAVING-Bedingung wird in Verbindung mit der „GROUP BY“-Klausel verwendet. Mit der HAVING-Bedingung kann definiert werden, dass nur die Gruppen im Ergebnis erscheinen sollen, welche die HAVING-Bedingung erfüllen.
Beispiel:
Im folgenden OQL-Ausdruck wird auf das Attribut count des Business Objects Boxy die Aggregat-Funktion COUNT angewendet. In der HAVING-Klausel wird definiert, dass nur die Gruppen im Ergebnis erscheinen sollen, bei denen die Bedingung erfüllt ist, dass die Anzahl von amount in der jeweiligen Gruppe größer 10 ist.
SELECT bo:number,COUNT(bo:amount) FROM com.cisag.app.general.obj.Boxy bo GROUP BY bo:number
HAVING COUNT(bo:amount)>10
ORDER BY
Wie in SQL so gibt es auch in der OQL die Möglichkeit, die Ergebnismenge sortieren zu lassen.
Struktur der ORDER BY-Klausel
Nach den Schlüsselwörtern ORDER BY werden die Attribute, nach denen sortiert werden soll, durch Komma getrennt aufgelistet. Alternativ können Sie statt nach einer Attribute-Referenz auch nach einer Spalte aus der Attributauswahl sortieren. Die Spalte aus der Attributauswahl identifizieren Sie über deren Position (1 bis n). Sie können ASC und DESC wie beim Objekt-Iterator verwenden.
Beispiel:
Folgender Ausdruck gibt die Liste aller Business Objects vom Typ Item zurück, aufsteigend sortiert nach dem Attribut description:
SELECT item:guid, item:description
FROM com.cisag.app.general.obj.Item item
ORDER BY item:description
Folgender Ausdruck hat dieselbe Bedeutung:
SELECT item:guid, item:description
FROM com.cisag.app.general.obj.Item item
ORDER BY 2
6.3 Modifikationen
Die Methode getUpdateStatement der Klasse CisObjectManager liefert ein Objekt vom Typ CisUpdateStatement und akzeptiert DELETE-, UPDATE- und INSERT-Ausdrücke. Sämtliche Syntax-Elemente der folgenden Diagramme wurden schon weiter oben im Dokument erläutert.
Bitte beachten Sie bei der Verwendung von Update-Statements die Auswirkungen auf die Performance und Datenkonsistenz, die im Referenzhandbuch zum Persistenzdienst beschrieben sind.
6.3.1 Löschen von Business Objects mit DELETE
Mit dem DELETE-Ausdruck werden alle Instanzen eines Business Objects gelöscht bzw. nur die Instanzen, die eine bestimmte Bedingung erfüllen.
Syntax des OQL-Ausdrucks DELETE
Beispiel:
Folgender Ausdruck löscht alle Instanzen des Business Objects Item:
DELETE FROM com.cisag.app.general.obj.Item item
Der nächste Ausdruck löscht nur die Instanzen, bei denen das Attribut originalItem einen Eintrag enthält:
DELETE FROM com.cisag.app.general.obj.Item item WHERE item:originalItem IS NOT NULL
6.3.2 Ändern von Business Objects mit UPDATE
Ein UPDATE-Ausdruck dient zum Ändern von Attribut-Werten von Business-Object-Instanzen. Möglich ist, entweder alle Instanzen zu verändern oder die Menge der zu ändernden Instanzen über die WHERE-Bedingung einzuschränken.
Syntax des OQL-Ausdrucks UPDATE
Beispiel:
Folgender Quelltextauszug ändert das Attribut name der Instanz des Business Objects Item mit der angegebenen GUID.
CisUpdateStatement up=om.getUpdateStatement(“
UPDATE com.cisag.app.general.obj.Partner partner SET partner:name=? WHERE partner:guid=?“);
up.setString(1,…);
up.setGuid(2,…);
Warnung:
Verboten ist, mit einem UPDATE-Ausdruck Unique-Key-Attribute zu ändern.
6.3.3 Erstellen von neuen Business Objects mit INSERT
Mit einem INSERT-Ausdruck können neue Instanzen von Business Objects erzeugt werden.
Syntax des OQL-Ausdrucks für Insert
Nach den Schlüsselwörtern INSERT INTO muss für PATH das gewünschte Business Object folgen. Danach werden in Klammern die Attribute benannt, welche mit Werten gefüllt werden sollen. Zwei Möglichkeiten existieren, um Werte anzugeben, die den Attributen zugeordnet werden sollen:
- Dem Schlüsselwort VALUES folgt in Klammern die Liste der Werte, jeweils durch Komma getrennt.
- Die Werte werden mit einem SubSelect ermittelt.
Empfohlen wird, INSERT in normalen Anwendungen nicht zu verwenden.
Beispiel:
CisUpdateStatement up=om.getUpdateStatement(“
INSERT INTO com.cisag.app.general.obj.Partner
(guid, number,type,name) VALUES(?,?,?,?)”);
up.setGuid(1,…);
up.setString(2,…);
…
6.4 Zeitstempel- und Datumsfunktionen
Der Ausdruck SYSTEMTIME liefert die aktuelle Uhrzeit des Datenbankservers.
Über die Funktion toTimeStamp()ist es möglich, Zeitstempel- oder Datumskonstanten anzugeben. Diese kann beispielsweise für Selektionen verwendet werden.
Sie müssen unbedingt den Datentyp des korrespondierenden Attributes berücksichtigen, um den korrekten Konstantenwert angeben zu können. Werten Sie dazu den Logischen Datentyp des Attributs aus. Die Zeitstempel- und Datums-Datentypen sind von speziell ausgezeichneten Logischen Datentypen abgeleitet, die den konkreten Datentyp des Attributes bestimmen. Die für ein Attribut gespeicherten Werte von Business-Object-Instanzen können sich auf unterschiedliche Zeitzonen beziehen. Dies müssen Sie bei der Formulierung der OQL-Anweisung ebenfalls beachten. Weitere Informationen finden Sie im Hilfe-Dokument „Datentypen des Typsystems“, dass Sie vor Benutzung dieser Funktionen lesen sollten.
Beachten Sie, dass eine Zeitzone über ihre Identifikation angeben werden muss und nicht über eine sprachabhängige Abkürzung. In der Anwendung „Zeitzonen“ im Framework „System-Management“ finden Sie die Tabelle der Zeitzonen mit den technischen Namen und deren Beschreibung. Für die verwendete Zeitzone in der aktuellen Sitzung wird die Zeitzonen-Identifikation im Tooltipp der Zeitzonenanzeige in der Statuszeile angezeigt. Beispielsweise ist „CET“ die Zeitzonen-Identifikation für die Zeitzone „(GMT+01:00) Europa Amsterdam, Andorra, Belgrad, Berlin, Brüssel, Budapest“, gebräuchliche deutsche Abkürzungen sind „MEZ“ oder „MESZ“.
6.4.1 SYSTEMTIME
Mit dem Ausdruck SYSTEMTIME ist es möglich, Spalten vom Typ „Timestamp“ mit der aktuellen Zeit des Datenbankservers zu vergleichen. Beispielsweise können Datensätze abgefragt werden, die mit einem Datum vor oder nach dem aktuellen Zeitpunkt versehen sind. So ermittelt folgende OQL-Anweisung Versionen von Artikeln, die erst in Zukunft gültig werden.
SELECT o:”number”, o:”validFrom” FROM com.cisag.app.general.obj.Item o WHERE o:”validFrom” > SYSTEMTIME
6.4.2 Funktion toTimeStamp()
Über die Funktion toTimeStamp() kann eine Zeitstempel-Konstante angegeben werden.
Auch die Datums-Datentypen von Comarch ERP Enterprise werden in der Datenbank auf Zeitstempel abgebildet. Deshalb können Sie mit dieser Funktion auch Datums-Konstanten angegeben.
Die Funktion hat die folgende Signatur:
toTimeStamp(’Zeitzonen-ID’, Jahr, Monat, Tag, Stunden, Minuten, Sekunden, Millisekunden)
Der Parameter „Zeitzonen-ID“ bestimmt, auf welche Zeitzone sich das angegebene Datum und Uhrzeit bezieht. Der angegebene Wert wird für das resultierende SQL-Statement in den entsprechenden Wert in der Zeitzone „GMT“ umgerechnet. In der Datenbank sind alle Zeitstempel in der Zeitzone „GMT“ gespeichert. Deshalb müssen Sie sicherstellen, dass Sie die richtige Zeitzone für den angegebenen Wert verwenden, damit auch wirklich der gewünschte Wert bzgl. der Zeitzone „GMT“ im SQL-Statement benutzt wird. Ansonsten wird ein falscher Zeitstempel im SQL-Statement verwendet, der zu unerwarteten Ergebnissen führen kann.
6.4.2.1 Angabe von Zeitstempel-Konstanten
Bei den Zeitstempel-Datentypen von Comarch ERP Enterprise können Sie den gewünschten Wert direkt angeben.
Beispiel
Der Zeitstempel „12.08.2006 08:21:06.233“ bzgl. der Zeitzone ‚CET’ wird folgendermaßen angegeben:
toTimeStamp(‘CET’, 2006, 8, 12, 8, 21,6, 233)
6.4.2.2 Angabe von Datumskonstanten
Um Datumskonstanten anzugeben, müssen bestimmte Bedingungen des Datentypssystems eingehalten werden. Ein Datumswert hat immer eine normierte Uhrzeit von „00:00:00.000“ und wird in der Datenbank als Zeitstempel gespeichert. Die Uhrzeit wird normalerweise nicht angezeigt. Um eine Datumskonstante anzugeben, müssen sie diese normierte Uhrzeit verwenden.
Beispiel
Das Datum „09.11.2006“ bzgl. der Zeitzone „CET“ wird folgendermaßen angegeben:
toTimeStamp(’CET’, 2006, 11, 9, 0, 0, 0, 0)
Ist der Comarch-ERP-Enterprise-Datentyp des korrespondierenden Attributes ein „lokales Bis-Datum“ müssen Sie beachten, dass der tatsächlich in der Datenbank gespeicherte Wert um einen Kalendertag verschoben ist. Deshalb müssen Sie einen Kalendertag auf den gewünschten Wert addieren.
Beispiel
Das Datum „09.11.2006“ bzgl. der Zeitzone „CET“ wird für Datentyp „lokales Bis-Datum“ folgendermaßen angegeben:
toTimeStamp(’CET’, 2006, 11, 10, 0, 0, 0, 0)
6.4.2.3 Nachbilden des Verhaltens von Suchen
Um bei Selektionen auf einem Attribut vom Typ „lokales Datum“ dasselbe Verhalten wie in den Suchen nachzubilden, muss ein Intervall angegeben werden, in dem die Zeitstempel für das gewünschte Datum liegen können. Eine Suche benutzt das Intervall vom vorigen Kalendertag mit der Uhrzeit „12:00:00.000“ bis zum angegebenen Datum mit der Uhrzeit „11:59:59.999“. Damit wird jeder Datumswert gefunden, der sich mit dem angegebenen Datumsbereich um mindestens 12 Stunden überschneidet.
Beispiel
Es sollen alle Sätze berücksichtigt werden, deren Datum der „09.11.2006“ ist:
…
WHERE … dateAttr >= toTimeStamp(’CET’, 2006, 11, 8, 12, 0, 0, 0) AND dateAttr < toTimeStamp(’CET’, 2006, 11, 9, 12, 0, 0, 0) …
Bei einem Attribut vom Typ „lokales Bis-Datum“ muss Verschiebung um einen Kalendertag bei der Bildung des Intervalls berücksichtigt werden.
6.4.3 Zeitstempel-Konstanten
Wichtige Zeitstempel-Konstanten werden über die folgenden OQL-Konstanten zur Verfügung gestellt:
OQL-Konstantenname | Bedeutung |
UNDEFINED_TIME_STAMP | Der Zeitstempel, der für den undefinierten Wert auf der Datenbank gespeichert wird. |
MIN_TIME_STAMP | Der kleinste auf der Datenbank speicherbare Zeitstempel |
MAX_TIME_STAMP | Der größte auf der Datenbank speicherbare Zeitstempel |
6.4.4 Funktion toTimeZoneGuid()
Über diese Funktion kann zu einer Zeitzonen-Identifikation die GUID der Zeitzone ermittelt werden. Damit ist es beispielsweise möglich, Zeitstempel- oder Datumswerte aus bestimmten Zeitzonen zu selektieren.
Die Funktion hat die folgende Signatur:
toTimeZoneGuid(’Zeitzonen-ID’)
Beispiel
Angabe der GUID der Zeitzone ‚CET’:
toTimeZoneGuid(’CET’)
6.5 Erweiterungen der OQL-Syntax für das Entwicklungsobjekt „Suche“
Über das Entwicklungsobjekt „Suche“ können Suchen für den Einsatz in anpassbaren Cockpits definiert werden. Zur Beschreibung des Anfrageergebnisses müssen Teile der OQL-Anweisung, wie z.B. die FROM-Klausel angegeben werden. Dazu können spezielle OQL-Syntax-Elemente verwendet werden, die nur in der Definition einer Suche erlaubt sind.
Join-Optimierung von OQL-Anweisungen
In einer Suche werden üblicherweise mehrere Joins zu Business Objects definiert, die nur das Ziel haben, den Spaltenvorrat der Suche für die Selektion, Anzeige und Sortierung zu erweitern. Abhängig von der konkret gestellten Suchanfrage können einige dieser Joins keinen Einfluss auf das Ergebnis der Suche haben. Solche Joins werden vor Ausführung der OQL-Anweisung automatisch erkannt und entfernt, um die Ausführungsperformance zu steigern.
Werden Attribute eines „gejointen“ Business Objects nur in der SELECT-Klausel verwendet, kann unter bestimmten Bedingungen auch dieser Join aus der OQL-Anweisung entfernt werden. Die Ermittlung der benötigten Attributwerte erfolgt in diesem Fall über den Persistenzdienst unter Ausnutzung des Shared Cache. Die so ermittelten Werte müssen aber nicht mehr mit den Werten in der Datenbank übereinstimmen, z.B. weil der Cache-Inhalt zum Zeitpunkt der Abfrage veraltet gewesen ist. Durch die Auszeichnung eines Joins mit dem Schlüsselwort „REMOVABLE“ legt der Entwickler der Suche fest, dass dieser Join bei der Suchausführung vom System entfernt werden darf, um die Ausführungsperformance zu erhöhen, aber auch, dass die über den Persistenzdienst ermittelten Daten inkonsistent zum tatsächlichen Datenbankinhalt sein dürfen (nicht transaktionssicher). Für die Anzeige von Daten in Cockpits oder Suchen ist die Transaktionssicherheit jedoch im Allgemeinen nicht erforderlich.
Folgende Bedingungen muss ein gejointes Business Object erfüllen, damit es aus der OQL-Anweisung entfernt werden kann:
- Der Join-Typ ist “LEFT OUTER” oder “RIGHT OUTER”.
- Es werden keine Attribute des gejointen Business Objects in den Klauseln WHERE, ORDER BY, GROUP BY oder HAVING verwendet. Werden Attribute des gejointen Business Objects in der SELECT-Klausel verwendet, so muss der Join explizit mit dem Schlüsselwort „REMOVABLE“ gekennzeichnet sein.
- Die Join-Bedingung muss über alle Attribute eines Schlüssels des gejointen Business Objects in der Form „Fremdschlüsselattribut1 = Schlüsselattribut1 AND Fremdschlüsselattribut2 = Schlüsselattribut2 AND …“ definiert sein und darf keine weiteren Bedingungen enthalten. Wurde bei einem zeitabhängigen Business Object das Attribut „validFrom“ nicht in der ON-Klausel angegeben, wird es wie bisher implizit berücksichtigt.
- Andere Joins, die sich in ihrer ON-Klausel auf den zu entfernenden Join beziehen, müssen sich ebenfalls entfernen lassen.
Struktur des Syntax-Elements entfernbarer Business Object-Join
Beispiel
Die OQL-Anweisung
SELECT p:number, l:isoCode
FROM com.cisag.app.general.obj.Partner p REMOVABLE LEFT OUTER JOIN com.cisag.app.general.obj.Language l on p:language = l:guid
wird intern zur OQL-Anweisung
SELECT p:number, p:language
FROM com.cisag.app.general.obj.Partner p
umgeformt, die auf der Datenbank ausgeführt wird. Bei Abfrage von „l:isoCode“ vom Result Set wird über den Attributwert von „p:language“ der Persistenzdienstschlüssel erzeugt, die zugehörige Sprachen-Instanz über den Persistenzdienst geladen und der Wert des Attributes „isoCode“ zurückgegeben.