09.02.2013 Aufrufe

Adaptive Server® Anywhere Handbuch für Programmierer - Sybase

Adaptive Server® Anywhere Handbuch für Programmierer - Sybase

Adaptive Server® Anywhere Handbuch für Programmierer - Sybase

MEHR ANZEIGEN
WENIGER ANZEIGEN

Sie wollen auch ein ePaper? Erhöhen Sie die Reichweite Ihrer Titel.

YUMPU macht aus Druck-PDFs automatisch weboptimierte ePaper, die Google liebt.

<strong>Adaptive</strong> <strong>Server®</strong> <strong>Anywhere</strong><br />

<strong>Handbuch</strong> <strong>für</strong> <strong>Programmierer</strong><br />

Stand: Oktober 2002<br />

Bestellnummer: 03946-01-0802-01


Copyright © 1989–2002 <strong>Sybase</strong>, Inc. Teil-Copyright © 2002 i<strong>Anywhere</strong> Solutions, Inc. Alle Rechte vorbehalten.<br />

Diese Publikation darf ohne vorheriges schriftliches Einverständnis der i<strong>Anywhere</strong> Solutions, Inc. weder ganz noch teilweise, weder elektronisch,<br />

mechanisch, manuell, optisch, noch auf sonst eine Weise reproduziert, übertragen oder übersetzt werden. i<strong>Anywhere</strong> Solutions, Inc ist eine<br />

Tochtergesellschaft der <strong>Sybase</strong> Inc.<br />

<strong>Sybase</strong>, das SYBASE-Logo, AccelaTrade, ADA Workbench, Adaptable Windowing Environment, <strong>Adaptive</strong> Component Architecture, <strong>Adaptive</strong><br />

Server, <strong>Adaptive</strong> Server <strong>Anywhere</strong>, <strong>Adaptive</strong> Server Enterprise, <strong>Adaptive</strong> Server Enterprise Monitor, <strong>Adaptive</strong> Server Enterprise Replication,<br />

<strong>Adaptive</strong> Server Everywhere, <strong>Adaptive</strong> Server IQ, <strong>Adaptive</strong> Warehouse, AnswerBase, <strong>Anywhere</strong> Studio, Application Manager, AppModeler,<br />

APT Workbench, APT-Build, APT-Edit, APT-Execute, APT-FORMS, APT-Library, APT-Translator, ASEP, Backup Server, BayCam, Bit-Wise,<br />

BizTracker, Certified PowerBuilder Developer, Certified SYBASE Professional, Certified SYBASE Professional (Logo), ClearConnect, Client<br />

Services, Client-Library, CodeBank, Column Design, ComponentPack, Connection Manager, Convoy/DM, Copernicus, CSP, Data Pipeline, Data<br />

Workbench, DataArchitect, Database Analyzer, DataExpress, DataServer, DataWindow, DB-Library, dbQueue, Developers Workbench, Direct<br />

Connect <strong>Anywhere</strong>, DirectConnect, Distribution Director, Dynamo, e-ADK, E-<strong>Anywhere</strong>, e-Biz Integrator, E-Whatever, EC-GATEWAY, ECMAP,<br />

ECRTP, eFulfillment Accelerator, Electronic Case Management, Embedded SQL, EMS, Enterprise Application Studio, Enterprise Client/Server,<br />

Enterprise Connect, Enterprise Data Studio, Enterprise Manager, Enterprise SQL Server Manager, Enterprise Work Architecture, Enterprise Work<br />

Designer, Enterprise Work Modeler, eProcurement Accelerator, eremote, Everything Works Better When Everything Works Together, EWA,<br />

Financial Fusion, Financial Fusion Server, First Impression, Formula One, Gateway Manager, GeoPoint, i<strong>Anywhere</strong>, i<strong>Anywhere</strong> Solutions,<br />

ImpactNow, Industry Warehouse Studio, InfoMaker, Information <strong>Anywhere</strong>, Information Everywhere, InformationConnect, InstaHelp, Intellidex,<br />

InternetBuilder, iremote, iScript, Jaguar CTS, jConnect for JDBC, KnowledgeBase, Logical Memory Manager, MainframeConnect, Maintenance<br />

Express, MAP, MDI Access Server, MDI Database Gateway, media.splash, MetaWorks, MethodSet, ML Query, MobiCATS, MySupport,<br />

Net-Gateway, Net-Library, New Era of Networks, Next Generation Learning, Next Generation Learning Studio, O DEVICE, OASiS, OASiS (logo),<br />

ObjectConnect, ObjectCycle, OmniConnect, OmniSQL Access Module, OmniSQL Toolkit, Open Biz, Open Business Interchange, Open Client,<br />

Open Client/Server, Open Client/Server Interfaces, Open ClientConnect, Open Gateway, Open Server, Open ServerConnect, Open Solutions,<br />

Optima++, Partnerships that Work, PB-Gen, PC APT Execute, PC DB-Net, PC Net Library, PhysicalArchitect, Pocket PowerBuilder,<br />

PocketBuilder, Power Through Knowledge, Power++, power.stop, PowerAMC, PowerBuilder, PowerBuilder Foundation Class Library,<br />

PowerDesigner, PowerDimensions, PowerDynamo, Powering the New Economy, PowerJ, PowerScript, PowerSite, PowerSocket, Powersoft,<br />

Powersoft Portfolio, Powersoft Professional, PowerStage, PowerStudio, PowerTips, PowerWare Desktop, PowerWare Enterprise, ProcessAnalyst,<br />

Rapport, Relational Beans, Replication Agent, Replication Driver, Replication Server, Replication Server Manager, Replication Toolkit, Report<br />

Workbench, Report-Execute, Resource Manager, RW-DisplayLib, RW-Library, S Designor, S-Designor, S.W.I.F.T. Message Format Libraries,<br />

SAFE, SAFE/PRO, SDF, Secure SQL Server, Secure SQL Toolset, Security Guardian, SKILS, smart.partners, smart.parts, smart.script,<br />

SQL Advantage, SQL <strong>Anywhere</strong>, SQL <strong>Anywhere</strong> Studio, SQL Code Checker, SQL Debug, SQL Edit, SQL Edit/TPU, SQL Everywhere,<br />

SQL Modeler, SQL Remote, SQL Server, SQL Server Manager, SQL Server SNMP SubAgent, SQL Server/CFT, SQL Server/DBM, SQL SMART,<br />

SQL Station, SQL Toolset, SQLJ, Stage III Engineering, Startup.Com, STEP, SupportNow, <strong>Sybase</strong> Central, <strong>Sybase</strong> Client/Server Interfaces, <strong>Sybase</strong><br />

Development Framework, <strong>Sybase</strong> Financial Server, <strong>Sybase</strong> Gateways, <strong>Sybase</strong> Learning Connection, <strong>Sybase</strong> MPP, <strong>Sybase</strong> SQL Desktop, <strong>Sybase</strong><br />

SQL Lifecycle, <strong>Sybase</strong> SQL Workgroup, <strong>Sybase</strong> Synergy Program, <strong>Sybase</strong> User Workbench, <strong>Sybase</strong> Virtual Server Architecture, <strong>Sybase</strong>Ware,<br />

Syber Financial, SyberAssist, SybMD, SyBooks, System 10, System 11, System XI (Logo), SystemTools, Tabular Data Stream, The Enterprise<br />

Client/Server Company, The Extensible Software Platform, The Future Is Wide Open, The Learning Connection, The Model For Client/Server<br />

Solutions, The Online Information Center, The Power of One, TradeForce, Transact-SQL, Translation Toolkit, Turning Imagination Into Reality,<br />

UltraLite, UNIBOM, Unilib, Uninull, Unisep, Unistring, URK Runtime Kit for UniCode, Viewer, Visual Components, VisualSpeller, VisualWriter,<br />

VQL, Warehouse Control Center, Warehouse Studio, Warehouse WORKS, WarehouseArchitect, Watcom, Watcom SQL, Watcom SQL Server,<br />

Web Deployment Kit, Web.PB, Web.SQL, WebSights, WebViewer, WorkGroup SQL Server, XA-Library, XA-Server und XP Server sind Marken<br />

von <strong>Sybase</strong>, Inc. oder ihren Tochtergesellschaften.<br />

Alle anderen Marken sind Eigentum ihrer jeweiligen Eigentümer.<br />

Stand: Oktober 2002. Bestellnummer: 03946-01-0802-01.


Inhalt<br />

Über dieses <strong>Handbuch</strong>.................................................... vii<br />

Dokumentation zu SQL <strong>Anywhere</strong> Studio ..............................viii<br />

Konventionen in dieser Dokumentation ................................... xi<br />

<strong>Adaptive</strong> Server <strong>Anywhere</strong>-Beispieldatenbank.......................xiv<br />

Wenn Sie mehr wissen und uns Ihre Anregungen<br />

mitteilen möchten.................................................................... xv<br />

1 Überblick über die Programmierschnittstelle.................. 1<br />

Die ODBC-Programmierschnittstelle ........................................2<br />

Die Programmierschnittstelle OLE DB......................................3<br />

Die Embedded SQL-Programmierschnittstelle .........................4<br />

Die JDBC-Programmierschnittstelle .........................................5<br />

Die Open Client-Programmierschnittstelle................................6<br />

2 SQL in Anwendungen verwenden .................................... 9<br />

SQL-Anweisungen in Anwendungen ausführen .....................10<br />

Anweisungen vorbereiten .......................................................12<br />

Der Cursor...............................................................................15<br />

Mit Cursorn arbeiten................................................................20<br />

Cursortypen auswählen ..........................................................26<br />

<strong>Adaptive</strong> Server <strong>Anywhere</strong>-Cursor .........................................30<br />

Ergebnismengen beschreiben ................................................47<br />

Transaktionen in Anwendungen steuern ................................49<br />

3 Einführung in Java <strong>für</strong> Datenbanken.............................. 53<br />

Einleitung ................................................................................54<br />

Fragen und Antworten zu Java in der Datenbank ..................57<br />

Ein Java-Seminar....................................................................64<br />

Die Laufzeitumgebung <strong>für</strong> Java in der Datenbank..................75<br />

Praktische Einführung: Eine Übung mit Java in<br />

der Datenbank.........................................................................84<br />

iii


4 Java in der Datenbank benutzen .................................... 93<br />

Einleitung ................................................................................ 94<br />

Datenbank <strong>für</strong> Java aktivieren ................................................ 97<br />

Java-Klassen in einer Datenbank installieren....................... 103<br />

Spalten <strong>für</strong> die Aufnahme von Java-Objekten<br />

erstellen................................................................................. 109<br />

Java-Objekte einfügen, aktualisieren und löschen ............... 111<br />

Java-Objekte abfragen.......................................................... 117<br />

Java-Felder und Objekte vergleichen ................................... 119<br />

Besondere Funktionen von Java-Klassen in der<br />

Datenbank............................................................................. 123<br />

So werden Java-Objekte gespeichert................................... 130<br />

Java-Datenbankdesign ......................................................... 133<br />

Berechnete Spalten mit Java-Klassen verwenden ............... 137<br />

Speicher <strong>für</strong> Java konfigurieren ............................................ 140<br />

5 Datenzugriff über JDBC ................................................ 143<br />

Überblick über JDBC ............................................................ 144<br />

jConnect-JDBC-Treiber verwenden...................................... 150<br />

JDBC-ODBC-Brücke verwenden.......................................... 155<br />

JDBC-Verbindungen herstellen ............................................ 157<br />

JDBC <strong>für</strong> den Zugriff auf Daten verwenden.......................... 165<br />

Verteilte Anwendungen erstellen .......................................... 174<br />

6 Programmieren mit Embedded SQL ............................ 181<br />

Überblick ............................................................................... 182<br />

Beispielprogramme mit Embedded SQL .............................. 190<br />

Datentypen in Embedded SQL ............................................. 196<br />

Hostvariable benutzen .......................................................... 200<br />

SQL-Kommunikationsbereich (SQLCA) ............................... 208<br />

Daten abrufen ....................................................................... 214<br />

Statische und dynamische SQL............................................ 223<br />

Der SQL-Deskriptor-Bereich (SQLDA) ................................. 228<br />

Lange Werte senden und abfragen ...................................... 237<br />

Gespeicherte Prozeduren verwenden .................................. 243<br />

Programmiertechniken <strong>für</strong> Embedded SQL.......................... 247<br />

SQL-Präprozessor ................................................................ 249<br />

Referenz der Bibliotheksfunktion .......................................... 253<br />

Befehlszusammenfassung <strong>für</strong> Embedded SQL.................... 272<br />

7 ODBC-Programmierung................................................ 277<br />

Einführung in ODBC ............................................................. 278<br />

ODBC-Anwendungen erstellen............................................. 280<br />

ODBC-Beispiele.................................................................... 285<br />

iv


ODBC-Handles .....................................................................287<br />

Verbindung mit einer Datenquelle herstellen........................290<br />

SQL-Anweisungen ausführen ...............................................294<br />

Mit Ergebnismengen arbeiten ...............................................299<br />

Gespeicherte Prozeduren aufrufen.......................................304<br />

Umgang mit Fehlern..............................................................306<br />

8 Die DBTools-Schnittstelle ............................................. 311<br />

Einführung in die DBTools-Schnittstelle................................312<br />

DBTools-Schnittstelle verwenden.........................................314<br />

DBTools-Funktionen .............................................................323<br />

DBTools-Strukturen...............................................................335<br />

DBTools-Aufzählungstypen ..................................................367<br />

9 Die OLE DB- und ADO-Programmierschnittstellen ..... 371<br />

Einführung zu OLE DB..........................................................372<br />

ADO-Programmierung mit <strong>Adaptive</strong> Server<br />

<strong>Anywhere</strong> ..............................................................................374<br />

Unterstützte OLE DB-Schnittstellen......................................382<br />

10 Die Open Client-Schnittstelle........................................ 389<br />

Was Sie <strong>für</strong> die Entwicklung von Open Client-<br />

Anwendungen brauchen .......................................................390<br />

Datentyp-Zuordnungen .........................................................391<br />

SQL in Open Client-Anwendungen verwenden ....................394<br />

Bekannte Open Client-Einschränkungen von<br />

<strong>Adaptive</strong> Server <strong>Anywhere</strong> ...................................................398<br />

11 Dreischichtige Datenverarbeitung und verteilte<br />

Transaktionen ................................................................ 399<br />

Einleitung ..............................................................................400<br />

Dreischichtige Datenverarbeitungsarchitektur ......................401<br />

Verteilte Transaktionen verwenden ......................................405<br />

EAServer mit <strong>Adaptive</strong> Server <strong>Anywhere</strong><br />

verwenden.............................................................................407<br />

12 Deployment: Datenbanken und Anwendungen im System<br />

bereitstellen ................................................................... 411<br />

Systemeinführung - Überblick...............................................412<br />

Installationsverzeichnisse und Dateinamen..........................415<br />

InstallShield-Objekte und Vorlagen zum<br />

Bereitstellen verwenden........................................................420<br />

v


vi<br />

Dialogfreie Installation <strong>für</strong> die Systemeinführung ................. 422<br />

Clientanwendungen im System bereitstellen........................ 426<br />

Tools zur Verwaltung bereitstellen........................................ 437<br />

Datenbankserver im System bereitstellen ............................ 438<br />

Eingebettete Datenbankanwendungen im System<br />

bereitstellen........................................................................... 441<br />

13 Fehlermeldungen des SQL-Präprozessors.................. 445<br />

Fehlermeldungen des SQL-Präprozessors,<br />

sortiert nach Fehlernummern................................................ 446<br />

SQLPP-Fehler....................................................................... 450<br />

Index............................................................................... 467


Über dieses <strong>Handbuch</strong><br />

Gegenstand<br />

Zielgruppe<br />

In diesem <strong>Handbuch</strong> wird beschrieben, wie Datenbankanwendungen in den<br />

Programmiersprachen C, C++ und Java aufgebaut und bereitgestellt werden.<br />

Benutzer von Programmen wie Visual Basic und PowerBuilder können deren<br />

Programmierschnittstellen einsetzen.<br />

Das <strong>Handbuch</strong> ist <strong>für</strong> Anwendungsentwickler bestimmt, die Programme<br />

schreiben, welche direkt mit einer der Schnittstellen von <strong>Adaptive</strong> Server<br />

<strong>Anywhere</strong> interagieren.<br />

Sie brauchen das <strong>Handbuch</strong> nicht zu lesen, wenn Sie ein Entwicklungstool<br />

wie PowerBuilder oder Visual Basic verwenden, die eine eigene Datenbank-<br />

Schnittstelle nach dem ODBC-Standard benutzen.<br />

vii


Dokumentation zu SQL <strong>Anywhere</strong> Studio<br />

viii<br />

Diese Dokumentation ist Teil der SQL <strong>Anywhere</strong>-Dokumentation. Dieser<br />

Abschnitt enthält eine Liste der Handbücher und Hinweise zu ihrer<br />

Verwendung.<br />

Dokumentation zu SQL <strong>Anywhere</strong> Studio<br />

Die Dokumentation zu SQL <strong>Anywhere</strong> Studio besteht aus folgenden<br />

Handbüchern:<br />

♦ SQL <strong>Anywhere</strong> Studio Erste Orientierung Dieses <strong>Handbuch</strong> enthält<br />

einen Überblick über die Datenbankverwaltungs- und<br />

Synchronisationstechnologien von SQL <strong>Anywhere</strong> Studio. Es enthält<br />

praktische Einführungen zu einzelnen Bestandteilen von SQL <strong>Anywhere</strong><br />

Studio.<br />

♦ Neues in SQL <strong>Anywhere</strong> Studio Dieses <strong>Handbuch</strong> richtet sich an<br />

Benutzer früherer Versionen dieser Software. Es enthält eine Liste neuer<br />

Funktionen in dieser und in früheren Versionen des Programms und eine<br />

Beschreibung der Upgrade-Prozeduren.<br />

♦ <strong>Adaptive</strong> Server <strong>Anywhere</strong> Erste Schritte Dieses <strong>Handbuch</strong> richtet<br />

sich an Personen, die noch nicht mit relationalen Datenbanken bzw. mit<br />

<strong>Adaptive</strong> Server <strong>Anywhere</strong> gearbeitet haben. Es enthält eine<br />

Kurzeinführung in das Datenbankverwaltungssystem <strong>Adaptive</strong> Server<br />

<strong>Anywhere</strong> und einführende Hinweise zum Entwerfen und Aufbauen von<br />

Datenbanken sowie zur Arbeit mit Datenbanken.<br />

♦ <strong>Adaptive</strong> Server <strong>Anywhere</strong> Datenbankadministration Dieses<br />

<strong>Handbuch</strong> befasst sich mit der Ausführung, Verwaltung und<br />

Konfiguration von Datenbanken.<br />

♦ <strong>Adaptive</strong> Server <strong>Anywhere</strong> SQL-Benutzerhandbuch In diesem<br />

<strong>Handbuch</strong> wird beschrieben, wie Datenbanken entworfen und<br />

eingerichtet, Daten importiert, exportiert, geändert bzw. abgerufen und<br />

gespeicherte Prozeduren und Trigger aufgebaut werden.<br />

♦ <strong>Adaptive</strong> Server <strong>Anywhere</strong> SQL-Referenzhandbuch Dieses <strong>Handbuch</strong><br />

ist eine umfassende Referenz <strong>für</strong> die in <strong>Adaptive</strong> Server <strong>Anywhere</strong><br />

verwendete SQL-Sprache. Auch die <strong>Adaptive</strong> Server <strong>Anywhere</strong>-<br />

Systemtabellen und Prozeduren werden darin beschrieben.


♦ <strong>Adaptive</strong> Server <strong>Anywhere</strong> <strong>Handbuch</strong> <strong>für</strong> <strong>Programmierer</strong> In diesem<br />

<strong>Handbuch</strong> wird beschrieben, wie Datenbankanwendungen in den<br />

Programmiersprachen C, C++ und Java aufgebaut und bereitgestellt<br />

werden. Benutzer von Programmen wie Visual Basic und PowerBuilder<br />

können deren Programmierschnittstellen einsetzen.<br />

♦ <strong>Adaptive</strong> Server <strong>Anywhere</strong> Fehlermeldungen Dieses <strong>Handbuch</strong><br />

enthält eine vollständige Liste der Fehlermeldungen in <strong>Adaptive</strong> Server<br />

<strong>Anywhere</strong> sowie Diagnosehinweise.<br />

♦ <strong>Adaptive</strong> Server <strong>Anywhere</strong> Ergänzung zu C2-Sicherheitssystemen<br />

<strong>Adaptive</strong> Server <strong>Anywhere</strong> 7.0 wurde die Sicherheitseinstufung TCSEC<br />

(Trusted Computer System Evaluation Criteria) C2 der US-Regierung<br />

verliehen. Dieses <strong>Handbuch</strong> kann <strong>für</strong> den Personenkreis von Interesse<br />

sein, der die aktuelle Version von <strong>Adaptive</strong> Server <strong>Anywhere</strong> in einer<br />

Umgebung ausführen möchte, die dem C2-Zertifikat entspricht. Nach<br />

der Zertifizierung hinzugefügte Sicherheitsfunktionen werden im<br />

<strong>Handbuch</strong> nicht erwähnt.<br />

♦ MobiLink Benutzerhandbuch In diesem <strong>Handbuch</strong> werden alle<br />

Aspekte des MobiLink-Datensynchronisationssystems <strong>für</strong> die mobile<br />

Datenverarbeitung erläutert. Mit diesem System können Daten von<br />

einzelnen Oracle-, <strong>Sybase</strong>-, Microsoft- oder IBM-Datenbanken und<br />

vielen <strong>Adaptive</strong> Server <strong>Anywhere</strong>- bzw. UltraLite-Datenbanken<br />

gemeinsam genutzt werden.<br />

♦ SQL Remote Benutzerhandbuch In diesem <strong>Handbuch</strong> werden alle<br />

Aspekte des SQL Remote-Datenreplikationssystems <strong>für</strong> mobile<br />

Datenverarbeitung beschrieben, das die gemeinsame Datennutzung von<br />

einer einzelnen <strong>Adaptive</strong> Server <strong>Anywhere</strong>- bzw. <strong>Adaptive</strong> Server<br />

Enterprise-Datenbank und vielen <strong>Adaptive</strong> Server <strong>Anywhere</strong>-<br />

Datenbanken über eine indirekte Verbindung wie etwa E-Mail oder<br />

Datenübertragung ermöglicht.<br />

♦ UltraLite Benutzerhandbuch In diesem <strong>Handbuch</strong> wird beschrieben,<br />

wie Datenbankanwendungen <strong>für</strong> kleine Geräte wie Organizer mit der<br />

UltraLite-Bereitstellungstechnologie <strong>für</strong> <strong>Adaptive</strong> Server <strong>Anywhere</strong>-<br />

Datenbanken aufgebaut werden.<br />

♦ UltraLite User’s Guide for PenRight! MobileBuilder (nur in<br />

englischer Sprache verfügbar) Dieses <strong>Handbuch</strong> richtet sich an<br />

Benutzer des Entwicklungsprogramms PenRight! MobileBuilder. Hier<br />

wird beschrieben, wie die UltraLite-Technologie in der MobileBuilder-<br />

Programmierumgebung eingesetzt wird.<br />

♦ SQL <strong>Anywhere</strong> Studio-Hilfe Dieses <strong>Handbuch</strong> ist nur online verfügbar.<br />

Es enthält die kontextsensitive Hilfe <strong>für</strong> <strong>Sybase</strong> Central, Interactive SQL<br />

und andere grafische Programme.<br />

ix


Dokumentationsformate<br />

x<br />

Zusätzlich zu dieser Dokumentation werden SQL Modeler und InfoMaker<br />

mit eigener Dokumentation geliefert.<br />

SQL <strong>Anywhere</strong> Studio umfasst Dokumentationen in folgenden Formaten:<br />

♦ Online-Dokumentation Die Online-Dokumentation enthält die<br />

vollständige SQL <strong>Anywhere</strong> Studio-Dokumentation, einschließlich der<br />

gedruckten Handbücher und der kontextsensitiven Hilfe <strong>für</strong> die<br />

SQL <strong>Anywhere</strong>-Dienstprogramme. Die Online-Dokumentation wird mit<br />

jeder Wartungsversion des Produkts aktualisiert. Dies ist die<br />

vollständigste und aktuellste Informationsquelle.<br />

Wenn Sie unter Windows-Betriebssystemen auf die Online-<br />

Dokumentation zugreifen wollen, klicken Sie auf<br />

Start➤Programme➤<strong>Sybase</strong> SQL <strong>Anywhere</strong> 8➤Online-Dokumentation.<br />

Der Zugriff auf den Inhalt erfolgt über die HTML-Inhaltsangabe, den<br />

Index und die Suchfunktion im linken Fensterausschnitt sowie über<br />

Links und Menüs im rechten Fensterausschnitt.<br />

Unter UNIX-Betriebssystemen geben Sie den folgenden Befehl in einer<br />

Befehlszeile ein, damit die Dokumentation aufgerufen wird:<br />

dbbooks<br />

♦ Ausdruckbare Handbücher Die SQL <strong>Anywhere</strong>-Handbücher werden<br />

in Form von PDF-Dateien geliefert, die mit dem Adobe Acrobat Reader<br />

eingesehen werden können.<br />

Die PDF-Dateien finden sich auf der CD-ROM im Verzeichnis<br />

pdf_docs. Während der Installation können Sie entscheiden, ob sie<br />

installiert werden sollen.<br />

♦ Gedruckte Handbücher Die folgenden Handbücher finden Sie in der<br />

SQL <strong>Anywhere</strong> Studio-Box:<br />

♦ SQL <strong>Anywhere</strong> Studio Erste Orientierung<br />

♦ <strong>Adaptive</strong> Server <strong>Anywhere</strong> Erste Schritte<br />

♦ SQL <strong>Anywhere</strong> Studio Kurzreferenz. Dieses <strong>Handbuch</strong> ist nur in<br />

gedruckter Form verfügbar.<br />

Der gesamte <strong>Handbuch</strong>satz kann als SQL <strong>Anywhere</strong>-Dokumentation<br />

über den <strong>Sybase</strong>-Vertrieb bzw. den e-Shop - den <strong>Sybase</strong>-Online-<br />

Vertrieb - bezogen werden, und zwar unter der Adresse http://eshop.sybase.com/cgi-bin/eshop.storefront/.


Konventionen in dieser Dokumentation<br />

Syntaxkonventionen<br />

In diesem Abschnitt werden die Konventionen <strong>für</strong> die Schreibweise und der<br />

grafische Aufbau beschrieben, der in dieser Dokumentation verwendet wird.<br />

Folgende Konventionen werden bei SQL-Syntaxbeispielen verwendet:<br />

♦ Schlüsselwörter Alle SQL-Schlüsselwörter werden wie die Wörter<br />

ALTER TABLE im folgenden Beispiel angezeigt:<br />

ALTER TABLE [ Eigentümer.]Tabellenname<br />

♦ Platzhalter Elemente, die durch entsprechende Identifizierer oder<br />

Ausdrücke ersetzt werden müssen, werden wie die Wörter Eigentümer<br />

und Tabellenname im folgenden Beispiel angezeigt:<br />

ALTER TABLE [ Eigentümer.]Tabellenname<br />

♦ Wiederholungen Listen mit sich wiederholenden Elementen werden mit<br />

einem Element der Liste, gefolgt von drei Punkten gezeigt, wie Spalten-<br />

Integritätsregel im folgenden Beispiel:<br />

ADD Spaltendefinition [ Spalten-Integritätsregel, … ]<br />

Ein oder mehrere Listenelemente sind zulässig. Wenn mehr als ein<br />

Element angegeben wird, muss eine Trennung der Elemente durch<br />

Kommas erfolgen.<br />

♦ Fakultative Bestandteile Fakultative Bestandteile einer Anweisung<br />

werden in eckige Klammern gesetzt.<br />

RELEASE SAVEPOINT [ Savepoint-Name ]<br />

Diese eckigen Klammern zeigen an, dass der Savepoint-Name fakultativ<br />

ist. Die eckigen Klammern werden nicht eingegeben.<br />

♦ Optionen Wenn aus einer Liste kein oder nur ein Element ausgewählt<br />

werden darf, werden die Elemente durch Senkrechtstriche voneinander<br />

getrennt, und die komplette Liste wird in eckige Klammern gesetzt.<br />

[ ASC | DESC ]<br />

Sie können z.B. entweder ASC, DESC oder keines wählen. Die eckigen<br />

Klammern werden nicht eingegeben.<br />

♦ Alternativen Wenn nur eine der vorhandenen Optionen gewählt werden<br />

darf, werden die Alternativen in geschweifte Klammern gesetzt.<br />

[ QUOTES { ON | OFF } ]<br />

xi


Grafische Symbole<br />

xii<br />

Wenn die Option QUOTES ausgewählt wird, muss entweder ON oder<br />

OFF angegeben werden. Eckige und geschweifte Klammern sind nicht<br />

einzugeben.<br />

♦ Eine oder mehrere Optionen Wenn Sie mehr als eine wählen, trennen<br />

Sie die Eingaben durch Kommas.<br />

{ CONNECT, DBA, RESOURCE }<br />

Folgende Symbole werden in dieser Dokumentation verwendet:


Symbol Bedeutung<br />

API<br />

Eine Clientanwendung<br />

Ein Datenbankserver, wie etwa <strong>Sybase</strong> <strong>Adaptive</strong><br />

Server <strong>Anywhere</strong> oder <strong>Adaptive</strong> Server Enterprise<br />

Eine UltraLite-Anwendung und der Datenbankserver.<br />

Bei UltraLite sind der Datenbankserver und die<br />

Anwendung Teil des gleichen Prozesses.<br />

Eine Datenbank. In einigen abstrakten Diagrammen<br />

kann dieses Symbol die Datenbank und gleichzeitig<br />

auch den Datenbankserver, der sie steuert,<br />

repräsentieren.<br />

Replikations- oder Synchronisations-Middleware. Mit<br />

Hilfe derartiger Software können Daten in mehreren<br />

Datenbanken gleichzeitig verwendet werden.<br />

Beispiele sind der MobiLink Synchronisationsserver,<br />

der SQL Remote-Nachrichtenagent und der<br />

Replication Agent (Log Transfer Manager), der in<br />

Replication Server eingesetzt wird.<br />

Ein <strong>Sybase</strong> Replication Server<br />

Eine Programmierschnittstelle<br />

xiii


<strong>Adaptive</strong> Server <strong>Anywhere</strong>-Beispieldatenbank<br />

xiv<br />

Viele der in der Dokumentation beschriebenen Beispiele verwenden die<br />

<strong>Adaptive</strong> Server <strong>Anywhere</strong>-Beispieldatenbank.<br />

Die Beispieldatenbank befindet sich in einer Datei mit dem Namen<br />

asademo.db im Installationsverzeichnis von SQL <strong>Anywhere</strong>.<br />

Die Beispieldatenbank stellt ein kleines Unternehmen dar. Sie enthält interne<br />

Informationen über das Unternehmen wie Mitarbeiter (employees),<br />

Abteilungen (departments) und Finanzdaten (finances) sowie<br />

Produktinformationen (products) und Verkaufsinformationen (sales orders,<br />

customers, contacts). Alle Daten in der Datenbank sind frei erfunden.<br />

In der nachstehend abgebildeten Strukturdarstellung werden die Tabellen der<br />

Beispieldatenbank und ihre Beziehungen zueinander erläutert.<br />

product<br />

id integer<br />

name char(15)<br />

description char(30)<br />

size char(18)<br />

color char(6)<br />

quantity integer<br />

unit_price numeric(15,2)<br />

customer<br />

id integer<br />

fname char(15)<br />

lname char(20)<br />

address char(35)<br />

city char(20)<br />

state char(2)<br />

zip char(10)<br />

phone char(12)<br />

company_name char(35)<br />

contact<br />

id integer<br />

last_name char(15)<br />

first_name char(15)<br />

title char(2)<br />

street char(30)<br />

city char(20)<br />

state char(2)<br />

zip char(5)<br />

phone char(10)<br />

fax char(10)<br />

id = prod_id<br />

id = cust_id<br />

asademo.db<br />

sales_order_items<br />

id integer<br />

line_id smallint<br />

prod_id integer<br />

quantity integer<br />

ship_date date<br />

id = id<br />

sales_order<br />

id integer<br />

cust_id integer<br />

order_date date<br />

fin_code_id char(2)<br />

region char(7)<br />

sales_rep integer<br />

code = fin_code_id<br />

fin_code<br />

code char(2)<br />

type char(10)<br />

description char(50)<br />

code = code<br />

fin_data<br />

year char(4)<br />

quarter char(2)<br />

code char(2)<br />

amount numeric(9)<br />

emp_id = sales_rep<br />

employee<br />

emp_id integer<br />

manager_id integer<br />

emp_fname char(20)<br />

emp_lname char(20)<br />

dept_id integer<br />

street char(40)<br />

city char(20)<br />

state char(4)<br />

zip_code char(9)<br />

phone char(10)<br />

status char(1)<br />

ss_number char(11)<br />

salary numeric(20,3)<br />

start_date date<br />

termination_date date<br />

birth_date date<br />

bene_health_ins char(1)<br />

bene_life_ins char(1)<br />

bene_day_care char(1)<br />

sex char(1)<br />

dept_id = dept_id<br />

emp_id = dept_head_id<br />

department<br />

dept_id integer<br />

dept_name char(40)<br />

dept_head_id integer


Wenn Sie mehr wissen und uns Ihre<br />

Anregungen mitteilen möchten<br />

Wir würden gerne Ihre Meinung kennen und sind an Ihren Vorschlägen und<br />

Anregungen zu dieser Dokumentation interessiert.<br />

Sie können uns Ihre Anregungen zu dieser Dokumentation und der Software<br />

übermitteln, indem Sie Newsgroups nutzen, die zur Diskussion über SQL<br />

<strong>Anywhere</strong>-Technologien eingerichtet wurden. Sie finden diese Newsgroups<br />

auf dem Newsserver forums.sybase.com.<br />

Dazu gehören:<br />

♦ sybase.public.sqlanywhere.general.<br />

♦ sybase.public.sqlanywhere.linux.<br />

♦ sybase.public.sqlanywhere.mobilink.<br />

♦ sybase.public.sqlanywhere.product_futures_discussion.<br />

♦ sybase.public.sqlanywhere.replication.<br />

♦ sybase.public.sqlanywhere.ultralite.<br />

Newsgroup-Verpflichtungsausschluss<br />

<strong>Sybase</strong> ist weder verpflichtet, Lösungen, Informationen oder Ideen in<br />

seinen Newsgroups bereitzustellen, noch ist <strong>Sybase</strong> verpflichtet, mehr<br />

bereitzustellen als einen Systemadministrator, der den Service überwacht<br />

und seine Abwicklung sowie die Verfügbarkeit gewährleistet.<br />

Die technischen Mitarbeiter von i<strong>Anywhere</strong> Solutions stehen, ebenso wie<br />

andere Mitarbeiter, <strong>für</strong> den Newsgroup-Service bereit, sofern sie Zeit dazu<br />

haben. Sie stellen ihre Hilfe freiwillig zur Verfügung und sind<br />

möglicherweise nicht regelmäßig verfügbar, um Lösungen und<br />

Informationen bereitzustellen. Ihre Einsatzfähigkeit ist abhängig von ihrer<br />

aktuellen Arbeitsauslastung.<br />

xv


xvi


KAPITEL 1<br />

Überblick über die<br />

Programmierschnittstelle<br />

Über dieses<br />

Kapitel<br />

Inhalt<br />

Dieses Kapitel ist eine Einführung in die einzelnen<br />

Programmierschnittstellen <strong>für</strong> <strong>Adaptive</strong> Server <strong>Anywhere</strong>. Alle Client-<br />

Anwendungen verwenden eine dieser Schnittstellen <strong>für</strong> die Kommunikation<br />

mit der Datenbank.<br />

Thema Seite<br />

Die ODBC-Programmierschnittstelle 2<br />

Die Programmierschnittstelle OLE DB 3<br />

Die Embedded SQL-Programmierschnittstelle 4<br />

Die JDBC-Programmierschnittstelle 5<br />

Die Open Client-Programmierschnittstelle 6<br />

1


Die ODBC-Programmierschnittstelle<br />

Die ODBC-Programmierschnittstelle<br />

2<br />

ODBC (Open Database Connectivity) ist eine Standardschnittstelle auf<br />

Aufrufebene (Call Level Interface, CLI), die von Microsoft entwickelt<br />

wurde. Sie basiert auf der SQL Access Group CLI Spezifikation. ODBC-<br />

Anwendungen können mit jeder Datenquelle ausgeführt werden, die einen<br />

ODBC-Treiber bereitstellt. Sie müssen ODBC verwenden, wenn Ihre<br />

Anwendung auf andere Datenquellen portierbar sein soll, die mit ODBC-<br />

Treibern arbeiten. Auch wenn Sie die Arbeit mit einer API bevorzugen,<br />

sollten Sie ODBC verwenden.<br />

ODBC ist eine Schnittstelle auf niedriger Ebene - etwa auf demselben<br />

Niveau wie Embedded SQL. Fast alle Funktionen von <strong>Adaptive</strong> Server<br />

<strong>Anywhere</strong> sind mit dieser Schnittstelle verfügbar. ODBC ist unter Windows<br />

Betriebssystemen außer Windows CE als DLL verfügbar. Unter UNIX steht<br />

der Treiber als Bibliothek zur Verfügung.<br />

Die wichtigste Dokumentation <strong>für</strong> ODBC ist der Microsoft ODBC Software<br />

Development Kit. Das vorliegende <strong>Handbuch</strong> enthält einige zusätzliche<br />

Hinweise, die sich an Entwickler richten, die ODBC-Anwendungen <strong>für</strong><br />

<strong>Adaptive</strong> Server <strong>Anywhere</strong> bereitstellen.<br />

$ ODBC wird im Abschnitt "ODBC-Programmierung" auf Seite 277<br />

beschrieben.


Kapitel 1 Überblick über die Programmierschnittstelle<br />

Die Programmierschnittstelle OLE DB<br />

OLE DB ist eine Gruppe von Component Object Model-Schnittstellen<br />

(COM), die von Microsoft entwickelt wurden und Anwendungen einen<br />

gleichförmigen Zugriff auf Daten bieten, die in unterschiedlichen<br />

Informationsquellen gespeichert sind, und darüber hinaus die Möglichkeit<br />

bieten, zusätzliche Datenbankdienste zu implementieren. Diese Schnittstellen<br />

unterstützen so viele DBMS-Funktionen, wie sie <strong>für</strong> die gemeinsame<br />

Nutzung des Datenspeichers erforderlich sind.<br />

ADO ist ein Objektmodell, das ermöglicht, über Programme und OLE DB-<br />

Systemschnittstellen auf eine große Anzahl von Datenquellen zuzugreifen,<br />

diese zu ändern und zu aktualisieren. ADO wurde ebenfalls von Microsoft<br />

entwickelt. Die meisten Entwickler, die die OLE DB-<br />

Programmierschnittstelle verwenden, tun dies in dem sie die ADO API<br />

einsetzen und nicht direkt die OLE DB API.<br />

<strong>Adaptive</strong> Server <strong>Anywhere</strong> umfasst einen OLE DB-Provider <strong>für</strong> OLE DBund<br />

ADO-<strong>Programmierer</strong>.<br />

Die primäre Dokumentation <strong>für</strong> das Programmieren mit OLE DB und ADO<br />

ist das Microsoft Developer Network. Das vorliegende <strong>Handbuch</strong> enthält<br />

einige zusätzliche Hinweise, die sich an Entwickler richten, die OLE DBund<br />

ADO-Anwendungen <strong>für</strong> <strong>Adaptive</strong> Server <strong>Anywhere</strong> bereitstellen.<br />

$ Weitere Hinweise finden Sie unter "Die OLE DB- und ADO-<br />

Programmierschnittstellen" auf Seite 371<br />

3


Die Embedded SQL-Programmierschnittstelle<br />

Die Embedded SQL-Programmierschnittstelle<br />

4<br />

Embedded SQL ist ein System, in dem SQL-Befehle direkt in eine C- oder<br />

C++-Quelldatei eingebettet sind. Ein Präprozessor übersetzt diese<br />

Anweisungen in Aufrufe einer Laufzeitbibliothek. Embedded SQL ist ein<br />

ISO/ANSI- und IBM-Standard.<br />

Embedded SQL kann auf andere Datenbanken und andere Umgebungen<br />

portiert werden und ist in allen Betriebsumgebungen funktional äquivalent.<br />

Sie stellt alle im Produkt verfügbaren Funktionen bereit. Die Arbeit mit<br />

Embedded SQL ist einfach und geradlinig, wenn auch eine gewisse<br />

Eingewöhnung erforderlich ist, Embedded SQL Anweisungen (und nicht<br />

Funktionsaufrufe) in einem C-Programmcode zu verwenden.<br />

$ Embedded SQL wird unter "Programmieren mit Embedded SQL" auf<br />

Seite 181 beschrieben.


Kapitel 1 Überblick über die Programmierschnittstelle<br />

Die JDBC-Programmierschnittstelle<br />

JDBC ist eine Schnittstelle auf Aufrufebene <strong>für</strong> Java-Anwendungen. Der<br />

Treiber wurde von Sun Microsystems entwickelt und bietet Java-<br />

<strong>Programmierer</strong>n eine einheitliche Schnittstelle zu einer Vielzahl von<br />

relationalen Datenbanken, sowie eine gemeinsame Basis, auf der Tools und<br />

Schnittstellen auf höherer Ebene aufgebaut werden können. JDBC ist jetzt<br />

ein Standardbestandteil von Java und wurde in den JDK aufgenommen.<br />

SQL <strong>Anywhere</strong> enthält einen einen reinen Java-JDBC-Treiber namens<br />

<strong>Sybase</strong> jConnect an. Dieser enthält außerdem einen JDBC-ODBC-Brücke.<br />

Beide werden im Abschnitt "Datenzugriff über JDBC" auf Seite 143<br />

beschrieben. Hinweise zur Auswahl eines Treibers finden Sie unter "JDBC-<br />

Treiber wählen" auf Seite 145.<br />

Zusätzlich zum Einsatz von JDBC als clientseitige<br />

Anwendungsprogrammierschnittstelle können Sie JDBC innerhalb des<br />

Datenbankservers verwenden, um Java-Daten in der Datenbank abzurufen.<br />

Aus diesem Grund wird JDBC als Teil von Java in der<br />

Datenbankdokumentation dokumentiert.<br />

$ JDBC wird in diesem <strong>Handbuch</strong> nicht beschrieben. Eine Beschreibung<br />

des JDBC-Treibers entnehmen Sie dem Kapitel "Datenzugriff über JDBC"<br />

auf Seite 143.<br />

5


Die Open Client-Programmierschnittstelle<br />

Die Open Client-Programmierschnittstelle<br />

Einsatzbereich des<br />

Open Clients<br />

Die Open Client-Architektur<br />

Client-Library und<br />

DB-Library<br />

6<br />

<strong>Sybase</strong> Open Client bietet Kundenanwendungen, Produkten von<br />

Drittanbietern und anderen <strong>Sybase</strong>-Produkten die erforderlichen<br />

Schnittstellen zur Kommunikation mit dem <strong>Adaptive</strong> Server <strong>Anywhere</strong> und<br />

anderen Open Servern.<br />

Der Einsatz der Open Client-Schnittstelle ist zu überlegen, wenn Ihnen die<br />

Kompatibilität von <strong>Adaptive</strong> Server Enterprise wichtig ist oder wenn Sie<br />

andere <strong>Sybase</strong>-Produkte verwenden, die die Open Client-Schnittstelle<br />

benötigen, zum Beispiel Replication Server.<br />

$ Eine Beschreibung der Open Client-Schnittstelle entnehmen Sie dem<br />

Abschnitt "Die Open Client-Schnittstelle" auf Seite 389.<br />

$ Weitere Hinweise über die Open Client-Schnittstelle finden Sie unter<br />

"<strong>Adaptive</strong> Server <strong>Anywhere</strong> als Open Server" auf Seite 117 der<br />

Dokumentation ASA Datenbankadministration.<br />

Das Konzept "Open Client" kann man sich als System mit zwei<br />

Komponenten vorstellen: Programmierschnittstellen und Netzwerkdiensten.<br />

Open Client bietet zwei Kern-Programmierschnittstellen <strong>für</strong> das Schreiben<br />

von Clientanwendungen: DB-Library und Client-Library.<br />

Die Open Client DB-Library bietet Unterstützung <strong>für</strong> ältere Open Client<br />

Anwendungen und ist eine von der Client-Library vollständig getrennte<br />

Programmierschnittstelle. DB-Bibliothek ist dokumentiert im Open Client<br />

DB-Library/C Reference Manual, das zum Lieferumfang des Produkts<br />

<strong>Sybase</strong> Open Client gehört.<br />

Client-Library-Programme sind auch von der CS-Library abhängig, die<br />

Routinen sowohl <strong>für</strong> den Einsatz in Client-Library- als auch Server-Library-<br />

Anwendungen bereitstellt. Client-Library-Anwendungen können auch<br />

Routinen der Bulk-Library benutzen, um die Hochgeschwindigkeits-<br />

Datenübertragung zu erleichtern.<br />

Die CS-Library und die Bulk-Library sind in <strong>Sybase</strong> Open Client enthalten.<br />

Dieses Produkt kann separat erworben werden.


Netzwerkdienste<br />

Kapitel 1 Überblick über die Programmierschnittstelle<br />

Open Client-Netzwerkdienste enthalten die <strong>Sybase</strong> Net-Library, die die<br />

Unterstützung <strong>für</strong> bestimmte Netzwerkprotokolle wie TCP/IP und DECnet<br />

bereithält. Die Net-Library-Schnittstelle ist <strong>für</strong> Anwendungsprogrammierer<br />

unsichtbar. Auf manchen Plattformen benötigt eine Anwendung unter<br />

Umständen einen anderen Net-Library-Treiber <strong>für</strong> unterschiedliche System-<br />

Netzwerkkonfigurationen. Je nach Ihrer Hostplattform wird der Net-Library-<br />

Treiber entweder durch die Konfiguration der <strong>Sybase</strong>-Produkte des Systems<br />

bestimmt, oder durch die Kompilierung und Verknüpfung Ihrer Programme.<br />

$ Hinweise zur Treiberkonfiguration finden Sie in der Dokumentation<br />

Open Client/Server Configuration Guide.<br />

$ Hinweise zum Aufbau von Client-Library-Programmen finden Sie in<br />

der Dokumentation Open Client/Server Programmer’s Supplement.<br />

7


Die Open Client-Programmierschnittstelle<br />

8


KAPITEL 2<br />

SQL in Anwendungen verwenden<br />

Über dieses<br />

Kapitel<br />

Inhalt<br />

Viele Aspekte der Entwicklung von Datenbankanwendungen hängen vom<br />

Entwicklungstool, von der Datenbank-Schnittstelle und von der<br />

Programmiersprache ab. Einige Probleme und Grundsätze sind jedoch<br />

allgemein gültig und wirken sich auf mehrere Aspekte der Entwicklung von<br />

Datenbankanwendungen aus.<br />

In diesem Kapitel werden einige Grundsätze und Techniken beschrieben, die<br />

<strong>für</strong> die meisten oder alle Schnittstellen gelten. Außerdem enthält das Kapitel<br />

Verweise auf weiterführende Informationen. Das Kapitel ist keine detaillierte<br />

Anweisung <strong>für</strong> die Programmierung mit einer bestimmten Schnittstelle.<br />

Thema Seite<br />

SQL-Anweisungen in Anwendungen ausführen 10<br />

Anweisungen vorbereiten 12<br />

Der Cursor 15<br />

Mit Cursorn arbeiten 20<br />

Cursortypen auswählen 26<br />

<strong>Adaptive</strong> Server <strong>Anywhere</strong>-Cursor 30<br />

Ergebnismengen beschreiben 47<br />

Transaktionen in Anwendungen steuern 49<br />

9


SQL-Anweisungen in Anwendungen ausführen<br />

SQL-Anweisungen in Anwendungen ausführen<br />

10<br />

Wie Sie SQL-Anweisungen in Ihre Anwendung einbauen, hängt vom<br />

Entwicklungstool und der Programmierschnittstelle ab, die Sie verwenden.<br />

♦ ODBC Wenn Sie direkt in die ODBC-Programmierschnittstelle<br />

schreiben, erscheinen Ihre SQL-Anweisungen in Funktionsaufrufen.<br />

Beispiel: Der folgende C-Funktionsaufruf führt eine DELETE-<br />

Anweisung aus:<br />

SQLExecDirect( stmt,<br />

"DELETE FROM employee<br />

WHERE emp_id = 105",<br />

SQL_NTS );<br />

♦ JDBC Wenn Sie die JDBC-Programmierschnittstelle verwenden,<br />

können Sie SQL-Anweisungen ausführen, indem Sie Methoden des<br />

Statement-Objekts aufrufen. Zum Beispiel:<br />

stmt.executeUpdate(<br />

"DELETE FROM employee<br />

WHERE emp_id = 105" );<br />

♦ Embedded SQL Wenn Sie Embedded SQL verwenden, erhalten die<br />

SQL-Anweisungen der C-Sprachen das Schlüsselwort EXEC SQL als<br />

Präfix. Der Code wird dann im Präprozessor verarbeitet, bevor er<br />

kompiliert wird. Zum Beispiel:<br />

EXEC SQL EXECUTE IMMEDIATE<br />

’DELETE FROM employee<br />

WHERE emp_id = 105’;<br />

♦ <strong>Sybase</strong> Open Client Wenn Sie die <strong>Sybase</strong> Open Client- Schnittstelle<br />

verwenden, erscheinen Ihre SQL-Anweisungen in Funktionsaufrufen.<br />

Die folgenden beiden Aufrufe führen zum Beispiel eine DELETE-<br />

Anweisung aus:<br />

ret = ct_command(cmd, CS_LANG_CMD,<br />

"DELETE FROM employee<br />

WHERE emp_id=105"<br />

CS_NULLTERM,<br />

CS_UNUSED);<br />

ret = ct_send(cmd);<br />

♦ Anwendungs-Entwicklungstools Anwendungs-Entwicklungstools wie<br />

die Mitglieder der <strong>Sybase</strong> Enterprise-Familie bieten ihre eigenen SQL-<br />

Objekte, die entweder ODBC (PowerBuilder) oder JDBC (Power J)<br />

verwenden.


Anwendungen im<br />

Server<br />

Kapitel 2 SQL in Anwendungen verwenden<br />

$ Genauere Hinweise zur Aufnahme von SQL-Anweisungen in Ihre<br />

Anwendungen finden Sie in der Dokumentation Ihres Entwicklungstools.<br />

Wenn Sie ODBC oder JDBC verwenden, finden Sie weitere Hinweise im<br />

Software Development Kit <strong>für</strong> diese Schnittstellen.<br />

$ Eine genaue Beschreibung der Programmierung mit Embedded SQL<br />

finden Sie unter "Programmieren mit Embedded SQL" auf Seite 181.<br />

Auf vielerlei Weise funktionieren gespeicherte Prozeduren und Trigger als<br />

Anwendungen oder Teile von Anwendungen, die im Server laufen. Sie<br />

können viele der hier beschriebenen Techniken auch in gespeicherten<br />

Prozeduren verwenden. Gespeicherte Prozeduren benutzen Anweisungen,<br />

die Embedded SQL sehr ähnlich sind.<br />

$ Weitere Hinweise zu gespeicherten Prozeduren und Triggern finden Sie<br />

unter "Prozeduren, Trigger und Anweisungsfolgen verwenden" auf Seite 565<br />

der Dokumentation ASA SQL-Benutzerhandbuch.<br />

Java-Klassen in der Datenbank können die JDBC-Schnittstelle genauso<br />

benutzen wie Java-Anwendungen dies außerhalb des Servers tun. In diesem<br />

Kapitel werden einige Aspekte von JDBC beschrieben. Weitere Hinweise<br />

zur Arbeit mit JDBC finden Sie unter "Datenzugriff über JDBC" auf<br />

Seite 143.<br />

11


Anweisungen vorbereiten<br />

Anweisungen vorbereiten<br />

Die<br />

Wiederverwendung<br />

von vorbereiteten<br />

Anweisungen kann<br />

die Performance<br />

verbessern<br />

12<br />

Jedes Mal, wenn eine Anweisung an eine Datenbank geschickt wird, muss<br />

der Server die Anweisung zunächst vorbereiten. Zur Vorbereitung können<br />

folgende Schritte gehören:<br />

♦ Syntaktische Analyse der Anweisung und Umwandlung in eine interne<br />

Form.<br />

♦ Prüfung der Richtigkeit aller Referenzen auf Datenbankobjekte, z.B.<br />

Prüfung, ob in der Abfrage genannte Spalten existieren.<br />

♦ Optimierer <strong>für</strong> Abfragen veranlassen, einen Zugriffsplan zu erstellen,<br />

falls die Anweisung Joins oder Unterabfragen umfasst.<br />

♦ Ausführung der Anweisung, nachdem alle diese Schritte durchgeführt<br />

wurden.<br />

Wenn Sie dieselbe Anweisung immer wieder verwenden, etwa das Einfügen<br />

von mehreren Zeilen in eine Tabelle, kommt es zu bedeutenden und<br />

unnötigen Overheads durch die wiederholte Vorbereitung der Anweisung.<br />

Um dies zu vermeiden, bieten einige Datenbank-Programmierschnittstellen<br />

eine Möglichkeit zur Verwendung von vorbereiteten Anweisungen. Eine<br />

vorbereitete Anweisung ist eine Anweisung, die eine Reihe von<br />

Platzhaltern enthält. Wenn Sie die Anweisung ausführen wollen, müssen Sie<br />

den Platzhaltern nur Werte zuweisen, anstatt die gesamte Anweisung erneut<br />

vorzubereiten.<br />

Der Einsatz von vorbereiteten Anweisungen ist besonders dann nützlich,<br />

wenn viele ähnliche Aktionen ausgeführt werden, wie etwa das Einfügen von<br />

vielen Zeilen.<br />

Im Allgemeinen erfordern vorbereitete Anweisungen die folgenden Schritte:<br />

1 Anweisung vorbereiten In diesem Schritt versehen Sie die Anweisung<br />

im Allgemeinen mit einigen Platzhalter-Zeichen anstelle von Werten.<br />

2 Wiederholtes Ausführen der vorbereiteten Anweisung In diesem<br />

Schritt liefern Sie Werte, die jedes Mal benutzt werden sollen, wenn die<br />

Anweisung ausgeführt wird. Die Anweisung braucht nicht jedes Mal<br />

vorbereitet zu werden.<br />

3 Anweisung löschen In diesem Schritt geben Sie die Ressourcen frei,<br />

die <strong>für</strong> die vorbereitete Anweisung in Beschlag genommen wurden.<br />

Einige Programmierschnittstellen verarbeiten diesen Schritt automatisch.


Bereiten Sie keine<br />

Anweisungen vor,<br />

die nur einmal<br />

verwendet werden.<br />

Kapitel 2 SQL in Anwendungen verwenden<br />

Im Allgemeinen sollten Sie Anweisungen nicht vorbereiten, wenn sie nur<br />

einmal ausgeführt werden sollen. Bei getrennter Vorbereitung und<br />

Durchführung kommt es zu leichten Einbußen bei der Performance, und<br />

außerdem werden dadurch unnötig komplizierte Schritte in die Anwendung<br />

eingefügt.<br />

Bei manchen Schnittstellen müssen Sie allerdings eine Anweisung<br />

vorbereiten, um sie mit einem Cursor zu verbinden.<br />

$ Hinweise zu Cursorn finden Sie unter "Der Cursor" auf Seite 15.<br />

Die Aufrufe <strong>für</strong> die Vorbereitung und Ausführung von Anweisungen sind<br />

nicht Teil der SQL und unterscheiden sich daher je nach verwendeter<br />

Schnittstelle. Jede Programmierschnittstelle des <strong>Adaptive</strong> Server <strong>Anywhere</strong><br />

bietet eine Methode <strong>für</strong> die Verwendung von vorbereiteten Anweisungen.<br />

So verwenden Sie vorbereitete Anweisungen<br />

In diesem Abschnitt wird ein kurzer Überblick über die Verwendung von<br />

vorbereiteten Anweisungen gegeben. Die allgemeine Vorgehensweise ist<br />

identisch, aber die Details unterscheiden sich je nach Schnittstelle. Ein<br />

Vergleich der Verwendung von vorbereiteten Anweisungen in den einzelnen<br />

Schnittstellen kann diesen Punkt vielleicht klarer darstellen.<br />

v So verwenden Sie eine vorbereitete Anweisung (generisch):<br />

1 Bereiten Sie die Anweisung vor.<br />

2 Setzen Sie Bindungsparameter, die benutzt werden, um Werte in der<br />

Anweisung zu halten.<br />

3 Weisen Sie den Bindungsparametern in der Anweisung Werte zu.<br />

4 Führen Sie die Anweisung aus.<br />

5 Wiederholen Sie nötigenfalls Schritte 3 und 4.<br />

6 Löschen Sie die Anweisung, wenn Sie fertig sind. Dieser Schritt ist in<br />

JDBC nicht erforderlich, da der Abfalldatenmechanismus von JDBC<br />

dies erledigt.<br />

v So verwenden Sie eine vorbereitete Anweisung (Embedded SQL):<br />

1 Bereiten Sie die Anweisung mit dem Befehl EXEC SQL PREPARE vor.<br />

2 Weisen Sie den Parametern in der Anweisung Werte zu.<br />

3 Führen Sie die Anweisung mit dem Befehl EXE SQL EXECUTE aus.<br />

13


Anweisungen vorbereiten<br />

14<br />

4 Geben Sie die mit der Anweisung verbundenen Ressourcen frei, indem<br />

Sie den Befehl EXEC SQL DROP benutzen.<br />

v So verwenden Sie eine vorbereitete Anweisung (ODBC):<br />

1 Bereiten Sie die Anweisung mit SQLPrepare vor.<br />

2 Binden Sie die Anweisungsparameter mit SQLBindParameter.<br />

3 Führen Sie die Anweisung mit SQLExecute aus.<br />

4 Löschen Sie die Anweisung mit SQLFreeStmt.<br />

$ Weitere Hinweise finden Sie unter "Vorbereitete Anweisungen<br />

ausführen" auf Seite 297 und in der Dokumentation zum ODBC SDK.<br />

v So verwenden Sie eine vorbereitete Anweisung (JDBC):<br />

1 Bereiten Sie die Anweisung mit der Methode prepareStatement des<br />

Verbindungsobjekts vor. Daraus wird ein PreparedStatement-Objekt<br />

erzeugt.<br />

2 Setzen Sie die Anweisungsparameter mit den entsprechenden setType-<br />

Methoden des PreparedStatement-Objekts. Hier ist Type der Datentyp,<br />

der zugewiesen wird.<br />

3 Führen Sie die Anweisung mit der geeigneten Methode <strong>für</strong> das<br />

PreparedStatement-Objekt aus. Für Einfügungen, Aktualisierungen und<br />

Löschungen ist dies die Methode executeUpdate.<br />

$ Weitere Hinweise zur Verwendung von vorbereiteten<br />

Anweisungen in JDBC finden Sie unter "Vorbereitete Anweisungen <strong>für</strong><br />

effizienteren Zugriff verwenden" auf Seite 171.<br />

v So verwenden Sie eine vorbereitete Anweisung (Open Client):<br />

1 Bereiten Sie die Anweisung mit der Funktion ct_dynamic mit<br />

CS_PREPARE als type-Parameter vor.<br />

2 Setzen Sie die Anweisungsparameter ct_param.<br />

3 Führen Sie die Anweisung mit ct_dynamic mit CS_EXECUTE als<br />

Typparameter aus.<br />

4 Geben Sie die mit der Anweisung verbundenen Ressourcen frei, indem<br />

Sie ct_dynamic mit einem CS_DEALLOC-Typparameter verwenden.<br />

Weitere Hinweise über die Verwendung von vorbereiteten Anweisungen<br />

in Open Client finden Sie unter "SQL in Open Client-Anwendungen<br />

verwenden" auf Seite 394.


Der Cursor<br />

Was sind Cursor?<br />

Cursorpositionen<br />

Kapitel 2 SQL in Anwendungen verwenden<br />

Wenn Sie eine Abfrage in einer Anwendung ausführen, besteht die<br />

Ergebnismenge aus einer Reihe von Zeilen. Im Allgemeinen wissen Sie<br />

nicht, wie viele Zeilen die Anwendung empfangen wird, bevor die Abfrage<br />

ausgeführt worden ist. Mit einem Cursor können Sie Ergebnismengen von<br />

Abfragen in Anwendungen verarbeiten.<br />

Wie Sie Cursor einsetzen, und welche Cursorarten verfügbar sind, hängt von<br />

der Programmierschnittstelle ab, die Sie benutzen. JDBC 1.0 bietet nur eine<br />

Basisverarbeitung von Ergebnismengen, während ODBC und Embedded<br />

SQL über viele unterschiedliche Cursorarten verfügen. Mit einem Cursor in<br />

Open Client kann man sich in einer Ergebnismenge nur vorwärts bewegen.<br />

Sie können mit einem Cursor folgende Aufgaben innerhalb einer<br />

Programmierschnittstelle durchführen:<br />

♦ Die Ergebnisse einer Abfrage mittels Schleifen bearbeiten.<br />

♦ Einfügungen, Aktualisierungen und Löschungen auf den<br />

darunterliegenden Daten an einem beliebigen Punkt in einer<br />

Ergebnismenge durchführen<br />

Zusätzlich ermöglichen Ihnen einige Programmierschnittstellen die<br />

Verwendung von Sonderfunktionen, um die Art zu optimieren, wie<br />

Ergebnismengen an Ihre Anwendung zurückgegeben werden, was<br />

beträchtliche Performance-Vorteile <strong>für</strong> Ihre Anwendung bietet.<br />

$ Weitere Hinweise zur den verfügbaren Cursorarten in den einzelnen<br />

Programmierschnittstellen finden Sie unter "Cursorverfügbarkeit" auf<br />

Seite 26.<br />

Ein Cursor ist ein Name, der einer Ergebnismenge zugeordnet ist. Die<br />

Ergebnismenge erhalten Sie durch eine SELECT-Anweisung oder den<br />

Aufruf einer gespeicherten Prozedur.<br />

Ein Cursor ist ein Handle auf der Ergebnismenge. Zu jedem Zeitpunkt hat<br />

der Cursor eine genau definierte Position innerhalb der Ergebnismenge. Mit<br />

einem Cursor können Sie die Daten zeilenweise untersuchen und<br />

gegebenenfalls bearbeiten. In <strong>Adaptive</strong> Server <strong>Anywhere</strong> unterstützen<br />

Cursor Vorwärts- und Rückwärts-Bewegungen durch die Abfrageergebnisse.<br />

Cursor können an den folgenden Stellen positioniert werden:<br />

♦ Vor der ersten Zeile der Ergebnismenge.<br />

15


Der Cursor<br />

Vorteile der Cursorbenutzung<br />

16<br />

♦ Auf einer Zeile in der Ergebnismenge.<br />

♦ Nach der letzten Zeile der Ergebnismenge.<br />

Cursorposition und Ergebnismenge werden im Datenbankserver<br />

aufrechterhalten. Zeilen werden vom Client zur Anzeige oder Verarbeitung<br />

einzeln oder in Gruppen abgerufen. Dem Client muss nicht die gesamte<br />

Ergebnismenge übermittelt werden.<br />

Sie müssen nicht unbedingt Cursor in Datenbankanwendungen verwenden,<br />

aber ihr Einsatz bietet eine Reihe von Vorteilen. Diese Vorteile beruhen<br />

darauf, dass die gesamte Ergebnismenge an den Client zur Ansicht und<br />

Verarbeitung übermittelt werden muss, wenn Sie keine Cursor verwenden:<br />

♦ Clientseitiger Speicher Bei umfangreichen Ergebnismengen kann das<br />

Halten der gesamten Ergebnismenge auf dem Client zu zusätzlichem<br />

Speicherbedarf führen.


Schritte der Cursorbenutzung<br />

Kapitel 2 SQL in Anwendungen verwenden<br />

♦ Antwortzeit Cursor können die ersten Zeilen liefern, bevor die gesamte<br />

Ergebnismenge zusammengestellt wird. Wenn Sie keine Cursor<br />

verwenden, muss die gesamte Ergebnismenge übermittelt werden, bevor<br />

eine Zeile von Ihrer Anwendung angezeigt werden kann.<br />

♦ Parallelitätskontrolle Wenn Sie Ihre Daten aktualisieren und keine<br />

Cursor in Ihrer Anwendung verwenden, müssen Sie separate SQL-<br />

Anweisungen an den Datenbankserver senden, um die Änderungen<br />

anzuwenden. Dadurch können Probleme mit der Parallelität entstehen,<br />

falls sich die Ergebnismenge seit der Abfrage durch den Client geändert<br />

hat. Das wiederum kann möglicherweise zu Aktualisierungsverlusten<br />

führen.<br />

Corsor sind wie Zeiger auf die darunter liegenden Daten und geben<br />

dadurch entsprechende Parallelitätsbeschränkungen <strong>für</strong> die<br />

durchgeführten Änderungen vor.<br />

Die Verwendung eines Cursors in Embedded SQL unterscheidet sich von der<br />

Verwendung eines Cursors in anderen Schnittstellen.<br />

v So verwenden Sie einen Cursor (Embedded SQL):<br />

1 Bereiten Sie eine Anweisung vor.<br />

Cursor verwenden üblicherweise einen Anweisungs-Handle statt einer<br />

Zeichenfolge. Sie müssen eine Anweisung vorbereiten, damit ein Handle<br />

verfügbar ist.<br />

$ Hinweise über das Vorbereiten einer Anweisung finden Sie unter<br />

"Anweisungen vorbereiten" auf Seite 12.<br />

2 Deklarieren Sie den Cursor.<br />

Jeder Cursor bezieht sich auf eine einzelne SELECT- oder CALL-<br />

Anweisung. Wenn Sie einen Cursor deklarieren, geben Sie den Namen<br />

des Cursors und die Anweisung an, auf die er sich bezieht.<br />

$ Weitere Hinweise finden Sie unter "DECLARE CURSOR-<br />

Anweisung [ESQL] [GP]" auf Seite 412 der Dokumentation ASA SQL-<br />

Referenzhandbuch.<br />

3 Öffnen Sie den Cursor.<br />

$ Weitere Hinweise finden Sie unter "OPEN-Anweisung [ESQL]<br />

[GP]" auf Seite 523 der Dokumentation ASA SQL-Referenzhandbuch.<br />

17


Der Cursor<br />

18<br />

Bei der CALL-Anweisung wird durch das Öffnen des Cursors die<br />

Abfrage bis zu dem Punkt ausgeführt, an dem die erste Zeile bezogen<br />

werden kann.<br />

4 Rufen Sie die Ergebnisse ab.<br />

Obwohl eine einfache Abruf-Operation den Cursor in die nächste Zeile<br />

der Ergebnismenge bewegt, ermöglicht <strong>Adaptive</strong> Server <strong>Anywhere</strong> auch<br />

kompliziertere Bewegungen in der Ergebnismenge. Die verfügbaren<br />

Abruf-Operationen hängen davon ab, wie Sie den Cursor deklarieren.<br />

$ Weitere Hinweise finden Sie unter "FETCH-Anweisung [ESQL]<br />

[GP]" auf Seite 458 der Dokumentation ASA SQL-Referenzhandbuch<br />

und "Daten abrufen" auf Seite 214.<br />

5 Schließen Sie den Cursor<br />

Wenn Sie die Arbeit mit dem Cursor abgeschlossen haben, schließen Sie<br />

ihn. Das löst etwaige Sperren auf den darunterliegenden Daten.<br />

$ Weitere Hinweise finden Sie unter "CLOSE-Anweisung [ESQL]<br />

[GP]" auf Seite 285 der Dokumentation ASA SQL-Referenzhandbuch.<br />

6 Löschen Sie die Anweisung.<br />

Um den Speicher freizugeben, der mit dem Cursor und der ihm<br />

zugeordneten Anweisung verbunden war, müssen Sie die Anweisung<br />

freigeben.<br />

$ Weitere Informationen finden Sie unter "DROP STATEMENT-<br />

Anweisung [ESQL]" auf Seite 439 der Dokumentation ASA SQL-<br />

Referenzhandbuch.<br />

v So verwenden Sie einen Cursor (ODBC, JDBC, Open Client):<br />

1 Bereiten Sie eine Anweisung vor und führen Sie sie aus:<br />

Führen Sie eine Anweisung mit der normalen Methode <strong>für</strong> die<br />

Schnittstelle aus. Sie können die Anweisung vorbereiten und dann<br />

ausführen, oder die Anweisung direkt ausführen.<br />

2 Überprüfen Sie, ob die Anweisung eine Ergebnismenge zurückgibt.<br />

Ein Cursor wird implizit geöffnet, wenn eine Anweisung ausgeführt<br />

wird, die eine Ergebnismenge erstellt. Beim Öffnen eines Cursors wird<br />

er vor die erste Zeile der Ergebnismenge gesetzt.<br />

3 Rufen Sie die Ergebnisse ab.<br />

Obwohl eine einfache Abruf-Operation den Cursor in die nächste Zeile<br />

der Ergebnismenge bewegt, ermöglicht <strong>Adaptive</strong> Server <strong>Anywhere</strong> auch<br />

kompliziertere Bewegungen in der Ergebnismenge.


Prefetch von Zeilen<br />

Kapitel 2 SQL in Anwendungen verwenden<br />

4 Schließen Sie den Cursor<br />

Wenn Sie die Arbeit mit dem Cursor abgeschlossen haben, schließen Sie<br />

ihn, damit die ihm zugewiesenen Ressourcen freigegeben werden.<br />

5 Geben Sie die Anweisung frei.<br />

Wenn Sie eine vorbereitete Anweisung verwendet haben, geben Sie sie<br />

frei, um den benutzten Speicher wieder verfügbar zu machen.<br />

In manchen Fällen kann die Interface-Bibliothek Performance-<br />

Optimierungen im Hintergrund durchführen (z.B. Prefetch von Ergebnissen),<br />

sodass diese Schritte in der Clientanwendung möglicherweise nicht den<br />

Vorgängen in der Software entsprechen.<br />

19


Mit Cursorn arbeiten<br />

Mit Cursorn arbeiten<br />

Cursor positionieren<br />

20<br />

In diesem Abschnitt wird beschrieben, wie bestimmte Cursorvorgänge<br />

ausgeführt werden.<br />

Wird ein Cursor geöffnet, ist er vor der ersten Zeile positioniert. Sie können<br />

den Cursor an eine absolute Position in Verhältnis zum Anfang oder zum<br />

Ende der Abfrageergebnisse positionieren oder ihn relativ zur aktuellen<br />

Cursor-Position verschieben. Wie Sie im Einzelnen den Cursor verschieben<br />

und welche Operationen möglich sind, hängt von der<br />

Programmierschnittstelle ab.<br />

Die Anzahl der Zeilenpositionen, die Sie mit einem Fetch-Vorgang abrufen<br />

können, wird durch die Größe einer Ganzzahl bestimmt. Mit einem Fetch-<br />

Vorgang können Sie Zeilen bis zu Nummer 2147483646 abrufen, wobei es<br />

sich um die größtmögliche Ganzzahl minus 1 handelt. Wenn Sie negative<br />

Werte verwenden (Zeilen in Bezug auf das Ende), können Sie Fetch-<br />

Vorgänge nach unten bis zum kleinsten negativen Wert, der in einer<br />

Ganzzahl möglich ist, plus 1 ausführen.<br />

Sie können spezielle positionsbasierte Aktualisierungs- oder<br />

Löschungsoperationen verwenden, um die Zeile an der aktuellen<br />

Cursorposition zu aktualisieren oder zu löschen. Ist der Cursor vor der ersten<br />

Zeile oder nach der letzten Zeile positioniert, wird der Fehler No current row<br />

of cursor zurückgeben.


Cursor beim Öffnen konfigurieren<br />

Kapitel 2 SQL in Anwendungen verwenden<br />

Probleme mit der Cursorpositionierung<br />

Einfügungen und manche Aktualisierungsvorgänge mit nichtempfindlichen<br />

Cursorn können Probleme mit der Positionierung von<br />

Cursorn verursachen. <strong>Adaptive</strong> Server <strong>Anywhere</strong> platziert eingefügte<br />

Zeilen an unvorhersehbaren Positionen innerhalb eines Cursors, falls die<br />

SELECT-Anweisung keine ORDER BY-Klausel hat. In einigen Fällen<br />

erscheint die eingefügte Zeile überhaupt nicht, bis der Cursor geschlossen<br />

und wieder geöffnet wurde.<br />

Bei <strong>Adaptive</strong> Server <strong>Anywhere</strong> passiert dies, wenn eine Arbeitstabelle<br />

erstellt werden musste, um den Cursor zu öffnen (unter "Arbeitstabellen in<br />

der Abfrageverarbeitung verwenden" auf Seite 178 der Dokumentation<br />

ASA SQL-Benutzerhandbuch finden Sie eine diesbezügliche<br />

Beschreibung).<br />

Die UPDATE-Anweisung kann bewirken, dass sich eine Zeile im Cursor<br />

verschiebt. Das passiert, wenn der Cursor eine ORDER BY-Klausel hat,<br />

die einen vorhandenen Index benutzt (es wird keine Arbeitstabelle<br />

erstellt). Mit der Verwendung eines statisch abrollenden Cursors werden<br />

diese Probleme vermieden, allerdings ist mehr Speicher und<br />

Verarbeitungsaufwand erforderlich.<br />

Sie können die folgenden Aspekte des Cursorverhaltens konfigurieren, wenn<br />

Sie einen Cursor öffnen:<br />

♦ Isolationsstufe Sie können die Isolationsstufen der Vorgänge <strong>für</strong> einen<br />

Cursor explizit so setzen, dass sie von der aktuellen Isolationsstufe der<br />

Transaktion verschieden sind. Dazu stellen Sie die<br />

ISOLATION_LEVEL-Option ein.<br />

$ Weitere Informationen finden Sie unter "ISOLATION_LEVEL-<br />

Option" auf Seite 637 der Dokumentation ASA<br />

Datenbankadministration.<br />

♦ Offen halten Standardmäßig werden Cursor in Embedded SQL am Ende<br />

einer Transaktion geschlossen. Wenn Sie einen Cursor mit der WITH<br />

HOLD-Option öffnen, können Sie ihn offen halten, bis die Verbindung<br />

beendet wird oder bis Sie ihn explizit schließen. ODBC, JDBC und<br />

Open Client lassen Cursor beim Ende von Transaktionen standardmäßig<br />

geöffnet.<br />

21


Mit Cursorn arbeiten<br />

Zeilen durch einen Cursor abrufen<br />

Mehrere Zeilen abrufen<br />

22<br />

Die einfachste Art, eine Ergebnismenge aus einer Abfrage mit einem Cursor<br />

zu verarbeiten, ist eine Schleife zum Absuchen aller Zeilen in der<br />

Ergebnismenge, bis keine Zeilen mehr vorhanden sind.<br />

v So führen Sie einen Schleifendurchlauf auf Zeilen einer<br />

Ergebnismenge durch:<br />

1 Deklarieren und öffnen Sie den Cursor (Embedded SQL), oder führen<br />

Sie eine Anweisung aus, die eine Ergebnismenge zurückgibt (ODBC,<br />

JDBC, Open Client).<br />

2 Setzen Sie die Fetch-Vorgänge <strong>für</strong> die nächste Zeile fort, bis der Fehler<br />

Zeile nicht gefunden (Row Not Found) erscheint.<br />

3 Schließen Sie den Cursor<br />

Die Ausführung des zweiten Schrittes hängt davon ab, welche Schnittstelle<br />

Sie verwenden. Zum Beispiel:<br />

♦ ODBC SQLFetch, SQLExtendedFetch oder SQLFetchScroll<br />

verschieben den Cursor in die nächste Zeile und geben die Daten zurück.<br />

$ Weitere Hinweise zur Verwendung eines Cursors in ODBC finden<br />

Sie unter "Mit Ergebnismengen arbeiten" auf Seite 299.<br />

♦ Embedded SQL Die FETCH-Anweisung führt dieselbe Operation aus.<br />

$ Weitere Hinweise über die Verwendung von Cursorn in Embedded<br />

SQL finden Sie unter "Cursor in Embedded SQL verwenden" auf<br />

Seite 215.<br />

♦ JDBC Die next-Methode des ResultSet-Objekts bewegt den Cursor<br />

weiter und gibt die Daten zurück.<br />

$ Weitere Hinweise zur Verwendung des ResultSet-Objekts in<br />

JDBC finden Sie unter "Abfragen mit JDBC" auf Seite 169.<br />

♦ Open Client Die ct_fetch-Funktion verschiebt den Cursor in die nächste<br />

Zeile und gibt die Daten zurück.<br />

$ Weitere Hinweise zur Verwendung eines Cursors in Open Client-<br />

Anwendungen finden Sie unter "Cursor verwenden" auf Seite 395.<br />

In diesem Abschnitt wird besprochen, wie Sie mehrere Zeilen mit einem<br />

Fetch-Vorgang abrufen können.


Mehrzeilen-Fetch-<br />

Vorgänge<br />

Mehrzeilen-Fetch-<br />

Vorgänge<br />

verwenden<br />

Fetch mit abrollendem Cursor<br />

Kapitel 2 SQL in Anwendungen verwenden<br />

Der mehrzeilige Abruf darf nicht mit dem Vorab-Abrufen von Zeilen<br />

verwechselt werden, was im nächsten Abschnitt beschrieben wird.<br />

Mehrzeilen-Abrufe werden von der Anwendung durchgeführt, während ein<br />

Vorab-Abrufen <strong>für</strong> die Anwendung nicht erkennbar ist und eine ähnliche<br />

Performance-Steigerung bietet.<br />

Einige Schnittstellen bieten Methoden zum gleichzeitigen Abrufen mehrerer<br />

Zeilen in die nächsten Felder eines Rasters. Im Allgemeinen gilt: Je weniger<br />

getrennte Fetch-Vorgänge Sie ausführen, desto weniger einzelne<br />

Anforderungen muss der Server bewältigen, und desto besser wird die<br />

Performance. Eine modifizierte FETCH-Anweisung, die mehrere Zeilen<br />

abruft, wird auch ein weiter Abruf genannt. Ein Cursor, der Mehrzeilen-<br />

Abrufe ausführt, wird manchmal auch als Block-Cursor (Blockcursor) oder<br />

fat cursor (Fetter Cursor) bezeichnet.<br />

♦ In ODBC können Sie die Anzahl der Zeilen einstellen, die bei jedem<br />

Aufruf von SQLFetchScroll oder SQLExtendedFetch zurückgegeben<br />

werden, indem Sie das Attribut SQL_ROWSET_SIZE setzen.<br />

♦ In Embedded SQL verwendet die FETCH-Anweisung eine ARRAY-<br />

Klausel, um die Anzahl der Zeilen zu steuern, die durch einen Fetch-<br />

Vorgang gleichzeitig abgerufen werden.<br />

♦ Open Client und JDBC unterstützen mehrzeilige Fetch-Vorgänge nicht.<br />

Sie verwenden Prefetch-Vorgänge.<br />

ODBC und Embedded SQL bieten Methoden <strong>für</strong> den Einsatz abrollender<br />

beziehungsweise dynamisch abrollender Cursortypen. Diese Methoden<br />

ermöglichen das gleichzeitige Vorwärtsbewegen oder Rückwärtsbewegen<br />

über mehrere Zeilen in einer Ergebnismenge.<br />

Die JDBC- und Open Client-Schnittstellen unterstützen keine abrollenden<br />

Cursor.<br />

Prefetch-Vorgänge sind auf Vorgänge mit einem abrollenden Cursor nicht<br />

anwendbar. Zum Beispiel werden beim Abrufen einer Zeile in<br />

entgegengesetzter Richtung nicht mehrere vorherige Zeilen abgerufen.<br />

23


Mit Cursorn arbeiten<br />

Zeilen mit einen Cursor ändern<br />

Aus welcher<br />

Tabelle werden<br />

Zeilen gelöscht?<br />

24<br />

Cursor können mehr als nur Ergebnisse aus einer Abfrage lesen. Sie können<br />

auch Daten in der Datenbank verändern, während Sie einen Cursor<br />

verarbeiten. Diese Vorgänge werden im Allgemeinen als positionsbasierte<br />

oder positionierte Aktualisierungs- und Löschvorgänge oder PUT-Vorgänge<br />

(wenn es sich um ein INSERT handelt) bezeichnet.<br />

Nicht alle Abfrage-Ergebnismengen ermöglichen positionsbasiertes<br />

Aktualisieren oder Löschen. Wenn Sie eine Abfrage in einer nicht<br />

aktualisierbaren Ansicht ausführen, werden in den Basistabellen keine<br />

Änderungen durchgeführt. Auch wenn die Abfrage einen Join enthält,<br />

müssen Sie angeben, aus welcher Tabelle Sie löschen wollen oder welche<br />

Spalten Sie aktualisieren wollen, wenn Sie die Vorgänge ausführen.<br />

Einfügungen durch einen Cursor können nur durchgeführt werden, wenn<br />

nicht eingefügte Spalten in der Tabelle NULLWERTE zulassen oder<br />

Standardwerte haben.<br />

ODBC, Embedded SQL und Open Client ermöglichen die Datenänderung<br />

mit einem Cursor, JDBC 1.1 hingegen nicht. Mit dem Open Client können<br />

Sie Zeilen löschen und aktualisieren, aber Zeilen nur in einer Ein-<br />

Tabellenabfrage einfügen.<br />

Wenn Sie ein positionsbasiertes Löschen durch einen Cursor versuchen, wird<br />

die Tabelle, aus der Zeilen gelöscht werden, wie folgt festgelegt:<br />

1 Wenn keine FROM-Klausel in der DELETE-Anweisung eingeschlossen<br />

ist, muss der Cursor nur <strong>für</strong> eine Tabelle gesetzt sein.<br />

2 Wenn der Cursor <strong>für</strong> eine Join-Abfrage (einschließlich zum Benutzen<br />

einer Ansicht mit enthaltenem Join) gesetzt ist, muss die FROM-Klausel<br />

verwendet werden. Nur die aktuelle Zeile der angegebenen Tabelle wird<br />

gelöscht. Die anderen Tabellen des Joins sind nicht betroffen.<br />

3 Wenn eine FROM-Klausel enthalten ist und kein Tabelleneigentümer<br />

angegeben wurde, ist der Tabellenangabewert der erste, der zu den<br />

Korrelationsnamen passt.<br />

$ Weitere Hinweise finden Sie unter "FROM-Klausel" auf Seite 467<br />

der Dokumentation ASA SQL-Referenzhandbuch.<br />

4 Wenn ein Korrelationsname existiert, ist der Tabellenangabename mit<br />

dem Korrelationsnamen identifiziert.<br />

5 Wenn ein Korrelationsname nicht vorhanden ist, muss der<br />

Tabellenangabewert eindeutig als Tabellenname im Cursor<br />

identifizierbar sein.


Cursorvorgänge abbrechen<br />

Kapitel 2 SQL in Anwendungen verwenden<br />

6 Wenn eine FROM-Klausel enthalten ist und ein Tabelleneigentümer<br />

angegeben wurde, muss der Tabellenangabewert als Tabellenname im<br />

Cursor eindeutig identifizierbar sein.<br />

7 Die positionsbasierte DELETE-Anweisung kann <strong>für</strong> einen Cursor<br />

verwendet werden, der auf eine Ansicht geöffnet ist, solange die Ansicht<br />

aktualisierbar ist.<br />

Sie können eine Anforderung durch eine Schnittstellenfunktion abbrechen. In<br />

Interactive SQL können Sie eine Anforderung durch Klicken auf die<br />

Schaltfläche "SQL-Anweisung unterbrechen" in der Symbolleiste abbrechen<br />

(oder durch den Befehl "Stop" im SQL-Menü).<br />

Wenn Sie eine Anforderung abbrechen, die eine Cursoroperation durchführt,<br />

ist die Position des Cursors unbestimmt. Nach dem Abbrechen der<br />

Anforderung müssen Sie die absolute Position des Cursors ermitteln oder ihn<br />

schließen.<br />

25


Cursortypen auswählen<br />

Cursortypen auswählen<br />

Cursorverfügbarkeit<br />

Cursoreigenschaften<br />

26<br />

Dieser Abschnitt beschreibt Zuordnungen zwischen <strong>Adaptive</strong> Server<br />

<strong>Anywhere</strong>-Cursorn und den Optionen, die Ihnen die<br />

Programmierschnittstellen bieten, die von <strong>Adaptive</strong> Server <strong>Anywhere</strong><br />

unterstützt werden.<br />

$ Hinweise zu <strong>Adaptive</strong> Server <strong>Anywhere</strong>-Cursorn finden Sie unter<br />

"<strong>Adaptive</strong> Server <strong>Anywhere</strong>-Cursor" auf Seite 30.<br />

Nicht alle Schnittstellen bieten Unterstützung <strong>für</strong> alle Cursortypen.<br />

♦ ODBC und OLE DB (ADO) unterstützen alle Cursortypen.<br />

$ Weitere Hinweise finden Sie unter "Mit Ergebnismengen arbeiten"<br />

auf Seite 299.<br />

♦ Embedded SQL unterstützt alle Cursortypen.<br />

♦ Für JDBC:<br />

♦ jConnect 4.x stellt nur asensitive (nicht empfindliche) Cursor zur<br />

Verfügung.<br />

♦ jConnect 5.x unterstützt alle Cursortypen, bei abrollbaren Cursorn<br />

kommt es jedoch zu erheblichen Performance-Einbußen.<br />

♦ Die JDBC-ODBC-Brücke unterstützt alle Cursortypen.<br />

♦ <strong>Sybase</strong> Open Client unterstützt lediglich asensitive (nicht empfindliche)<br />

Cursor. Außerdem kommt es zu erheblichen Performance-Einbußen,<br />

wenn aktualisierbare, nicht eindeutige Cursor benutzt werden.<br />

Sie fordern einen Cursortyp entweder explizit oder implizit von der<br />

Programmierschnittstelle an. Unterschiedliche Schnittstellenbibliotheken<br />

bieten eine unterschiedliche Auswahl von Cursortypen an. JDBC und<br />

ODBC schreiben zum Beispiel unterschiedliche Cursortypen vor.<br />

Jeder Cursortyp wird duch eine Reihe von Eigenschaften definiert:


Kapitel 2 SQL in Anwendungen verwenden<br />

♦ Eindeutigkeit Wenn ein Cursor als eindeutig deklariert wird, zwingt<br />

dies die Abfrage, alle Spalten zurückzugeben, die <strong>für</strong> die eindeutige<br />

Identifizierung der einzelnen Zeilen erforderlich sind. Oft bedeutet dies,<br />

dass alle Spalten im Primärschlüssel zurückgegeben werden. Alle<br />

erforderlichen, aber nicht angegebenen Spalten werden der<br />

Ergebnismenge hinzugefügt. Der Standardcursortyp ist "Nicht<br />

eindeutig".<br />

♦ Aktualisierbarkeit Ein als schreibgeschützt deklarierter Corsor kann<br />

nicht <strong>für</strong> eine positionierte Aktualisierung oder Löschung verwendet<br />

werden. Der Standardcursortyp ist "Aktualisierbar".<br />

♦ Abrollfähigkeit Sie können Cursor so deklarieren, dass Sie sich<br />

unterschiedlich verhalten, wenn Sie sich durch die Ergebnismenge<br />

bewegen. Manche Cursor können nur die aktuelle oder die nächste Zeile<br />

abrufen. Andere können sich vorwärts und rückwärts in der<br />

Ergebnismenge bewegen.<br />

♦ Empfindlichkeit Änderungen an der Datenbank können durch einen<br />

Cursor sichtbar sein, müssen es aber nicht.<br />

Diese Eigenschaften haben möglicherweise signifikante Auswirkungen auf<br />

Performance und Datenbankserver-Speicherzuordnung.<br />

<strong>Adaptive</strong> Server <strong>Anywhere</strong> stellt Ihnen Cursor mit unterschiedlichen<br />

Zusammensetzungen dieser Eigenschaften zur Verfügung. Wenn Sie einen<br />

Corsor eines gegebenen Typs anfordern, versucht <strong>Adaptive</strong> Server<br />

<strong>Anywhere</strong>, diese Eigenschaften so gut wie möglich zuzuordnen. Wie<br />

<strong>Adaptive</strong> Server <strong>Anywhere</strong>-Cursor den in den Programmierschnittstellen<br />

festgelegten Cursorn im Einzelnen entsprechen, ist das Thema der folgenden<br />

Abschnitte.<br />

Unter Umständen ist es nicht möglich, allen Eigenschaften zu entsprechen.<br />

Unempfindliche Cursor in <strong>Adaptive</strong> Server <strong>Anywhere</strong> zum Beispiel müssen<br />

schreibgeschützt sein, aus den weiter unten angeführten Gründen. Wenn Ihre<br />

Anwendung einen aktualisierbaren unempfindlichen Cursor anfordert, wird<br />

statt dessen ein anderer Cursortyp (Wert-empfindlich) geliefert.<br />

<strong>Adaptive</strong> Server <strong>Anywhere</strong>-Cursor anfordern<br />

Wenn Sie einen Cursortyp von Ihrer Clientanwendung aus anfordern, liefert<br />

<strong>Adaptive</strong> Server <strong>Anywhere</strong> einen Cursor. <strong>Adaptive</strong> Server <strong>Anywhere</strong>-Cursor<br />

werden nicht durch den in der Programmierschnittstelle festgelegten Typ<br />

definiert, sondern durch die Empfindlichkeit der Ergebnismenge auf<br />

Änderungen in den darunter liegenden Daten. Abhängig vom verlangten<br />

Cursortyp liefert <strong>Adaptive</strong> Server <strong>Anywhere</strong> einen Cursor mit einem<br />

Verhalten, das dem Typ entspricht.<br />

27


Cursortypen auswählen<br />

ODBC und OLE DB<br />

Ausnahmen<br />

Embedded SQL<br />

28<br />

Die Empfindlichkeit der <strong>Adaptive</strong> Server <strong>Anywhere</strong>-Cursorn wird<br />

entsprechend der Cursortyp-Anfrage des Clients gesetzt.<br />

Die nachstehende Tabelle beschreibt die Cursorempfindlichkeit, die bei<br />

verschiedenen abrollbaren ODBC-Cursortypen eingestellt wird.<br />

Abrollbarer ODBC-Cursortyp <strong>Adaptive</strong> Server <strong>Anywhere</strong>-Cursor<br />

STATIC Insensitive (Unempfindlich)<br />

KEYSET Wertempfindlich<br />

DYNAMIC Sensitiv (Empfindlich)<br />

MIXED Wertempfindlich<br />

$ Hinweise zu <strong>Adaptive</strong> Server <strong>Anywhere</strong>-Cursorn und ihrem Verhalten<br />

finden Sie unter "<strong>Adaptive</strong> Server <strong>Anywhere</strong>-Cursor" auf Seite 30. Hinweise<br />

über das Anfordern eines Cursortyps in ODBC finden Sie unter "Cursor-<br />

Eigenschaften wählen" auf Seite 299.<br />

Wenn Sie einen STATIC-Cursor als aktualisierbar anfordern, wird statt<br />

dessen ein Wert-empfindlicher Cursor geliefert und eine Warnung<br />

ausgegeben.<br />

Wenn ein DYNAMIC- oder MIXED-Cursor angefordert wird und die<br />

Abfrage nicht ohne Arbeitstabellen ausgeführt werden kann, wird statt<br />

dessen ein nicht-empfindlicher Cursor geliefert und eine Warnung<br />

ausgegeben.<br />

Um einen Cursor von einer Embedded SQL-Anwendung anzufordern, geben<br />

Sie den Cursortyp in der DECLARE-Anweisung an. Die nachstehende<br />

Tabelle beschreibt die Cursorempfindlichkeit, die als Antwort auf<br />

unterschiedliche Anforderungen eingestellt wird.<br />

Cursortyp <strong>Adaptive</strong> Server <strong>Anywhere</strong>-Cursor<br />

NO SCROLL Asensitiv (Nicht empfindlich)<br />

DYNAMIC SCROLL Asensitive (Nicht empfindlich)<br />

SCROLL Wertempfindlich<br />

INSENSITIVE Insensitive (Unempfindlich)<br />

SENSITIVE Sensitive (Empfindlich)


Ausnahmen<br />

JDBC<br />

Open Client<br />

Lesezeichen und Cursor<br />

Block-Cursor<br />

Kapitel 2 SQL in Anwendungen verwenden<br />

Wenn Sie einen DYNAMIC SCROLL- oder NO SCROLL-Cursor als<br />

UPDATABLE anfordern, wird ein empfindlicher oder wertempfindlicher<br />

Cursor geliefert. Es ist nicht ausgemacht, welcher der Beiden geliefert wird.<br />

Diese Ungewissheit entspricht der Definition von nicht-empfindlichem<br />

Verhalten.<br />

Wenn Sie einen INSENSITIVE-Cursor als UPDATABLE anfordern, wird<br />

ein wertempfindlicher Cursor geliefert.<br />

Wenn Sie einen DYNAMIC SCROLL-Cursor anfordern, die PREFETCH-<br />

Datenbankoption auf OFF eingestellt ist und der Ausführungsplan der<br />

Abfrage keine Arbeitstabellen verlangt, wird möglicherweise ein<br />

empfindlicher Cursor geliefert. Wieder entspricht diese Ungewissheit der<br />

Definition von nicht-empfindlichem Verhalten.<br />

Es steht nur ein Typ von Cursorn <strong>für</strong> JDBC-Anwendungen zur Verfügung.<br />

Dies ist ein nicht-empfindlicher Cursor. In JDBC können Sie eine<br />

ExecuteQuery-Anweisung ausführen, um einen Cursor zu öffnen.<br />

Es steht nur ein Typ von Cursorn <strong>für</strong> JDBC-Anwendungen zur Verfügung.<br />

Das ist ein nicht-empfindlicher Cursor.<br />

ODBC bietet Lesezeichen an bzw. Werte zum Identifizieren von Zeilen in<br />

einem Cursor. <strong>Adaptive</strong> Server <strong>Anywhere</strong> unterstützt Lesezeichen <strong>für</strong> alle<br />

Arten von Cursorn, mit Ausnahme von dynamischen Cursorn.<br />

ODBC stellt einen Cursortyp namens Block-Cursor zur Verfügung. Wenn<br />

Sie einen solchen Block-Cursor verwenden, können Sie SQLFetchScroll<br />

oder SQLExtendedFetch benutzen, um einen Zeilenblock und nicht eine<br />

einzelne Zeile abzurufen. Block-Cursor verhalten sich genauso wie<br />

Embedded SQL ARRAY-Abrufe.<br />

29


<strong>Adaptive</strong> Server <strong>Anywhere</strong>-Cursor<br />

<strong>Adaptive</strong> Server <strong>Anywhere</strong>-Cursor<br />

Änderungen bei<br />

Mitgliedschaft,<br />

Reihenfolge und<br />

Werten<br />

30<br />

Sobald ein Cursor geöffnet ist, hat er eine zugeordnete Ergebnismenge. Der<br />

Cursor bleibt eine Zeit lang geöffnet. Während dieser Zeit kann die dem<br />

Cursor zugeordnete Ergebnismenge geändert werden, entweder durch den<br />

Cursor selbst oder, abhängig von den Anforderungen der Isolationsstufe,<br />

durch andere Transaktionen. Manche Cursor ermöglichen es, Änderungen an<br />

den darunter liegenden Daten sichtbar zu machen, während bei Anderen<br />

diese Änderungen nicht auszumachen sind. Das unterschiedliche Verhalten<br />

von Cursorn in Bezug auf Änderungen an den darunter liegenden Daten wird<br />

die Empfindlichkeit des Cursors genannt.<br />

<strong>Adaptive</strong> Server <strong>Anywhere</strong> stellt Cursor mit einer Vielzahl von<br />

Empfindlichkeitseigenschaften zur Verfügung. Dieser Abschnitt beschreibt,<br />

was Empfindlichkeit ist, sowie die Empfindlichkeitseigenschaften von<br />

Cursorn.<br />

Dabei wird vorausgesetzt, dass Sie mit dem Abschnitt "Was sind Cursor?"<br />

auf Seite 15 vertraut sind.<br />

Änderungen an den darunter liegenden Daten können sich folgendermaßen<br />

auf die Ergebnismenge eines Cursors auswirken:<br />

♦ Mitgliedschaft Die Menge der Zeilen in der Ergebnismenge, die durch<br />

ihre Primärschlüsselwerte gekennzeichnet sind.<br />

♦ Reihenfolge Die Reihenfolge der Zeilen in der Ergebnismenge.<br />

♦ Wert Die Werte der Zeilen in der Ergebnismenge.<br />

Nehmen Sie zum Beispiel die folgende einfache Tabelle mit Mitarbeiterdaten<br />

(emp_id ist die Primärschlüsselspalte):<br />

emp_id emp_lname<br />

1 Whitney<br />

2 Cobb<br />

3 Chin<br />

Ein Cursor auf der folgenden Abfrage gibt alle Ergebnisse aus der Tabelle in<br />

der Reihenfolge des Primärschlüssels zurück.<br />

SELECT emp_id, emp_lname<br />

FROM employee<br />

ORDER BY emp_id


Sichtbare und<br />

unsichtbare<br />

Änderungen<br />

Kapitel 2 SQL in Anwendungen verwenden<br />

Die Mitgliedschaft der Ergebnismenge könnte durch das Hinzufügen einer<br />

neuen Zeile oder das Löschen einer Zeile geändert werden. Die Werte<br />

könnten durch eine Namensänderung in der Tabelle geändert werden. Die<br />

Reihenfolge könnte geändert werden, indem der Primärschlüssel eines<br />

Mitarbeiters geändert wird.<br />

Abhängig von den Anforderungen der Isolationsstufe können Mitgliedschaft,<br />

Reihenfolge und Werte der Ergebnismenge eines Cursors geändert werden,<br />

nachdem der Cursor geöffnet wurde. Es hängt vom Typ des verwendeten<br />

Cursors ab, ob sich die Ergebnismenge, wie sie von der Anwendung gesehen<br />

wird, ändert, um diese Änderungen darzustellen.<br />

Änderungen an den darunter liegenden Daten können durch den Cursor<br />

sichtbar oder unsichtbar sein. Eine sichtbare Änderung ist eine, die sich in<br />

der Ergebnismenge des Cursors wiederspiegelt. Änderungen an den darunter<br />

liegenden Daten, die nicht in der Ergebnismenge, wie sie vom Cursor<br />

gesehen wird, wiedergespiegelt werden, sind unsichtbar.<br />

Überblick über die Cursor-Empfindlichkeit<br />

<strong>Adaptive</strong> Server <strong>Anywhere</strong>-Cursor werden anhand ihrer Empfindlichkeit<br />

gegenüber Änderungen an den darunter liegenden Daten eingeteilt. Im<br />

Besonderen wird die Cursor-Empfindlichkeit anhand der Sichtbarkeit von<br />

Änderungen definiert.<br />

♦ Unempfindliche Cursor Die Ergebnismenge ist unveränderlich, wenn<br />

der Cursor geöffnet ist. Änderungen an den darunter liegenden Daten<br />

sind nicht sichtbar.<br />

$ Weitere Hinweise finden Sie unter "Unempfindliche Cursor" auf<br />

Seite 36.<br />

♦ Empfindliche Cursor Die Ergebnismenge kann sich ändern, nachdem<br />

der Cursor geöffnet wurde. Alle Änderungen an den darunter liegenden<br />

Daten sind sichtbar.<br />

$ Weitere Hinweise finden Sie unter "Empfindliche Cursor" auf<br />

Seite 37.<br />

♦ Nicht-empfindliche Cursor Änderungen können in der Mitgliedschaft,<br />

der Reihenfolge oder den Werten der Ergebnismenge, wie sie durch den<br />

Cursor gesehen wird, wiedergespiegelt werden, müssen es aber nicht.<br />

$ Weitere Hinweise finden Sie unter "Nicht-empfindliche Cursor"<br />

auf Seite 39.<br />

♦ Wert-empfindliche Cursor Änderungen in der Reihenfolge oder den<br />

Werten der darunter liegenden Daten sind sichtbar. Die Mitgliedschaft<br />

der Ergebnismenge ist unveränderlich, wenn der Cursor geöffnet ist.<br />

31


<strong>Adaptive</strong> Server <strong>Anywhere</strong>-Cursor<br />

32<br />

$ Weitere Hinweise finden Sie unter "Wert-empfindliche Cursor" auf<br />

Seite 40.<br />

Die unterschiedlichen Anforderungen an Cursor bewirken unterschiedliche<br />

Beschränkungen bei der Ausführung, was sich wiederum auf die<br />

Performance auswirkt. Weitere Hinweise finden Sie unter "Cursor-<br />

Empfindlichkeit und Performance" auf Seite 43.<br />

Beispiel <strong>für</strong> Cursor-Empfindlichkeit: Eine gelöschte Zeile<br />

Dieses Beispiel verwendet eine einfache Abfrage, um zu illustrieren, wie<br />

verschiedene Cursor auf eine Zeile in der Ergebnismenge reagieren, die<br />

gelöscht wird.<br />

Es gibt die folgende Abfolge von Ereignissen:<br />

1 Eine Anwendung öffnet einen Cursor auf der folgenden Abfrage auf der<br />

Beispieldatenbank.<br />

SELECT emp_id, emp_lname<br />

FROM employee<br />

ORDER BY emp_id<br />

emp_id emp_lname<br />

102 Whitney<br />

105 Cobb<br />

160 Breault<br />

… …<br />

2 Die Anwendung ruft die erste Zeile durch den Cursor ab (102).<br />

3 Die Anwendung ruft die nächste Zeile durch den Cursor ab (105).<br />

4 Eine weitere Anwendung löscht Mitarbeiter 102 (Whitney) und schreibt<br />

die Änderung fest.<br />

In dieser Situation hängen die Ergebnisse der Cursor-Aktionen von der<br />

Cursor-Empfindlichkeit ab.<br />

♦ Unempfindliche Cursor Das DELETE wird weder in der Mitgliedschaft<br />

noch in den Werten der Ergebnissen, wie sie durch den Cursor gesehen<br />

werden, wiedergespiegelt:


Maßnahme Ergebnis<br />

Vorherige Zeile<br />

abrufen<br />

Erste Zeile abrufen<br />

(absoluter Abruf)<br />

Zweite Zeile abrufen<br />

(absoluter Abruf)<br />

Kapitel 2 SQL in Anwendungen verwenden<br />

Gibt die ursprüngliche Kopie der Zeile zurück<br />

(102).<br />

Gibt die ursprüngliche Kopie der Zeile zurück<br />

(102).<br />

Gibt die ungeänderte Zeile zurück (105).<br />

♦ Empfindliche Cursor Die Mitgliedschaft der Ergebnismenge hat sich<br />

insofern geändert, dass jetzt Zeile 105 die erste Zeile in der<br />

Ergebnismenge ist:<br />

Maßnahme Ergebnis<br />

Vorherige Zeile<br />

abrufen<br />

Erste Zeile abrufen<br />

(absoluter Abruf)<br />

Zweite Zeile abrufen<br />

(absoluter Abruf)<br />

Gibt den Fehler Zeile nicht gefunden zurück. Es<br />

gibt keine vorherige Zeile.<br />

Gibt Zeile 105 zurück.<br />

Gibt Zeile 160 zurück.<br />

♦ Wert-empfindliche Cursor Die Mitgliedschaft der Ergebnismenge ist<br />

unveränderlich, und daher ist Zeile 105 weiterhin die zweite Zeile in der<br />

Ergebnismenge. Das DELETE wird in den Werten des Cursors<br />

wiedergespiegelt und erzeugt ein tatsächliches "Loch" in der<br />

Ergebnismenge.<br />

Maßnahme Ergebnis<br />

Vorherige Zeile<br />

abrufen<br />

Erste Zeile abrufen<br />

(absoluter Abruf)<br />

Zweite Zeile abrufen<br />

(absoluter Abruf)<br />

Gibt Keine aktuelle Cursorzeile zurück. Wo<br />

vorher die erste Zeile war, steht jetzt im Cursor<br />

eine Lücke.<br />

Gibt Keine aktuelle Cursorzeile zurück. Wo<br />

vorher die erste Zeile war, steht jetzt im Cursor<br />

eine Lücke.<br />

Gibt Zeile 105 zurück.<br />

33


<strong>Adaptive</strong> Server <strong>Anywhere</strong>-Cursor<br />

34<br />

♦ Nicht-empfindliche Cursor Die Mitgliedschaft und Werte der<br />

Ergebnismenge sind in Bezug auf die Änderungen unbestimmt. Die<br />

Antwort auf einen Abruf der vorherigen Zeile, der ersten Zeile oder der<br />

zweiten Zeile hängt von der entsprechenden Optimierungsmethode <strong>für</strong><br />

die Abfrage ab. Die Antwort hängt davon ab, ob die Methode die<br />

Erstellung einer Arbeitstabelle erfordert und ob die abgerufene Zeile<br />

vom Client vorab abgerufen wurde.<br />

Der Vorteil von nicht-empfindlichen Cursorn liegt darin, dass <strong>für</strong> viele<br />

Anwendungen die Empfindlichkeit unwichtig ist. Besonders wenn Sie<br />

einen schreibgeschützten Vorwärts-Cursor verwenden, sind keine der<br />

darunter liegenden Änderungen sichtbar. Auch wenn Sie auf einer hohen<br />

Isolationsstufe ausführen, sind darunter liegende Änderungen nicht<br />

zulässig.<br />

Beispiel <strong>für</strong> Cursor-Empfindlichkeit: Eine aktualisierte Zeile<br />

Dieses Beispiel verwendet eine einfache Abfrage, um zu illustrieren wie<br />

verschiedene Cursortypen auf eine Zeile in der Ergebnismenge reagieren, die<br />

aktualisiert wird und dadurch die Reihenfolge in der Ergebnismenge<br />

verändert.<br />

Es gibt die folgende Abfolge von Ereignissen:<br />

1 Eine Anwendung öffnet einen Cursor auf der folgenden Abfrage auf der<br />

Beispieldatenbank.<br />

SELECT emp_id, emp_lname<br />

FROM employee<br />

emp_id emp_lname<br />

102 Whitney<br />

105 Cobb<br />

160 Breault<br />

… …<br />

2 Die Anwendung ruft die erste Zeile durch den Cursor ab (102).<br />

3 Die Anwendung ruft die nächste Zeile durch den Cursor ab (105).<br />

4 Eine weitere Transaktion aktualisiert die Mitarbeiter-ID des Mitarbeiters<br />

102 (Whitney) auf 165 und schreibt die Änderung fest.<br />

In dieser Situation hängen die Ergebnisse der Cursor-Aktionen von der<br />

Cursor-Empfindlichkeit ab.


Kapitel 2 SQL in Anwendungen verwenden<br />

♦ Unempfindliche Cursor Das UPDATE wird weder in der<br />

Mitgliedschaft noch in den Werten der Ergebnisse, wie sie durch den<br />

Cursor gesehen werden, wiedergespiegelt:<br />

Maßnahme Ergebnis<br />

Vorherige Zeile<br />

abrufen<br />

Erste Zeile abrufen<br />

(absoluter Abruf)<br />

Zweite Zeile abrufen<br />

(absoluter Abruf)<br />

Gibt die ursprüngliche Kopie der Zeile zurück<br />

(102).<br />

Gibt die ursprüngliche Kopie der Zeile zurück<br />

(102).<br />

Gibt die ungeänderte Zeile zurück (105).<br />

♦ Empfindliche Cursor Die Mitgliedschaft der Ergebnismenge hat sich<br />

insofern geändert, dass jetzt Zeile 105 die erste Zeile in der<br />

Ergebnismenge ist:<br />

Maßnahme Ergebnis<br />

Vorherige Zeile<br />

abrufen<br />

Erste Zeile abrufen<br />

(absoluter Abruf)<br />

Zweite Zeile abrufen<br />

(absoluter Abruf)<br />

Gibt den Fehler Zeile nicht gefunden zurück.<br />

Die Mitgliedschaft der Ergebnismenge hat sich<br />

geändert und 105 ist jetzt die erste Zeile. Der<br />

Cursor wird auf die Position vor der ersten Zeile<br />

verschoben.<br />

Gibt Zeile 105 zurück.<br />

Gibt Zeile 160 zurück.<br />

Außerdem wird beim Abrufen durch einen empfindlichen Cursor die<br />

Warnung SQLE_ROW_UPDATED_WARNING ausgegeben, wenn die<br />

Zeile seit dem letzten Lesen geändert wurde. Die Warnung wird nur<br />

einmal ausgegeben. Aufeinander folgende FETCH-Vorgänge <strong>für</strong><br />

dieselbe Zeile lösen keine Warnung aus.<br />

Ähnlich gibt auch eine positionsbasierte UPDATE- oder DELETE-<br />

Anweisung durch den Cursor auf einer Zeile, die seit dem letzten Abruf<br />

geändert wurde, die Fehlermeldung<br />

SQLE_ROW_UPDATED_SINCE_READ aus. Eine Anwendung muss<br />

das Abrufen einer Zeile nochmals durchführen, damit UPDATE oder<br />

DELETE bei einem empfindlichen Cursor funktionieren.<br />

Eine Aktualisierung einer Spalte bewirkt die Warnung oder den Fehler,<br />

auch wenn die Spalte vom Cursor nicht referenziert wird. Beispiel: Ein<br />

Cursor auf einer Abfrage, der emp_lname zurückgibt, würde die<br />

Aktualisierung melden, auch wenn nur die Spalte salary geändert<br />

worden wäre.<br />

35


<strong>Adaptive</strong> Server <strong>Anywhere</strong>-Cursor<br />

Unempfindliche Cursor<br />

Standards<br />

36<br />

♦ Wert-empfindliche Cursor Die Mitgliedschaft der Ergebnismenge ist<br />

unveränderlich, und daher ist Zeile 105 weiterhin die zweite Zeile in der<br />

Ergebnismenge. Das DELETE wird in den Werten des Cursors<br />

wiedergespiegelt und erzeugt ein tatsächliches "Loch" in der<br />

Ergebnismenge.<br />

Maßnahme Ergebnis<br />

Vorherige Zeile<br />

abrufen<br />

Erste Zeile abrufen<br />

(absoluter Abruf)<br />

Zweite Zeile abrufen<br />

(absoluter Abruf)<br />

Gibt den Fehler Zeile nicht gefunden zurück.<br />

Die Mitgliedschaft der Ergebnismenge hat sich<br />

geändert und 105 ist jetzt die erste Zeile. Der<br />

Cursor wird über dem Loch positioniert: Er<br />

befindet sich vor Zeile 105.<br />

Gibt den Fehler Zeile nicht gefunden zurück.<br />

Die Mitgliedschaft der Ergebnismenge hat sich<br />

geändert und 105 ist jetzt die erste Zeile. Der<br />

Cursor wird über dem Loch positioniert: Er<br />

befindet sich vor Zeile 105.<br />

Gibt Zeile 105 zurück.<br />

♦ Nicht-empfindliche Cursor Die Mitgliedschaft und Werte der<br />

Ergebnismenge sind in Bezug auf die Änderungen unbestimmt. Die<br />

Antwort auf einen Abruf der vorherigen Zeile, der ersten Zeile oder der<br />

zweiten Zeile hängt von der entsprechenden Optimierungsmethode <strong>für</strong><br />

die Abfrage ab, ob die Methode die Erstellung einer Arbeitstabelle<br />

erfordert und ob die abgerufene Zeile vom Client vorab abgerufen<br />

wurde.<br />

Keine Warnungen oder Fehler in Massenvorgängen<br />

Warnungs- und Fehlerbedingungen <strong>für</strong> Aktualisierungen kommen in<br />

Massenvorgängen nicht vor (Option -b <strong>für</strong> Datenbankserver).<br />

Diese Cursor haben unempfindliche Mitgliedschaft, Reihenfolge und Werte.<br />

Keine Änderungen, die nach dem Öffnen des Cursors durchgeführt werden,<br />

sind sichbar.<br />

Unempfindliche Cursor werden nur <strong>für</strong> schreibgeschützte Cursortypen<br />

verwendet.<br />

Unempfindliche Cursor entsprechen der ISO/ANSI-Standarddefinition von<br />

unempfindlichen Cursorn beziehungsweise den statischen ODBC-Cursorn.


Programmierschnittstellen<br />

Beschreibung<br />

Empfindliche Cursor<br />

Standards<br />

Schnittstelle Cursortyp Kommentar<br />

ODBC, OLE DB<br />

und ADO<br />

Embedded SQL INSENSITIVE<br />

oder NO<br />

SCROLL<br />

JDBC Nicht unterstützt<br />

Open Client Nicht unterstützt<br />

Kapitel 2 SQL in Anwendungen verwenden<br />

Static Wenn ein aktualisierbarer statischer<br />

Cursor angefordert wird, wird statt<br />

dessen ein Wert-empfindlicher Cursor<br />

verwendet.<br />

Unempfindliche Cursor geben immer Zeilen zurück, die den<br />

Auswahlkriterien der Abfrage entsprechen, und zwar in der durch eine<br />

ORDER BY-Klausel festgelegte Reihenfolge.<br />

Die Ergebnismenge eines unempfindlichen Cursors wird vollständig als<br />

Arbeitstabelle materialisiert, wenn der Cursor geöffnet wird. Das hat<br />

folgende Konsequenzen:<br />

♦ Wenn die Ergebnismenge sehr umfangreich ist, sind die Festplatten- und<br />

Speicheranforderungen zum Verwalten des Ergebnisses möglicherweise<br />

von Bedeutung.<br />

♦ Keine Zeile wird an die Anwendung zurückgegeben, bevor nicht die<br />

gesamte Ergebnismenge als eine Arbeitstabelle zusammengestellt ist.<br />

Bei komplexen Abfragen kann das zu einer Verzögerung führen, bevor<br />

die erste Zeile an die Anwendung zurückgegeben wird.<br />

♦ Nachfolgende Zeilen können direkt von der Arbeitstabelle abgerufen<br />

werden, und werden daher rasch ausgegeben. Die Client-Bibliothek<br />

kann mehrere Zeilen gleichzeitig vorab abrufen, was die Performance<br />

weiter steigert.<br />

♦ Unempfindliche Cursor sind von ROLLBACK oder ROLLBACK TO<br />

SAVEPOINT nicht betroffen.<br />

Diese Cursor haben empfindliche Mitgliedschaft, Reihenfolge und Werte.<br />

Empfindliche Cursor können <strong>für</strong> schreibgeschützte oder aktualisierbare<br />

Cursortypen verwendet werden.<br />

Empfindliche Cursor entsprechen der ISO/ANSI-Standarddefinition von<br />

empfindlichen Cursorn beziehungsweise den dynamischen ODBC-Cursorn.<br />

37


<strong>Adaptive</strong> Server <strong>Anywhere</strong>-Cursor<br />

Programmierschnittstellen<br />

Beschreibung<br />

38<br />

Schnittstelle Cursortyp Kommentar<br />

ODBC, OLE DB<br />

und ADO<br />

Dynamic<br />

Embedded SQL SENSITIVE Wird auch als Antwort auf eine Anfrage<br />

nach einem DYNAMIC SCROLL-Cursor<br />

geliefert, wenn keine Arbeitstabelle<br />

erforderlich ist und PREFETCH auf OFF<br />

eingestellt ist.<br />

Alle Änderungen sind durch den Cursor sichtbar, sowohl die Änderungen<br />

durch den Cursor als auch die durch andere Transaktionen. Höhere<br />

Isolationsstufen können auf Grund von Sperren manche Änderungen<br />

verbergen, die von anderen Transaktionen durchgeführt werden.<br />

Alle Änderungen von Mitgliedschaft, Reihenfolge und Spaltenwerten des<br />

Cursors sind sichtbar. Beispiel: Wenn ein empfindlicher Cursor einen Join<br />

enthält und einer der Werte von einer der darunter liegenden Tabelle<br />

geändert wird, dann zeigen alle Ergebniszeilen, die aus dieser Basiszeile<br />

zusammengesetzt sind, den neuen Wert. Die Mitgliedschaft und Reihenfolge<br />

der Ergebnismenge können sich bei jedem Abruf ändern.<br />

Empfindliche Cursor geben immer Zeilen zurück, die den Auswahlkriterien<br />

der Abfrage entsprechen, und zwar in der durch eine ORDER BY-Klausel<br />

festgelegte Reihenfolge. Aktualisierungen können sich auf die<br />

Mitgliedschaft, Reihenfolge und Werte der Ergebnismenge auswirken.<br />

Die Anforderungen von empfindlichen Cursorn bewirken bei der<br />

Implementierung von empfindlichen Cursorn folgende Einschränkungen:<br />

♦ Zeilen können nicht vorab abgerufen werden, weil die Änderungen an<br />

solchen Zeilen durch den Cursor nicht sichtbar wären. Das kann sich auf<br />

die Performance auswirken.<br />

♦ Empfindliche Cursor müssen so implementiert werden, dass keine<br />

Arbeitstabellen zusammengestellt werden, weil Änderungen an den in<br />

der Arbeitstabelle gespeicherten Zeilen durch den Cursor nicht sichtbar<br />

wären.<br />

♦ Die Bedingung, keine Arbeitstabelle zu verwenden, schränkt die<br />

Auswahl der Join-Methode durch den Optimierer ein und kann sich<br />

daher auf die Performance auswirken.<br />

♦ Bei einigen Abfragen ist es unvermeidlich, dass der Optimierer einen<br />

Plan erstellt, der eine Arbeitstabelle enthält, und somit keinen<br />

empfindlichen Cursor erlaubt.


Nicht-empfindliche Cursor<br />

Standards<br />

Programmierschnittstellen<br />

Kapitel 2 SQL in Anwendungen verwenden<br />

Arbeitstabellen werden üblicherweise zum Sortieren und Gruppieren<br />

von Zwischenergebnissen verwendet. Eine Arbeitstabelle ist zum<br />

Sortieren nicht erforderlich, wenn auf die Zeilen durch einen Index<br />

zugegriffen werden kann. Es ist nicht immer möglich vorherzusagen,<br />

welche Abfragen Arbeitstabellen verwenden, aber sie werden von<br />

folgenden Abfragen verwendet:<br />

♦ UNION-Abfragen, auch wenn UNION ALL nicht unbedingt<br />

Arbeitstabellen verwenden.<br />

♦ Anweisungen mit einer ORDER BY-Klausel, wenn es keinen Index<br />

auf der ORDER BY-Spalte gibt.<br />

♦ Jede Abfrage, die mit einem Hash-Join optimiert ist.<br />

♦ Viele Abfragen, die DISTINCT- oder GROUP BY-Klauseln<br />

betreffen.<br />

In diesen Fällen gibt <strong>Adaptive</strong> Server <strong>Anywhere</strong> entweder eine<br />

Fehlermeldung an die Anwendung zurück, oder er ändert den Cursortyp<br />

in einen nicht-empfindlichen Cursor und gibt eine Warnmeldung aus.<br />

$ Weitere Hinweise zur Abfragenoptimierung und Verwendung von<br />

Arbeitstabellen finden Sie unter "Abfragen optimieren und ausführen"<br />

auf Seite 345 der Dokumentation ASA SQL-Benutzerhandbuch.<br />

Diese Cursor haben keine genau definierte Empfindlichkeit in ihrer<br />

Mitgliedschaft, ihrer Reihenfolge oder ihren Werten. Die Flexibilität, die sie<br />

in Bezug auf Empfindlichkeit haben, ermöglicht es, nicht-empfindliche<br />

Cursor <strong>für</strong> die Performance zu optimieren.<br />

Nicht-empfindliche Cursor werden nur <strong>für</strong> schreibgeschützte Cursortypen<br />

verwendet.<br />

Nicht-empfindliche Cursor entsprechen der ISO/ANSI-Standarddefinition<br />

von nicht-empfindlichen Cursorn beziehungsweise den ODBC-Cursorn mit<br />

unbestimmter Empfindlichkeit.<br />

Schnittstelle Cursortyp<br />

ODBC, OLE DB und ADO Unspecified sensitivity<br />

Embedded SQL DYNAMIC SCROLL<br />

39


<strong>Adaptive</strong> Server <strong>Anywhere</strong>-Cursor<br />

Beschreibung<br />

Wert-empfindliche Cursor<br />

Standards<br />

Programmierschnittstellen<br />

40<br />

Die Anforderung eines nicht-empfindlichen Cursors schränkt die Auswahl<br />

der Methoden kaum ein, die <strong>Adaptive</strong> Server <strong>Anywhere</strong> verwenden kann,<br />

um die Abfrage zu optimieren und Zeilen an die Anwendung zurückzugeben.<br />

Aus diesen Gründen erhalten Sie mit nicht-empfindlichen Cursorn die beste<br />

Performance. Vor allem steht es dem Optimierer frei, jede Maßnahme zur<br />

Materialisierung von Zwischenergebnissen, wie z.B. Arbeitstabellen,<br />

anzuwenden, und Zeilen können vom Client vorab abgerufen werden.<br />

<strong>Adaptive</strong> Server <strong>Anywhere</strong> kann die Sichtbarkeit von Änderungen in den<br />

darunter liegenden Basiszeilen nicht garantieren. Einige Änderung können<br />

sichtbar sein, andere nicht. Die Mitgliedschaft und Reihenfolge können sich<br />

mit jedem Abruf ändern. Besonders Aktualisierungen in Basiszeilen können<br />

dazu führen, dass nur einige der aktualisierten Spalten im Ergebnis des<br />

Cursors wiedergespiegelt werden.<br />

Nicht-empfindliche Cursor sind keine Garantie da<strong>für</strong>, dass Zeilen<br />

zurückgegeben werden, die der Auswahl und Reihenfolge der Abfrage<br />

entsprechen. Die Zeilenmitgliedschaft steht zum Zeitpunkt des Öffnens des<br />

Cursors fest, aber nachfolgende Änderungen an den darunter liegenden<br />

Werten werden in den Ergebnissen wiedergespiegelt.<br />

Nicht-empfindliche Cursor geben immer Zeilen zurück, die den WHEREund<br />

ORDER BY-Klauseln des Kunden zu dem Zeitpunkt entsprachen, an<br />

dem die Cursor-Mitgliedschaft etabliert wurde. Wenn sich Spaltenwerte nach<br />

dem Öffnen des Cursors ändern, werden möglicherweise Zeilen<br />

zurückgegeben, die nicht mehr den WHERE- und ORDER BY-Klauseln<br />

entsprechen.<br />

Diese Cursor sind in Bezug auf ihre Mitgliedschaft unempfindlich, da<strong>für</strong> sind<br />

sie empfindlich, was die Reihenfolge und Werte der Ergebnismenge betrifft.<br />

Wert-empfindliche Cursor können <strong>für</strong> schreibgeschützte oder aktualisierbare<br />

Cursortypen verwendet werden.<br />

Wert-empfindliche Cursor entsprechen keiner ISO/ANSI-Standarddefintion.<br />

Sie entsprechen den Schlüsselmengen-gesteuerten ODBC-Cursorn.<br />

Schnittstelle Cursortyp<br />

ODBC, OLE DB und ADO Schlüsselmengen-basiert<br />

Embedded SQL SCROLL<br />

JDBC Schlüsselmengen-basiert<br />

Open Client Schlüsselmengen-basiert


Beschreibung<br />

Kapitel 2 SQL in Anwendungen verwenden<br />

Wenn eine Anwendung eine Zeile abruft, die aus einer darunter liegenden<br />

geänderten Basiszeile besteht, dann muss der Anwendung der aktualisierte<br />

Wert sowie die SQL_ROW_UPDATED-Statusmeldung übermittelt werden.<br />

Wenn die Anwendung versucht, eine Zeile abzurufen, die aus einer darunter<br />

liegenden Basiszeile zusammengesetzt war, welche gelöscht worden ist,<br />

muss eine SQL_ROW_DELETED-Statusmeldung an die Anwendung<br />

übermittelt werden.<br />

Eine Änderung am Primärschlüsselwert entfernt die Zeile aus der<br />

Ergebnismenge (dies wird als Löschen, gefolgt von Einfügen, behandelt).<br />

Ein Sonderfall tritt auf, wenn eine Zeile in der Ergebnismenge gelöscht wird<br />

(durch den Cursor oder von auswärts), und eine neue Zeile mit demselben<br />

Schlüsselwert eingefügt wird. Das führt dazu, dass die neue Zeile die alte<br />

Zeile in der ursprünglichen Position ersetzt.<br />

Es gibt keine Garantie, dass die Zeilen in der Ergebnismenge dem<br />

Reihenfolgen- oder Auswahlkriterium der Abfrage entsprechen. Da die<br />

Zeilenmitgliedschaft zum Zeitpunkt des Öffnens festgelegt wird, führen<br />

nachfolgende Änderungen, durch die eine Zeile nicht mehr der WHEREoder<br />

ORDER BY-Klausel entspricht, nicht dazu, dass sich die Mitgliedschaft<br />

oder Position einer Zeile ändert.<br />

Alle Werte sind in Bezug auf Änderungen, die durch den Cursor<br />

durchgeführt werden,empfindlich. Die Empfindlichkeit der Mitgliedschaft<br />

gegenüber Änderungen, die durch den Cursor ausgeführt werden, wird durch<br />

die ODBC-Option SQL_STATIC_SENSITIVITY gesteuert. Wenn diese<br />

Option auf ON eingestellt ist, fügen Einfügungen durch den Cursor die Zeile<br />

dem Cursor hinzu. Ansonsten ist sie nicht in der Ergebnismenge enthalten.<br />

Löschungen durch den Cursor entfernen die Zeile aus der Ergebnismenge,<br />

wodurch ein Lücke vermieden wird, und geben die SQL_ROW_DELETED-<br />

Statusmeldung zurück.<br />

Wert-empfindliche Cursor verwenden eine Schlüsselmengen-Tabelle. Wenn<br />

der Cursor geöffnet wird, füllt <strong>Adaptive</strong> Server <strong>Anywhere</strong> eine<br />

Arbeitstabelle mit Kenndaten <strong>für</strong> jede Zeile an, die zur Ergebnismenge<br />

beiträgt. Wenn Sie die Ergebnismenge durchblättern, wird die<br />

Schlüsselmengen-Tabelle zur Identifizierung der Mitgliedschaft der<br />

Ergebnismenge verwendet, aber die Daten werden, falls erforderlich, von<br />

den darunter liegenden Tabellen bezogen.<br />

Die Eigenschaft der festen Mitgliedschaft von Wert-empfindlichen Cursorn<br />

ermöglicht es Ihrer Anwendung, sich an die Zeilenpositionen innerhalb eines<br />

Cursors erinnern, und stellt sicher, dass diese Positionen nicht geändert<br />

werden. Weitere Hinweise finden Sie unter "Beispiel <strong>für</strong> Cursor-<br />

Empfindlichkeit: Eine gelöschte Zeile" auf Seite 32.<br />

41


<strong>Adaptive</strong> Server <strong>Anywhere</strong>-Cursor<br />

42<br />

♦ Wenn eine Zeile seit dem Öffnen des Cursors aktualisiert<br />

beziehungsweise möglicherweise aktualisiert wurde, gibt <strong>Adaptive</strong><br />

Server <strong>Anywhere</strong> die Warnung SQLE_ROW_UPDATED_WARNING<br />

zurück, wenn die Zeile abgerufen wird. Die Warnung wird nur einmal<br />

ausgegeben: Ein weiteres Abrufen der Zeile generiert keine<br />

Warnmeldung.<br />

Eine Aktualisierung einer beliebigen Spalte in der Zeile verursacht diese<br />

Warnung sogar, wenn die aktualisierte Spalte nicht durch den Cursor<br />

referenziert wird. Ein Cursor auf emp_lname und emp_fname würde<br />

beispielsweise die Aktualisierung melden, selbst wenn nur die birthdate-<br />

Spalte geändert worden wäre. Diese Warn- und Fehlerbedingungen bei<br />

Aktualisierung treten nicht im Massenoperationsmodus (Option -b <strong>für</strong><br />

Datenbankserver) auf, wenn die Zeilensperre deaktiviert ist. Siehe<br />

"Performance-Überlegungen beim Bewegen von Daten" auf Seite 470<br />

der Dokumentation ASA SQL-Benutzerhandbuch.<br />

$ Weitere Hinweise finden Sie unter "Zeile wurde seit dem letzten<br />

Lesen aktualisiert" auf Seite 324 der Dokumentation ASA<br />

Fehlermeldungen<br />

♦ Der Versuch, eine positionsbasierte UPDATE- oder DELETE-<br />

Anweisung auf einer Zeile auszuführen, die seit dem letzten Abruf<br />

geändert wurde, gibt den SQLE_ROW_UPDATED_SINCE_READ-<br />

Fehler aus und bricht die Anweisung ab. Eine Anwendung muss die<br />

Zeile noch einmal mit FETCH ABRUFEN, bevor das UPDATE oder<br />

DELETE zugelassen wird.<br />

Eine Aktualisierung einer beliebigen Spalte in der Zeile verursacht<br />

diesen Fehler. Dies ist sogar dann der Fall, wenn die aktualisierte Spalte<br />

nicht durch den Cursor referenziert wird. Der Fehler tritt nicht im<br />

Massenvorgangsmodus auf.<br />

$ Weitere Hinweise finden Sie unter "Zeile seit dem letzten Lesen<br />

geändert - Vorgang abgebrochen" auf Seite 323 der Dokumentation ASA<br />

Fehlermeldungen.<br />

♦ Wenn eine Zeile, entweder durch den Cursor oder durch eine andere<br />

Transaktion, nach dem Öffnen des Cursors gelöscht wurde, entsteht im<br />

Cursor eine Lücke. Die Mitgliedschaft des Cursors steht fest, daher ist<br />

die Position einer Zeile reserviert, aber der DELETE-Vorgang wird im<br />

geänderten Wert <strong>für</strong> die Zeile wiedergespiegelt. Wenn Sie die Zeile an<br />

dieser Lücke abrufen, wird mit der Fehlermeldung Keine aktuelle<br />

Cursorzeile (SQL state 24503) darauf hingewiesen, dass es keine<br />

aktuelle Zeile gibt, und der Cursor wird auf der Lücke belassen. Sie<br />

können Lücken vermeiden, indem Sie empfindliche Cursor verwenden,<br />

da sich deren Mitgliedschaft zusammen mit den Werten verändert.


Kapitel 2 SQL in Anwendungen verwenden<br />

$ Weitere Hinweise finden Sie unter "Keine aktuelle Cursorzeile" auf<br />

Seite 207 der Dokumentation ASA Fehlermeldungen.<br />

Sie können <strong>für</strong> Wert-empfindliche Cursor Zeilen nicht vorab abrufen. Diese<br />

Einschränkung kann sich manchmal auf die Performance auswirken.<br />

Cursor-Empfindlichkeit und Performance<br />

Es besteht eine Wechselwirkung zwischen Performance und anderen Cursor-<br />

Eigenschaften. Besonders wenn Sie einen Cursor aktualisierbar machen,<br />

führt das zu Beschränkungen der Abfrageverarbeitung und -zustellung, was<br />

die Performance vermindert. Auch können Anforderungen an die Cursor-<br />

Empfindlichkeit die Performance einschränken.<br />

Um zu verstehen, wie sich die Aktualisierbarkeit und Empfindlichkeit von<br />

Cursorn auf die Performance auswirkt, ist es hilfreich zu wissen, wie die<br />

Ergebnisse, die durch einen Cursor sichtbar sind, von der Datenbank an die<br />

Client-Anwendung übermittelt werden.<br />

Im Einzelnen können Ergebnisse aus Performance-Gründen an zwei<br />

dazwischengeschalteten Standorten gespeichert werden:<br />

♦ Arbeitstabellen Sowohl Zwischen- als auch Endergebnisse können als<br />

Arbeitstabellen gespeichert werden. Wert-empfindliche Cursor<br />

verwenden eine Arbeitstabelle <strong>für</strong> Primärschlüsselwerte. Abfrage-<br />

Eigenschaften können ebenfalls dazu führen, dass der Optimierer in<br />

seinem gewählten Ausführungsplan Arbeitstabellen verwendet.<br />

♦ Prefetch-Vorgang Der Client kann Zeilen vorab in einen clientseitigen<br />

Puffer abrufen, um separate Anfragen an der Datenbankserver <strong>für</strong> jede<br />

Zeile zu vermeiden.<br />

Client-<br />

Anwendung<br />

ODBC-Treiber in der<br />

Netzwerk-Bibliothek<br />

Vorab<br />

abgerufene<br />

Zeilen<br />

Datenbank-<br />

Server<br />

Arbeitstabelle<br />

Die Empfindlichkeit und Aktualisierbarkeit beschränken die Verwendung<br />

von zwischengeschalteten Standorten.<br />

43


<strong>Adaptive</strong> Server <strong>Anywhere</strong>-Cursor<br />

Zeilen-Prefetch<br />

44<br />

Einem aktualisierbaren Cursor ist es nicht gestattet, Arbeitstabellen zu<br />

verwenden oder mit PREFETCH Ergebnisse vorab abzurufen. Wäre dies<br />

möglich, wäre er <strong>für</strong> verlorene Aktualisierungen anfällig. Dieses Problem<br />

wird im folgenden Beispiel erläutert:<br />

1 Eine Anwendung öffnet auf der Beispieldatenbank in der folgenden<br />

Abfrage einen Cursor.<br />

SELECT id, quantity<br />

FROM product<br />

id quantity<br />

300 28<br />

301 54<br />

302 75<br />

… …<br />

2 Die Anwendung ruft die Zeile mit id = 300 durch den Cursor ab.<br />

3 Eine weitere Transaktion aktualisiert die Zeile mit der folgenden<br />

Anweisung:<br />

UPDATE product<br />

SET quantity = quantity - 10<br />

WHERE id = 300<br />

4 Die Anwendung aktualisiert die Zeile durch den Cursor auf einen Wert<br />

von (quantity - 5 ).<br />

5 Der korrekte Endwert <strong>für</strong> die Zeile sollte 13 sein. Wenn der Cursor die<br />

Zeile vorab abgerufen hätte, würde der neue Wert <strong>für</strong> die Zeile 23 lauten<br />

und die Aktualisierung der anderen Transaktion verloren gehen.<br />

Ähnliche Einschränkungen sind maßgebend <strong>für</strong> die Empfindlichkeit. Weitere<br />

Hinweise finden Sie unter den Beschreibungen der einzelnen Cursortypen.<br />

Prefetch-Vorgänge und Mehrzeilen-Fetch-Vorgänge unterscheiden sich<br />

voneinander. Prefetch-Vorgänge können ohne explizite Anweisungen aus der<br />

Clientanwendung ausgeführt werden. Prefetch-Vorgänge rufen Zeilen aus<br />

dem Server in einen Puffer auf dem Client ab, machen diese Zeilen aber <strong>für</strong><br />

die Clientanwendung erst verfügbar, wenn die entsprechende Zeile von der<br />

Anwendung abgerufen wird.


Prefetch-<br />

Funktionen aus<br />

einer Anwendung<br />

steuern<br />

Kapitel 2 SQL in Anwendungen verwenden<br />

Standardmäßig führt die Clientbibliothek von <strong>Adaptive</strong> Server <strong>Anywhere</strong><br />

Prefetch-Vorgänge <strong>für</strong> mehrere Zeilen aus, wenn eine Anwendung eine<br />

einzelne Zeile abruft. Die Clientbibliothek von <strong>Adaptive</strong> Server <strong>Anywhere</strong><br />

speichert die zusätzlichen Zeilen in einem Puffer.<br />

Prefetch-Vorgänge verbessern die Performance durch die Reduktion des<br />

Client/Server-Verkehrs und erhöhen den Durchsatz, indem ohne separate<br />

Anforderung <strong>für</strong> einzelne Zeilen oder Zeilenblöcke viele Zeilen verfügbar<br />

gemacht werden.<br />

$ Weitere Hinweise zur Steuerung der Prefetch-Funktionen finden Sie<br />

unter "PREFETCH-Option" auf Seite 659 der Dokumentation ASA<br />

Datenbankadministration.<br />

♦ Durch die PREFETCH-Option wird gesteuert, ob Prefetch-Vorgänge<br />

durchgeführt werden oder nicht. Sie können die PREFETCH-Option <strong>für</strong><br />

eine einzelne Verbindung auf ON oder OFF setzen. Standardmäßig wird<br />

sie auf ON gesetzt.<br />

♦ In Embedded SQL können Sie die PREFETCH-Vorgänge auf<br />

Cursorbasis steuern, wenn Sie einen Cursor bei einem FETCH-Vorgang<br />

öffnen, indem Sie die BLOCK-Klausel verwenden.<br />

Die Anwendung kann eine maximale Anzahl von Zeilen festlegen, die in<br />

einem einzelnen FETCH-Vorgang vom Server enthalten sein dürfen,<br />

indem die BLOCK-Klausel angegeben wird. Beispiel: Wenn Sie 5<br />

Zeilen gleichzeitig abrufen und anzeigen, können Sie BLOCK 5<br />

verwenden. Wenn Sie BLOCK 0 festlegen, wird jeweils 1 Datensatz<br />

abgerufen, und ein FETCH RELATIVE 0 ruft die Zeile nochmals vom<br />

Server ab.<br />

Obwohl Sie die PREFETCH-Vorgänge auch durch einen<br />

Verbindungsparameter <strong>für</strong> die Anwendung ausschalten können, ist es<br />

effektiver, BLOCK=0 zu verwenden.<br />

$ Weitere Hinweise finden Sie unter "PREFETCH-Option" auf<br />

Seite 659 der Dokumentation ASA Datenbankadministration.<br />

♦ In Open Client können Sie das PREFETCH-Verhalten mit ct_cursor<br />

und CS_CURSOR_ROWS nach der Deklaration, aber vor dem Öffnen<br />

des Cursors steuern.<br />

Cursor-Empfindlichkeit und Isolationsstufen<br />

Sowohl Cursor-Empfindlichkeit als auch Isolationsstufen betreffen das<br />

Problem der Parallelität, allerdings auf unterschiedliche Weise.<br />

45


<strong>Adaptive</strong> Server <strong>Anywhere</strong>-Cursor<br />

46<br />

Indem Sie eine Isolationsstufe <strong>für</strong> eine Transaktion auswählen (häufig auf<br />

der Verbindungsebene), legen Sie fest, wann Sperren auf Zeilen in der<br />

Datenbank plaziert werden. Sperren verhindern, dass andere Transaktionen<br />

auf die Werte in der Datanbank zugreifen oder sie verändern.<br />

Indem Sie eine Cursor-Empfindlichkeit auswählen legen Sie fest, welche<br />

Änderungen <strong>für</strong> die Anwendung, die den Cursor verwendet, sichtbar sind.<br />

Indem Sie die Cursor-Empfindlichkeit einstellen legen Sie nicht fest, wann<br />

Sperren auf Zeilen in der Datenbank gelegt werden, und Sie schränken auch<br />

nicht die Änderungen ein, die an der Datenbank selbst durchgeführt werden.


Ergebnismengen beschreiben<br />

Kapitel 2 SQL in Anwendungen verwenden<br />

Einige Anwendungen bauen SQL-Anweisungen auf, die in der Anwendung<br />

nicht ausgeführt werden können. Anweisungen hängen manchmal von einer<br />

Antwort des Benutzers ab, sodass die Anwendung erst dann erfährt, welche<br />

Daten abzurufen sind, z.B. wenn eine Berichtsanwendung dem Benutzer die<br />

Möglichkeit gibt, die anzuzeigenden Spalten auszuwählen.<br />

In einem solchen Fall benötigt die Anwendung eine Methode, um<br />

Informationen über die Art der Ergebnismenge selbst sowie den Inhalt der<br />

Ergebnismenge zu erhalten. Die Informationen über die Art der<br />

Ergebnismenge werden als Deskriptor bezeichnet. Sie identifizieren die<br />

Datenstruktur einschließlich Anzahl und Typ der erwarteten Spalten. Wenn<br />

die Anwendung die Art der Ergebnismenge ermittelt hat, ist der Abruf des<br />

Inhalts ein einfacher Vorgang.<br />

Diese Ergebnismengen-Metadaten (Informationen über Art und Inhalt der<br />

Daten) werden mit Hilfe von Deskriptoren bearbeitet. Das Beziehen und<br />

Verwalten von Ergebnismengen-Metadaten wird als Beschreiben<br />

bezeichnet.<br />

Da Cursor im Allgemeinen Ergebnismengen produzieren, sind Deskriptoren<br />

und Cursor eng verknüpft, obwohl manche Schnittstellen die Verwendung<br />

von Deskriptoren vor dem Benutzer verbergen. Normalerweise gilt:<br />

Anweisungen, die Deskriptoren benötigen, sind entweder SELECT-<br />

Anweisungen oder gespeicherte Prozeduren, die Ergebnismengen<br />

zurückgeben.<br />

Ein Deskriptor wird bei einem cursorbasierten Vorgang folgendermaßen<br />

eingesetzt:<br />

1 Weisen Sie den Deskriptor zu. Dies kann implizit erfolgen, die explizite<br />

Zuweisung ist aber in manchen Schnittstellen zulässig.<br />

2 Bereiten Sie die Anweisung vor.<br />

3 Anweisung beschreiben. Wenn es sich bei der Anweisung um eine<br />

gespeicherte Prozedur oder um eine Anweisungsfolge handelt und die<br />

Ergebnismenge nicht durch eine Ergebnisklausel in der<br />

Prozedurdefinition definiert wird, sollte die Beschreibung nach dem<br />

Öffnen des Cursors erscheinen.<br />

4 Deklarieren Sie einen Cursor <strong>für</strong> die Anweisung und öffnen Sie ihn<br />

(Embedded SQL), oder führen Sie die Anweisung aus.<br />

5 Beziehen Sie den Deskriptor und ändern Sie erforderlichenfalls den<br />

zugewiesenen Bereich . Dies erfolgt oft implizit.<br />

6 Rufen Sie die Anweisungsergebnisse ab und und verarbeiten Sie sie.<br />

47


Ergebnismengen beschreiben<br />

Hinweise zur<br />

Implementierung<br />

48<br />

7 Heben Sie die Zuweisung des Deskriptors auf.<br />

8 Schließen Sie den Cursor.<br />

9 Löschen Sie die Anweisung . Einige Schnittstellen führen dies<br />

automatisch durch.<br />

♦ In Embedded SQL enthält eine SQLDA-(SQL Descriptor Area) Struktur<br />

die Deskriptor-Informationen.<br />

$ Weitere Hinweise finden Sie unter "Der SQL-Deskriptor-Bereich<br />

(SQLDA)" auf Seite 228.<br />

♦ In ODBC bietet ein Deskriptor-Handle, durch SQLAllocHandle<br />

zugewiesen, den Zugriff auf die Felder eines Deskriptors. Sie können<br />

diese Felder mit SQLSetDescRec, SQLSetDescField,<br />

SQLGetDescRec und SQLGetDescField verarbeiten.<br />

Alternativ können Sie SQLDescribeCol und SQLColAttributes<br />

verwenden, um Spalteninformationen zu beziehen.<br />

♦ In Open Client können Sie ct_dynamic <strong>für</strong> die Vorbereitung einer<br />

Anweisung und ct_describe zur Beschreibungder Ergebnismenge der<br />

Anweisung verwenden. Sie können aber auch ct_command benutzen,<br />

um eine SQL-Anweisung ohne vorherige Vorbereitung zu senden und<br />

dann ct_results benutzen, um die zurückgegebenen Zeilen nacheinander<br />

zu verarbeiten. Dies ist die normalerweise benutzte Vorgehensweise bei<br />

der Open Client-Anwendungsentwicklung.<br />

♦ In JDBC bietet die Klasse java.SQL.ResultSetMetaData<br />

Informationen über Ergebnismengen.<br />

♦ Sie können auch Deskriptoren verwenden, um Daten an die Engine zu<br />

senden (z.B. mit der INSERT-Anweisung), aber dies ist eine andere Art<br />

von Deskriptor als <strong>für</strong> die Ergebnismenge.<br />

$ Weitere Hinweise zu Eingabe- und Ausgabeparametern <strong>für</strong> die<br />

DESCRIBE-Anweisung finden Sie unter "DESCRIBE-Anweisung<br />

[ESQL]" auf Seite 426 der Dokumentation ASA SQL-Referenzhandbuch.


Kapitel 2 SQL in Anwendungen verwenden<br />

Transaktionen in Anwendungen steuern<br />

Transaktionen sind Zusammenstellungen einzelner SQL-Anweisungen.<br />

Entweder werden alle Anweisungen in der Transaktion ausgeführt oder<br />

keine. In diesem Abschnitt werden einige Aspekte der Transaktionen in<br />

Anwendungen behandelt.<br />

$ Weitere Hinweise zu Transaktionen entnehmen Sie dem Kapitel<br />

"Transaktionen und Isolationsstufen verwenden" auf Seite 99 der<br />

Dokumentation ASA SQL-Benutzerhandbuch.<br />

Automatisch oder manuell festschreiben<br />

Datenbank-Programmierschnittstellen können entweder im manuellen<br />

Festschreibemodus (manual commit) oder im automatischen<br />

Festschreibemodus (autocommit) operieren.<br />

♦ Manueller Festschreibemodus (manual commit) Operationen werden<br />

nur festgeschrieben, wenn Ihre Anwendung eine explizite<br />

Festschreibungsoperation durchführt oder der Datenbankserver eine<br />

automatische Festschreibung vollzieht, wie zum Beispiel beim<br />

Ausführen einer ALTER TABLE-Anweisung oder anderer<br />

Datendefinitionsanweisungen. Der manuelle Festschreibungsmodus<br />

wird manchmal auch verketteter Modus genannt.<br />

Um in Ihren Anwendungen Transaktionen wie verschachtelte<br />

Transaktionen und Savepoints verwenden zu können, müssen Sie im<br />

manuellen Festschreibemodus operieren.<br />

♦ Automatischer Festschreibemodus (autocommit) Jede Anweisung<br />

wird wie eine separate Transaktion behandelt. Die Wirkung ist dieselbe,<br />

wie wenn Sie eine COMMIT-Anweisung an das Ende jedes Ihrer<br />

Befehle anhängen. Der automatische Festschreibungsmodus wird<br />

manchmal auch unverketteter Modus genannt.<br />

Dieser Modus kann sich auf die Performance und das Verhalten Ihrer<br />

Anwendung auswirken. Verwenden Sie ihn nicht, wenn Ihre Anwendung<br />

Transaktionsintegrität erfordert.<br />

$ Hinweise über die Auswirkungen von AUTOCOMMIT auf die<br />

Performance finden Sie unter "Autocommit-Modus ausschalten" auf<br />

Seite 166 der Dokumentation ASA SQL-Benutzerhandbuch.<br />

49


Transaktionen in Anwendungen steuern<br />

AUTOCOMMIT-Verhalten steuern<br />

50<br />

Wie Sie das Festschreibungsverhalten Ihrer Anwendung steuern hängt von<br />

der verwendeten Programmierschnittstelle ab. Die Implementierung von<br />

AUTOCOMMIT kann, abhängig von der Schnittstelle, clientseitig oder<br />

serverseitig stattfinden.<br />

$ Weitere Hinweise finden Sie unter "Die AUTOCOMMIT-<br />

Implementierung" auf Seite 51.<br />

v So steuern Sie den AUTOCOMMIT-Modus (ODBC):<br />

♦ Standardmäßig arbeitet ODBC im AUTOCOMMIT-Modus. Die Art,<br />

wie Sie AUTOCOMMIT ausschalten, hängt davon ab, ob Sie ODBC<br />

direkt verwenden, oder ein Anwendungsentwicklungstool einsetzen.<br />

Wenn Sie direkt über die ODBC-Schnittstelle programmieren, stellen<br />

Sie das SQL_ATTR_AUTOCOMMIT-Verbindungsattribut ein.<br />

v So steuern Sie den AUTOCOMMIT-Modus (JDBC):<br />

♦ Standardmäßig arbeitet JDBC im AUTOCOMMIT-Modus. Um<br />

AUTOCOMMIT auszuschalten, verwenden Sie die setAutoCommit-<br />

Methode des Verbindungsobjekts:<br />

conn.setAutoCommit( false );<br />

v So steuern Sie den AUTOCOMMIT-Modus (Open Client):<br />

♦ Standardmäßig operiert eine Verbindung, die durch Open Client<br />

hergestellt wird, im AUTOCOMMIT-Modus. Sie können dieses<br />

Verhalten ändern, indem Sie die Datenbankoption CHAINED in Ihrer<br />

Anwendung auf ON setzen, indem Sie eine Anweisung wie die<br />

Folgende verwenden:<br />

SET OPTION CHAINED=’ON’<br />

v So steuern Sie den AUTOCOMMIT-Modus (Embedded SQL):<br />

♦ Standardmäßig operieren Embedded SQL-Anwendungen im manuellen<br />

Festschreibemodus. Um AUTOCOMMIT einzuschalten, stellen Sie die<br />

CHAINED-Datenbankoption auf OFF ein, indem Sie eine Anweisung<br />

wie die Folgende verwenden:<br />

SET OPTION CHAINED=’OFF’


Die AUTOCOMMIT-Implementierung<br />

Isolationsstufe steuern<br />

Kapitel 2 SQL in Anwendungen verwenden<br />

Der vorherige Abschnitt, "AUTOCOMMIT-Verhalten steuern" auf Seite 50,<br />

beschreibt, wie das AUTOCOMMIT-Verhalten von den einzelnen <strong>Adaptive</strong><br />

Server <strong>Anywhere</strong>-Programmierschnittstellen gesteuert werden kann.<br />

Abhängig von der verwendeten Schnittstelle und davon, wie Sie das<br />

AUTOCOMMIT-Verhalten steuern, verhält sich der AUTOCOMMIT-<br />

Modus leicht unterschiedlich.<br />

Der AUTOCOMMIT-Modus kann auf zwei Arten implementiert werden:<br />

♦ Clientseitiges AUTOCOMMIT Wenn eine Anwendung AUTOCOMMIT<br />

verwendet, sendet die Clientbibliothek eine COMMIT-Anweisung nach<br />

jeder ausgeführten SQL-Anweisung.<br />

<strong>Adaptive</strong> Server <strong>Anywhere</strong> verwendet clientseitiges AUTOCOMMIT<br />

<strong>für</strong> ODBC- und OLE DB-Anwendungen.<br />

♦ Serverseitiges AUTOCOMMIT Wenn eine Anwendung<br />

AUTOCOMMIT verwendet, gibt der Datenbankserver nach jeder SQL-<br />

Anweisung ein COMMIT aus. Dieses Verhalten wird, im Fall von JDBC<br />

implizit, durch die CHAINED-Datenbankoption gesteuert.<br />

<strong>Adaptive</strong> Server <strong>Anywhere</strong> verwendet serverseitiges AUTOCOMMIT<br />

<strong>für</strong> Embedded SQL-, JDBC- und Open Client-Anwendungen.<br />

Es gibt einen Unterschied zwischen clientseitigem und serverseitigem<br />

AUTOCOMMIT im Fall von zusammengesetzten Anweisungen wie<br />

gespeicherten Prozeduren und Triggern. Für den Client ist eine gespeicherte<br />

Prozedur eine einzelne Anweisung, und daher sendet AUTOCOMMIT eine<br />

einzelne COMMIT-Anweisung, nachdem die gesamte Prozedur ausgeführt<br />

wurde. Aus der Perspektive des Datenbankservers kann die gespeicherte<br />

Prozedur aus vielen SQL-Anweisungen bestehen, und daher gibt ein<br />

serverseitiges AUTOCOMMIT ein COMMIT nach jeder SQL-Anweisung<br />

innerhalb der Prozedur aus.<br />

Clientseitige und serverseitige Implementierungen nicht<br />

vermischen<br />

Sie sollten in Ihrer ODBC- oder OLE DB-Anwendung die Verwendung<br />

der CHAINED-Option nicht mit AUTOCOMMIT kombinieren.<br />

Sie können die Isolationsstufe einer aktuellen Verbindung mit der<br />

Datenbankoption ISOLATION_LEVEL einstellen.<br />

51


Transaktionen in Anwendungen steuern<br />

Cursor und Transaktionen<br />

ROLLBACK und<br />

Cursor<br />

Savepoints<br />

Cursor und<br />

Isolationsstufe<br />

52<br />

Einige Schnittstellen, wie ODBC, ermöglichen das Setzen der Isolationsstufe<br />

<strong>für</strong> eine Verbindung beim Aufbau. Diese Isolationsstufe kann später mit der<br />

Datenbankoption ISOLATION_LEVEL zurückgesetzt werden.<br />

Im Allgemeinen wird ein Cursor geschlossen, wenn ein COMMIT<br />

ausgeführt wird. Es gibt zwei Ausnahmen <strong>für</strong> dieses Verhalten.<br />

♦ Die Datenbankoption CLOSE_ON_ENDTRANS ist auf OFF gesetzt.<br />

♦ Ein Cursor wird mit WITH HOLD geöffnet, was der Standard bei Open<br />

Client und JDBC ist.<br />

Trifft einer dieser beiden Fälle zu, bleibt der Cursor bei COMMIT geöffnet.<br />

Beim Zurücksetzen einer Transaktion wird der Cursor geschlossen, außer<br />

wenn er mit WITH HOLD geöffnet wurde. Dem Inhalt eines Cursors können<br />

Sie nach einem Zurücksetzen nicht vertrauen.<br />

Der projektierte ISO SQL3-Standard legt fest, dass bei einem Zurücksetzen<br />

alle Cursor geschlossen werden sollen. Sie können dieses Verhalten<br />

erzwingen, indem Sie die Option<br />

ANSI_CLOSE_CURSORS_AT_ROLLBACK auf ON setzen.<br />

Wenn eine Transaktion bis zu einem Savepoint zurückgesetzt wird und<br />

ANSI_CLOSE_CURSORS_AT_ROLLBACK auf ON gesetzt ist, wird jeder<br />

nach dem SAVEPOINT geöffnete Cursor geschlossen (sogar die Cursor, die<br />

mit WITH HOLD geöffnet wurden).<br />

Sie können die Isolationsstufe <strong>für</strong> eine Verbindung während einer<br />

Transaktion setzen, indem Sie die Anweisung SET OPTION verwenden, um<br />

die Option ISOLATION_LEVEL zu ändern. Diese Änderung wirkt sich<br />

jedoch nur auf geschlossene Cursor aus.


KAPITEL 3<br />

Einführung in Java <strong>für</strong> Datenbanken<br />

Über dieses<br />

Kapitel<br />

Inhalt<br />

In diesem Kapitel wird erklärt, warum es sinnvoll ist, Java in einer<br />

Datenbank zu verwenden.<br />

Der <strong>Adaptive</strong> Server <strong>Anywhere</strong> ist eine Laufzeit-Umgebung <strong>für</strong> Java. Java<br />

bietet eine natürliche Erweiterung <strong>für</strong> SQL und verwandelt <strong>Adaptive</strong> Server<br />

<strong>Anywhere</strong> in eine Plattform <strong>für</strong> Unternehmensanwendungen der nächsten<br />

Generation.<br />

Thema Seite<br />

Einleitung 54<br />

Fragen und Antworten zu Java in der Datenbank 57<br />

Ein Java-Seminar 64<br />

Die Laufzeitumgebung <strong>für</strong> Java in der Datenbank 75<br />

Praktische Einführung: Eine Übung mit Java in der Datenbank 84<br />

53


Einleitung<br />

Einleitung<br />

Getrennt<br />

lizenzierbare<br />

Komponente<br />

Der SQLJ-<br />

Standard<br />

54<br />

<strong>Adaptive</strong> Server <strong>Anywhere</strong> ist eine Laufzeit-Umgebung <strong>für</strong> Java. Das<br />

bedeutet, dass Java-Klassen im Datenbankserver ausgeführt werden können.<br />

Durch die Integration einer Laufzeit-Umgebung <strong>für</strong> Java-Klassen in den<br />

Datenbankserver werden neue, vielfältige Wege <strong>für</strong> die Verwaltung und<br />

Speicherung von Daten und Logik eröffnet.<br />

Java in der Datenbank bietet folgende Möglichkeiten:<br />

♦ Sie können Java-Komponenten in den verschiedenen Schichten Ihrer<br />

Anwendung verwenden (Client, mittlere Schicht oder Server) und<br />

überall einsetzen, wo es <strong>für</strong> Sie am sinnvollsten ist. <strong>Adaptive</strong> Server<br />

<strong>Anywhere</strong> wird damit zu einer Plattform <strong>für</strong> verteilte<br />

Informationsverarbeitung.<br />

♦ Java bietet mehr Möglichkeiten als gespeicherte Prozeduren <strong>für</strong> die<br />

Integration von Logik in die Datenbank.<br />

♦ Java-Klassen werden zu reichhaltigen, benutzerdefinierten Datentypen.<br />

♦ Die Methoden der Java-Klassen bieten neue Funktionen <strong>für</strong> den Zugriff<br />

aus SQL.<br />

♦ Java kann in der Datenbank benutzt werden, ohne dass die Integrität, die<br />

Sicherheit und die Robustheit der Datenbank verletzt werden.<br />

Java in der Datenbank ist eine Komponente, die separat lizenziert werden<br />

kann und vor der Installation bestellt werden muss. Die Bestellung kann mit<br />

der betreffenden Karte im SQL <strong>Anywhere</strong> Studio-Paket oder über<br />

http://www.sybase.com/detail?id=1015780 erfolgen.<br />

Java in der Datenbank basiert auf den vorgeschlagenen Standards SQLJ Part<br />

1 und SQLJ Part 2. SQLJ Part 1 liefert Spezifikationen zum Aufrufen von<br />

statischen Java-Methoden als gespeicherte SQL-Prozeduren und<br />

benutzerdefinierte Funktionen. SQLJ Part 2 bietet Spezifikationen <strong>für</strong> den<br />

Einsatz von Java-Klassen als in SQL geschriebene benutzerdefinierte<br />

Datentypen.<br />

Hinweise zu Java in der Datenbank<br />

Java ist eine relativ neue Programmiersprache, mit einer wachsenden, aber<br />

immer noch limitierten Wissensbasis. Diese Dokumentation wurde <strong>für</strong> ein<br />

breites Spektrum von Java-Entwicklern geschrieben und unterstützt daher<br />

alle, von erfahrenen Entwicklern bis zu fachlich nicht vorgebildeten Lesern,<br />

die die Sprache, ihre Möglichkeiten, ihre Syntax und ihre<br />

Einsatzmöglichkeiten nicht kennen.


Java-<br />

Dokumentation<br />

Kapitel 3 Einführung in Java <strong>für</strong> Datenbanken<br />

Leser, <strong>für</strong> die Java nichts Neues mehr ist, finden in diesem Kapitel wertvolle<br />

Hinweise <strong>für</strong> den Einsatz von Java in einer Datenbank. <strong>Adaptive</strong> Server<br />

<strong>Anywhere</strong> erweitert nicht nur die Möglichkeiten der Datenbank mit Java,<br />

sondern auch die Möglichkeiten von Java mit der Datenbank.<br />

In der nachstehenden Tabelle finden Sie Hinweise zur Dokumentation zum<br />

Thema Java in der Datenbank.<br />

Titel Verwendung<br />

"Einführung in Java <strong>für</strong><br />

Datenbanken" auf Seite 53<br />

(dieses Kapitel)<br />

"Java in der Datenbank<br />

benutzen" auf Seite 93<br />

"Datenzugriff über JDBC" auf<br />

Seite 143<br />

"Fehlersuche in der<br />

Datenbanklogik" auf<br />

Seite 635 der Dokumentation<br />

ASA SQL-Benutzerhandbuch<br />

<strong>Adaptive</strong> Server <strong>Anywhere</strong><br />

Referenzhandbuch<br />

Referenzhandbuch <strong>für</strong> die<br />

Java API von Sun<br />

Thinking in Java Thinking in<br />

Java by Bruce Eckel.<br />

Java-Dokumentation benutzen<br />

Java-Konzepte und Anwendungsmethoden in<br />

<strong>Adaptive</strong> Server <strong>Anywhere</strong><br />

Praktische Anleitung zum Einsatz von Java in<br />

der Datenbank<br />

Zugriff auf Daten aus Java-Klassen,<br />

einschließlich verteilter<br />

Informationsverarbeitung<br />

Testen und Fehlersuche von Java-Code <strong>für</strong> den<br />

Einsatz in der Datenbank<br />

Das Referenzhandbuch enthält Informationen<br />

zu den SQL-Erweiterungen, die Java in der<br />

Datenbank unterstützen.<br />

Online-<strong>Handbuch</strong> <strong>für</strong> Java API-Klassen, Felder<br />

und Methoden. Nur als Windows-Hilfedatei<br />

verfügbar.<br />

Online-Buch, mit dem man das Programmieren<br />

in Java lernen kann. Es wird im Adobe PDF<br />

Format im Unterverzeichnis<br />

Samples\ASA\Java des <strong>Adaptive</strong> Server<br />

<strong>Anywhere</strong>-Installationsverzeichnisses<br />

bereitgestellt.<br />

Die folgende Tabelle ist ein Wegweiser <strong>für</strong> die Java-Dokumentationen, die<br />

Sie je nach Ihren Interessen und Vorkenntnissen benutzen können. Die<br />

Tabelle ist nur als Richtlinie gedacht und soll Ihre Bemühungen, mehr über<br />

Java in der Datenbank zu lernen, unterstützen.<br />

55


Einleitung<br />

56<br />

Gesuchtes Thema Textstelle<br />

Sie benötigen eine Einführung in<br />

objektorientiertes Programmieren<br />

Sie benötigen eine Erklärung von<br />

Themen wie instanziert, Feld und<br />

Klassenmethode.<br />

Sie sind ein Java-Entwickler, der gleich<br />

mit der praktischen Arbeit beginnen will.<br />

Sie wollen die Hauptmerkmale von Java<br />

in der Datenbank kennen lernen.<br />

Sie wollen herausfinden, wie der Zugriff<br />

auf Daten aus Java erfolgt.<br />

Sie wollen eine Datenbank <strong>für</strong> Java<br />

vorbereiten.<br />

Sie brauchen eine komplette Liste der<br />

unterstützten Java APIs.<br />

Sie versuchen, eine Java API-Klasse zu<br />

verwenden und benötigen Java-<br />

Referenzinformationen.<br />

Sie wollen ein Beispiel <strong>für</strong> verteilte<br />

Informationsverarbeitung sehen.<br />

"Ein Java-Seminar" auf Seite 64<br />

Thinking in Java von Bruce Eckel.<br />

"Ein Java-Seminar" auf Seite 64<br />

"Die Laufzeitumgebung <strong>für</strong> Java in<br />

der Datenbank" auf Seite 75<br />

"Praktische Einführung: Eine Übung<br />

mit Java in der Datenbank" auf<br />

Seite 84<br />

"Fragen und Antworten zu Java in der<br />

Datenbank" auf Seite 57<br />

"Datenzugriff über JDBC" auf<br />

Seite 143<br />

"Datenbank <strong>für</strong> Java aktivieren" auf<br />

Seite 97<br />

"Java-Klassen-Datentypen" auf<br />

Seite 86 der Dokumentation ASA<br />

SQL-Referenzhandbuch<br />

Online-<strong>Handbuch</strong> <strong>für</strong> Java API-<br />

Klassen, Felder und Methoden (nur<br />

als Windows-Online-Hilfe)<br />

"Verteilte Anwendungen erstellen"<br />

auf Seite 174


Kapitel 3 Einführung in Java <strong>für</strong> Datenbanken<br />

Fragen und Antworten zu Java in der Datenbank<br />

In diesem Abschnitt werden die Hauptmerkmale von Java in der Datenbank<br />

beschrieben.<br />

Die wichtigsten Funktionen von Java in der Datenbank<br />

Detaillierte Erläuterungen aller nachstehenden Punkte sind in den folgenden<br />

Abschnitten zu finden.<br />

♦ Sie können Java auf dem Datenbankserver ausführen Eine interne<br />

Java Virtual Machine (VM) führt den Java-Code auf dem<br />

Datenbankserver aus.<br />

♦ Sie können Java aus SQL aufrufen Sie können Java-Funktionen<br />

(Methoden) aus SQL-Anweisungen ausführen. Java-Methoden bieten<br />

eine leistungsfähigere Sprache als in SQL geschriebene gespeicherte<br />

Prozeduren, wenn Sie Ihrer Datenbank logische Elemente hinzufügen<br />

wollen.<br />

♦ Sie können aus Java auf Daten zugreifen Ein interner JDBC-Treiber<br />

ermöglicht den Zugriff auf Daten aus Java.<br />

♦ Sie können die Fehlersuche <strong>für</strong> Java in der Datenbank vornehmen<br />

Sie können den <strong>Sybase</strong> Java Debugger verwenden, um Ihre Java-<br />

Klassen in der Datenbank zu testen und auf Fehler zu durchsuchen.<br />

♦ Sie können Java-Klassen als Datentypen verwenden Jede in einer<br />

Datenbank installierte Java-Klasse wird als Datentyp verfügbar, der <strong>für</strong><br />

eine Spalte in einer Tabelle oder einer Variablen verwendet werden<br />

kann.<br />

♦ Sie können Java-Objekte in Tabellen speichern Eine Instanz einer<br />

Java-Klasse (ein Java-Objekt) kann als Wert in einer Tabelle gespeichert<br />

werden. Java-Objekte können in eine Tabelle eingefügt, SELECT-<br />

Anweisungen in den Feldern und Methoden von in Tabellen<br />

gespeicherten Objekten ausgeführt, und Java-Objekte aus einer Tabelle<br />

abgerufen werden.<br />

Mit diesen Möglichkeiten wird <strong>Adaptive</strong> Server <strong>Anywhere</strong> zu einer<br />

objekt-relationalen Datenbank, die Objekte unterstützt, gleichzeitig aber<br />

die bestehenden relationalen Funktionen nicht beeinträchtigt.<br />

♦ SQL wird bewahrt Der Einsatz von Java ändert das Verhalten<br />

bestehender SQL-Anweisungen oder andere Aspekte des nicht mit Java<br />

verbundenen Verhaltens der relationalen Datenbank nicht.<br />

57


Fragen und Antworten zu Java in der Datenbank<br />

Java-Instruktionen in der Datenbank speichern<br />

58<br />

Java ist eine objektorientierte Sprache, ihre Anweisungen (Quellcode)<br />

werden daher in Form von Klassen geliefert. Um Java in einer Datenbank<br />

auszuführen, schreiben Sie die Java-Instruktionen außerhalb der Datenbank<br />

in kompilierte Klassen (Bytecode), bei denen es sich um Binärdateien mit<br />

Java-Instruktionen handelt.<br />

Sie installieren diese kompilierten Klassen dann in einer Datenbank. Nach<br />

der Installation können Sie diese Klassen im Datenbankserver ausführen.<br />

<strong>Adaptive</strong> Server <strong>Anywhere</strong> ist eine Laufzeit-Umgebung <strong>für</strong> Java-Klassen,<br />

keine Java-Entwicklungsumgebung. Sie brauchen eine Java-<br />

Entwicklungsumgebung, wie <strong>Sybase</strong> PowerJ oder Java Development Kit von<br />

Sun Microsystems, um Java-Codes zu schreiben und zu kompilieren.<br />

$ Weitere Hinweise finden Sie unter "Java-Klassen in einer Datenbank<br />

installieren" auf Seite 103.<br />

Java in einer Datenbank ausführen<br />

Unterschiede zu<br />

einer eigenständigen<br />

VM<br />

<strong>Adaptive</strong> Server <strong>Anywhere</strong> enthält eine Java Virtual Machine (VM), die in<br />

der Datenbankumgebung läuft. Die <strong>Sybase</strong> Java VM interpretiert kompilierte<br />

Java-Instruktionen und führt sie im Datenbankserver aus.<br />

Zusätzlich zur VM wurde der SQL-Abfrageprozessor im Datenbankserver<br />

erweitert, so dass er in der VM Aufrufe durchführen kann, um Java-<br />

Instruktionen auszuführen. Er kann auch Abfragen von der VM verarbeiten,<br />

um den Datenzugriff aus Java zu aktivieren.<br />

Es gibt einen Unterschied zwischen dem Ausführen von Java-Codes mit<br />

einer Standard-VM wie Sun Java VM java.exe und dem Ausführen von<br />

Java-Codes in einer Datenbank. Die Sun VM wird von einer Befehlszeile aus<br />

gestartet, während die Java VM von <strong>Adaptive</strong> Server <strong>Anywhere</strong> jederzeit<br />

verfügbar ist, um einen Java-Vorgang auszuführen, wenn dies als Teil der<br />

Ausführung einer SQL-Anweisung erforderlich ist.<br />

Auf den <strong>Sybase</strong> Java-Interpreter können Sie extern nicht zugreifen. Er wird<br />

nur benutzt, wenn die Ausführung einer SQL-Anweisung einen Java-<br />

Vorgang erforderlich macht. Der Datenbankserver startet die VM<br />

automatisch, wenn sie benötigt wird: Sie brauchen keine ausdrücklichen<br />

Bedienungsmaßnahmen auszuführen, um die VM zu starten oder zu stoppen.


Vorteile von Java<br />

Kapitel 3 Einführung in Java <strong>für</strong> Datenbanken<br />

Java bietet eine Reihe von Merkmalen, die <strong>für</strong> den Einsatz in Datenbanken<br />

besonders gut geeignet sind:<br />

♦ Präzise Fehlerprüfung bei der Kompilierung<br />

♦ Integrierte Fehlerbehandlung mit einer gut definierten Methode <strong>für</strong> die<br />

Fehlerbehandlung<br />

♦ Integrierte Sammlung von Abfalldaten (Speicher wird freigesetzt)<br />

♦ Eliminierung vieler fehleranfälliger Programmiertechniken<br />

♦ Leistungsfähige Sicherheitsfunktionen<br />

♦ Java-Code wird interpretiert, daher werden keine Vorgänge ausgeführt,<br />

die von der VM nicht akzeptiert werden<br />

Plattformen, die Java in der Datenbank unterstützen<br />

Java in der Datenbank wird auf Windows CE nicht unterstützt. Wohl aber<br />

unter Windows-Betriebssystemen, UNIX und NetWare.<br />

Java und SQL zusammen einsetzen<br />

Ein Grundsatz <strong>für</strong> das Konzept von Java in der Datenbank besteht darin, dass<br />

damit eine natürliche, offene Erweiterung <strong>für</strong> bestehende SQL-Funktionen<br />

gegeben ist.<br />

♦ Java-Vorgänge werden aus SQL aufgerufen <strong>Sybase</strong> hat den Bereich<br />

der SQL-Ausdrücke erweitert, sodass Eigenschaften und Methoden von<br />

Java-Objekten einbezogen werden können und damit der Einbau von<br />

Java-Vorgängen in eine SQL-Anweisung möglich ist.<br />

♦ Java-Klassen werden Domänen Sie speichern Java-Klassen mit<br />

denselben SQL-Anweisungen wie <strong>für</strong> normale SQL-Datentypen.<br />

Sie können viele der Klassen verwenden, die Teil der Java API sind, so wie<br />

sie mit dem Java Development Kit von Sun Microsystems geliefert werden.<br />

Sie können auch Klassen verwenden, die von Java-Entwicklern erstellt und<br />

kompiliert wurden.<br />

59


Fragen und Antworten zu Java in der Datenbank<br />

Beschreibung der Java API<br />

Zugriff auf Java aus SQL<br />

60<br />

Die Java-Programmierschnittstelle (Java Application Programmer’s<br />

Interface, API) ist eine Gruppe von Klassen, die von Sun Microsystems<br />

erstellt wurde. Sie bietet eine Reihe von Basisfunktionen, die von Java-<br />

Entwicklern benutzt und erweitert werden können. Sie bilden den Kern aller<br />

Einsatzmöglichkeiten von Java.<br />

Die Java API bietet aus sich heraus zahlreiche Möglichkeiten und<br />

Funktionen. Ein Großteil der Java API kann in jede Datenbank integriert<br />

werden, die <strong>für</strong> die Arbeit mit Java-Programmcode eingerichtet wurde. Dazu<br />

gehört die Mehrzahl der nicht-visuellen Klassen aus der Java API, die<br />

Entwicklern, welche schon mit dem Java Development Kit (JDK) von Sun<br />

Microsystems arbeiten, bekannt sein dürften.<br />

$ Weitere Hinweise über unterstützte Java-APIs finden Sie unter<br />

"Unterstützte Java-Pakete" auf Seite 87 der Dokumentation ASA SQL-<br />

Referenzhandbuch.<br />

Die Java API kann nicht nur in Klassen verwendet werden, sondern auch in<br />

gespeicherten Prozeduren und SQL-Anweisungen. Sie können die Java API-<br />

Klassen als Erweiterungen zu den verfügbaren Funktionen behandeln, die<br />

von SQL zur Verfügung gestellt werden.<br />

Beispiel: Die SQL-Funktion PI(*) gibt den Wert <strong>für</strong> pi zurück. Die Java API-<br />

Klasse java.lang.Math hat ein paralleles Feld namens PI, das denselben<br />

Wert zurückgibt. Die Klasse java.lang.Math hat aber auch ein Feld namens<br />

E, das die Basis von natürlichen Logarithmen zurückgibt, sowie eine<br />

Methode, die die Restoperation auf zwei Argumente gemäß dem Standard<br />

IEEE 754 durchführt.<br />

Andere Bestandteile der Java API bieten weitere, zusätzliche Möglichkeiten.<br />

Beispiel: java.util.Stack generiert eine Warteschlange nach dem Last-In-<br />

First-Out-Prinzip, die eine Liste sortiert speichern kann,<br />

java.util.HashTable wird benutzt, um Werte Schlüsseln zuzuordnen,<br />

java.util.StringTokenizer unterteilt eine Zeichenfolge in einzelne<br />

Worteinheiten.<br />

$ Weitere Hinweise finden Sie unter "Java-Objekte einfügen,<br />

aktualisieren und löschen" auf Seite 111.


Unterstützte Java-Klassen<br />

Kapitel 3 Einführung in Java <strong>für</strong> Datenbanken<br />

Die Datenbank unterstützt nicht alle Java API-Klassen. Einige Klassen,<br />

beispielsweise das Paket java.awt, das Bestandteile der Benutzerschnittstelle<br />

<strong>für</strong> Anwendungen enthält, ist in einem Datenbankserver nicht sinnvoll.<br />

Andere Klassen, einschließlich Teile der Klasse java.io, übernehmen<br />

Schreibfunktionen auf der Festplatte, was in einer Datenbankserver-<br />

Umgebung ebenfalls nicht unterstützt wird.<br />

$ Weitere Hinweise über unterstützte und nicht unterstützte Klassen<br />

finden Sie unter "Unterstützte Java-Pakete" auf Seite 87 der Dokumentation<br />

ASA SQL-Referenzhandbuch und "Nicht-unterstützte Java-Pakete und<br />

Klassen" auf Seite 88 der Dokumentation ASA SQL-Referenzhandbuch.<br />

Eigene Java-Klassen in Datenbanken einsetzen<br />

Sie können Ihre eigenen Java-Klassen in einer Datenbank installieren.<br />

Beispiel: Ein Entwickler könnte die benutzerdefinierte Klasse "Mitarbeiter"<br />

oder "Verpackung" konzipieren, in Java schreiben und mit einem Java-<br />

Compiler kompilieren.<br />

Von einem Benutzer erstellte Java-Klassen können Informationen über den<br />

Gegenstand der Klasse und Rechnerlogik enthalten. Nachdem sie in einer<br />

Datenbank installiert wurden, stellt <strong>Adaptive</strong> Server <strong>Anywhere</strong> diese Klassen<br />

in allen Teilen und Vorgängen der Datenbank zur Verfügung und führt ihre<br />

Funktionen (in der Form von Klassen- oder Instanzenmethoden) genauso<br />

schnell und einfach aus wie gespeicherte Prozeduren.<br />

Java-Klassen und gespeicherte Prozeduren unterscheiden sich<br />

Java-Klassen unterscheiden sich von gespeicherten Prozeduren. Während<br />

gespeicherte Prozeduren in SQL geschrieben sind, bieten Java-Klassen<br />

eine leistungsfähigere Sprache und können aus Clientanwendungen genau<br />

so leicht aufgerufen werden wie gespeicherte Prozeduren.<br />

Wenn eine Java-Klasse in einer Datenbank installiert wird, steht sie als neue<br />

Domäne zur Verfügung. Eine Java-Klasse kann in jeder Situation verwendet<br />

werden, in der integrierte SQL-Datentypen benutzt werden können: Als<br />

Spaltentyp in einer Tabelle oder als Variablentyp.<br />

Beispiel: Wenn eine Klasse namens Adresse in einer Datenbank installiert<br />

wurde, kann eine Spalte in einer Tabelle namens Adr den Typ Adresse<br />

haben, was bedeutet, dass nur auf der Klasse Adresse basierende Objekte als<br />

Zeilenwerte <strong>für</strong> diese Spalte gespeichert werden können.<br />

$ Weitere Hinweise finden Sie unter "Java-Klassen in einer Datenbank<br />

installieren" auf Seite 103.<br />

61


Fragen und Antworten zu Java in der Datenbank<br />

Mit Java auf Daten zugreifen<br />

62<br />

Die JDBC-Schnittstelle ist ein Industriestandard, der speziell <strong>für</strong> den Zugriff<br />

auf Datenbanksysteme entwickelt wurde. Die JDBC-Klassen sollen folgende<br />

Aufgaben ermöglichen: Verbindung mit einer Datenbank, Anforderung von<br />

Daten mit SQL-Anweisungen und Rücklieferung von Ergebnismengen, die<br />

in der Clientanwendung verarbeitet werden können.<br />

Normalerweise werden die JDBC-Klassen von einer Clientanwendung<br />

verwendet, und der Datenbank-Systemlieferant stellt einen JDBC-Treiber zur<br />

Verfügung, mit dem JDBC-Klassen eine Verbindung herstellen können.<br />

Sie können sich aus einer Clientanwendung mit <strong>Adaptive</strong> Server <strong>Anywhere</strong><br />

über JDBC verbinden, indem Sie jConnect oder eine JDBC/ODBC-Brücke<br />

benutzen. <strong>Adaptive</strong> Server <strong>Anywhere</strong> bietet auch einen internen JDBC-<br />

Treiber, der es in einer Datenbank installierten Java-Klassen ermöglicht,<br />

JDBC-Klassen zu verwenden, die SQL-Anweisungen ausführen.<br />

$ Weitere Hinweise finden Sie unter "Datenzugriff über JDBC" auf<br />

Seite 143.<br />

Klassen vom Client auf einen Server verschieben<br />

Verteilte Anwendungen erstellen<br />

Sie können Java-Klassen erstellen, die zwischen verschiedenen Ebenen einer<br />

Unternehmensanwendung verschoben werden können. Dieselbe Java-Klasse<br />

kann in die Clientanwendung, eine mittlere Schicht oder die Datenbank<br />

integriert werden - also an der Stelle, an der sie am sinnvollsten eingesetzt<br />

werden kann.<br />

Eine Klasse, die Geschäftslogik, Daten oder eine Kombination von beiden<br />

enthält, kann auf jede Ebene des Unternehmenssystems, auch auf den Server,<br />

verschoben werden, so dass Sie die vorhandenen Ressourcen optimal<br />

einsetzen können. Die Betreiber von unternehmensweiten Systemen können<br />

daher mit einer einzigen Programmiersprache in einer mehrschichtigen<br />

Architektur mit bisher nie gekannter Flexibilität eigene Anwendungen<br />

entwickeln.<br />

Sie können eine Anwendung erstellen, bei der einige Teile in der Datenbank<br />

arbeiten, andere auf dem Client-System. Sie können Java-Objekte vom<br />

Server an den Client übergeben und umgekehrt, genauso wie Sie SQL-Daten<br />

wie Zeichendaten und numerische Werte übergeben können.<br />

$ Weitere Hinweise finden Sie unter "Verteilte Anwendungen erstellen"<br />

auf Seite 174.


Einschränkungen <strong>für</strong> Java in der Datenbank<br />

Kapitel 3 Einführung in Java <strong>für</strong> Datenbanken<br />

<strong>Adaptive</strong> Server <strong>Anywhere</strong> ist eine Laufzeit-Umgebung <strong>für</strong> Java-Klassen,<br />

keine Java-Entwicklungsumgebung.<br />

Sie können folgende Aufgaben in einer Datenbank nicht durchführen:<br />

♦ Klasse-Quelldaten bearbeiten (*.java-Dateien).<br />

♦ Java-Klassen-Quelldateien kompilieren (*.java-Dateien).<br />

♦ Java APIs ausführen, die nicht unterstützt werden, wie z.B. Applets und<br />

visuelle Klassen<br />

♦ Java-Methoden ausführen, die die Ausführung nativer Methoden<br />

voraussetzen. Alle Benutzerklassen, die in einer Datenbank installiert<br />

sind, müssen 100% Java sein.<br />

Die in <strong>Adaptive</strong> Server <strong>Anywhere</strong> benutzten Klassen müssen mit einem<br />

Java-Entwicklungstool geschrieben und kompiliert werden. Danach werden<br />

sie in einer Datenbank installiert, um dort getestet, auf Fehler geprüft und<br />

vom Endbenutzer benutzt zu werden.<br />

63


Ein Java-Seminar<br />

Ein Java-Seminar<br />

Erklärung von Java-Klassen<br />

64<br />

In diesem Abschnitt werden die wichtigsten Java-Konzepte vorgestellt.<br />

Nachdem Sie sich diesen Abschnitt durchgelesen haben, sollten Sie in der<br />

Lage sein, Java-Code zu prüfen, wie z.B. einfache Klassendefinitionen oder<br />

den Aufruf einer Methode, bzw. gegebenenfalls verstehen, warum etwaige<br />

Probleme auftreten.<br />

Java-Beispielverzeichnis<br />

Alle Klassen, die als Beispiele in diesem Dokument verwendet werden,<br />

sind im Verzeichnis mit den Java-Beispielen zu finden, nämlich im<br />

Unterverzeichnis Samples\ASA\Java zum Verzeichnis von <strong>Adaptive</strong><br />

Server <strong>Anywhere</strong>.<br />

Zwei Dateien stehen <strong>für</strong> jedes Java-Klassen-Beispiel: Java-Quellcode und<br />

kompilierte Klasse. Sie können die kompilierte Version der Beispiele von<br />

Java-Klassen in einer Datenbank sofort und ohne Änderung installieren.<br />

Eine Java-Klasse kombiniert Daten und Funktionen: Die Möglichkeit zur<br />

Speicherung von Informationen und die Fähigkeit zur Durchführung von<br />

Rechenvorgängen. Eine Klasse kann man als eine Entität, also eine abstrakte<br />

Darstellung von Dingen sehen.<br />

Eine "Rechnungsklasse” könnte beispielsweise so entworfen werden, dass<br />

sie eine normale Rechnung imitiert, wie sie im täglichen Geschäftsverkehr<br />

verwendet wird. Eine Rechnung enthält bestimmte Informationen (z.B. die<br />

verrechneten Artikel, die Rechnungsadresse, Rechnungsdatum, Zahlbetrag<br />

und Fälligkeit) - dasselbe gilt <strong>für</strong> die Instanz einer Rechnungsklasse. Klassen<br />

speichern Daten in Feldern.<br />

Eine Klasse beschreibt nicht nur Daten, sondern kann auch Berechnungen<br />

vornehmen und logische Vorgänge durchführen. Die Rechnungsklasse<br />

könnte beispielsweise die Steuer <strong>für</strong> eine Liste von Rechnungsposten <strong>für</strong><br />

jedes Rechnungsobjekt errechnen und der Zwischensumme hinzufügen, um<br />

damit die Gesamtrechnungssumme auszuwerfen, ohne dass ein Eingriff des<br />

Benutzers erforderlich wäre. Eine solche Klasse würde auch da<strong>für</strong> sorgen,<br />

dass alle benötigten Informationselemente in die Rechnung eingefügt<br />

werden, und könnte sogar automatisch anzeigen, ob die Zahlung fällig ist<br />

oder schon teilweise geleistet wurde. Berechnungen und andere logische<br />

Vorgänge werden durch die Methoden einer Klasse ausgeführt.


Beispiel<br />

Unterklassen in Java<br />

Kapitel 3 Einführung in Java <strong>für</strong> Datenbanken<br />

Der folgende Java-Code deklariert eine Klasse namens "Invoice". Diese<br />

Klassendeklaration würde in einer Datei namens Invoice.java gespeichert und<br />

dann mit einem Java-Compiler in eine Java-Klasse kompiliert.<br />

Java-Klassen kompilieren<br />

Beim Kompilieren des Quellcodes <strong>für</strong> eine Java-Klasse wird eine neue<br />

Datei mit demselben Namen wie die Quelldatei erzeugt, jedoch mit einer<br />

anderen Erweiterung. Durch das Kompilieren von Invoice.java wird dabei<br />

eine Datei namens Invoice.class erstellt, die in einer Java-Anwendung<br />

verwendet und durch eine Java VM ausgeführt werden kann.<br />

Das Sun JDK Tool <strong>für</strong> das Kompilieren der Klassendeklarationen ist<br />

javac.exe.<br />

public class Invoice {<br />

// Bis jetzt kann diese Klasse nichts und hat auch<br />

keine Daten<br />

}<br />

Auf das Schlüsselwort class folgt der Name der Klasse. Es gibt eine<br />

geöffnete und eine geschlossene geschweifte Klammer. Alles, was<br />

dazwischen liegt, also z.B. Felder und Methoden, wird zu einem Teil der<br />

Klasse.<br />

Grundsätzlich gibt es keinen Java-Code außerhalb von Klassen. Sogar die<br />

Java-Prozedur, die von einem Java-Interpreter automatisch ausgeführt wird,<br />

um andere Objekte zu erstellen - die Hauptmethode (main), die oft der<br />

Beginn Ihrer Anwendung ist - befindet sich selbst wieder innerhalb einer<br />

Klassendeklaration.<br />

Sie können Klassen als Unterklassen (subclasses) anderer Klassen<br />

definieren. Eine Klasse, die als Unterklasse einer anderen Klasse fungiert,<br />

kann die Felder und Methoden ihrer übergeordneten Klasse verwenden: Dies<br />

wird als Vererbung bezeichnet. Sie können zusätzliche Methoden und<br />

Felder definieren, die nur <strong>für</strong> die Unterklasse gelten, und die Bedeutung der<br />

geerbten Felder und Methoden verändern.<br />

Java ist eine Programmiersprache mit einer Einzelhierarchie. Das bedeutet,<br />

dass alle Klassen, die Sie erstellen oder benutzen, von einer Klasse erben.<br />

Das bedeutet weiterhin, dass die Klassen der niedrigsten Ebene (also in der<br />

Hierarchie weiter oben angesiedelt) vorhanden sein müssen, bevor Klassen<br />

der oberen Ebene benutzt werden können. Die Basisgruppe der<br />

erforderlichen Klassen <strong>für</strong> Java-Anwendungen wird als Laufzeit-Java-<br />

Klassen oder Java-API bezeichnet.<br />

65


Ein Java-Seminar<br />

Erklärung der Java-Objekte<br />

Methoden und<br />

Felder<br />

Klassenkonstruktoren<br />

66<br />

Eine Klasse definiert, was ein Objekt tun kann, genauso wie ein<br />

Rechnungsformular festlegt, welche Informationen die Rechnung enthalten<br />

sollte.<br />

Klassen enthalten keine spezifischen Informationen über Objekte. Vielmehr<br />

erstellt oder instanziert Ihre Anwendung Objekte auf Grundlage der Klasse<br />

(Vorlage), und die Objekte enthalten die Daten bzw. führen Berechnungen<br />

aus. Das instanzierte Objekt ist eine Instanz der Klasse. Beispiel: Ein<br />

Rechungsobjekt ist eine Instanz der Rechnungsklasse. Die Klasse definiert,<br />

was das Objekt leisten kann, aber das Objekt ist die Verwirklichung der<br />

Klasse, die erst Sinn und praktische Verwendbarkeit der Klasse ermöglicht.<br />

Im Beispiel mit dem Rechnungsformular definiert es, was alle Rechnungen<br />

enthalten müssen, die auf diesem Rechnungsformular aufgebaut werden. Es<br />

gibt ein Formular und 0 bis unendlich viele Rechnungen, die aufgrund dieses<br />

Formulars erstellt werden. Das Formular enthält die Definition, aber die<br />

Rechnung beinhaltet dann den tatsächlichen Nutzen.<br />

Das Rechnungsobjekt, das aus der Klasse erstellt wird, enthält die Daten,<br />

wird gespeichert, abgerufen, bearbeitet, und so weiter.<br />

Genauso wie ein Rechnungsformular verwendet wird, um viele Rechnungen<br />

zu erstellen, wobei jede Rechnung in den Details von jeder anderen<br />

Rechnung abweicht, so können aus einer Klasse viele Objekte abgeleitet<br />

werden.<br />

Eine Methode ist der Teil einer Klasse, der Arbeit leistet, eine Funktion, die<br />

<strong>für</strong> die Klasse eine Berechnung durchführt oder mit anderen Objekten<br />

interagiert. Methoden können Argumente aufnehmen und einen Wert an die<br />

aufrufende Funktion zurückgeben. Wenn kein Rückgabewert benötigt wird,<br />

kann eine Methode void (leer) zurückgegeben werden. Klassen können jede<br />

beliebige Anzahl von Methoden haben.<br />

Ein Feld ist Teil einer Klasse, das Informationen enthält. Wenn ein Objekt<br />

des Typs JavaClass erstellt wird, enthalten die Felder in der JavaClass einen<br />

ausschließlich <strong>für</strong> dieses Objekt bestimmten Zustand.<br />

Sie erstellen ein Objekt, indem Sie einen Klassen-Konstruktor aufrufen. Ein<br />

Konstruktor ist eine Methode mit den folgenden Eigenschaften:<br />

♦ Eine Konstruktormethode hat denselben Namen wie die Klasse und<br />

keinen deklarierten Datentyp. Beispiel: Ein einfacher Konstruktor <strong>für</strong><br />

die Klasse "Produkt" würde wie folgt deklariert werden:<br />

Produkt () {


Erklärung von Feldern<br />

Beispiele<br />

Kapitel 3 Einführung in Java <strong>für</strong> Datenbanken<br />

...Konstruktorcode wird hier eingegeben...<br />

}<br />

♦ Wenn Sie keine Konstruktormethode in Ihre Klassendefinition<br />

aufnehmen, wird eine Standardmethode benutzt, die mit dem Java-<br />

Basisobjekt mitgeliefert wurde.<br />

♦ Sie können mehr als einen Konstruktor <strong>für</strong> jede Klasse mit<br />

unterschiedlichen Argumenttypen- und Argumentzahlen liefern. Beim<br />

Aufruf eines Konstruktors wird derjenige benutzt, der die richtige<br />

Argumentzahl und die passenden Argumenttypen aufweist.<br />

Es gibt zwei Kategorien von Java-Feldern:<br />

♦ Instanzfelder Jedes Objekt hat seine eigene Gruppe von Instanzfeldern,<br />

die bei der Erstellung des Objekts geschaffen wurden. Sie enthalten<br />

Informationen, die speziell <strong>für</strong> diese Instanz gelten. Beispiel: Ein Feld<br />

lineItem1Description in der Klasse "Invoice" enthält die Beschreibung<br />

<strong>für</strong> einen Rechnungsposten einer bestimmten Rechnung. Sie können auf<br />

Instanzfelder nur über eine Objektreferenz zugreifen.<br />

♦ Klassenfelder Ein Klassenfeld enthält Informationen, die von einer<br />

bestimmten Instanz unabhängig sind. Ein Klassenfeld wird erstellt, wenn<br />

die Klasse zum ersten Mal geladen wird, und es werden keine weiteren<br />

Instanzen geschaffen, gleichgültig wie viele Objekte erzeugt werden.<br />

Auf Klassenfelder kann über den Klassennamen oder die Objektreferenz<br />

zugegriffen werden.<br />

Um ein Feld in einer Klasse zu deklarieren, legen Sie seinen Typ fest und<br />

setzen danach seinen Namen und ein Semikolon. Um ein Klassenfeld zu<br />

erstellen, benutzen Sie das Java-Schlüsselwort static in der Deklaration.<br />

Felder werden im Hauptteil einer Klasse, und nicht in einer Methode<br />

deklariert. Die Deklaration einer Variablen in einer Methode macht sie zu<br />

einem Teil der Methode, nicht der Klasse.<br />

Die folgende Deklaration der Klasse "Invoice" hat vier Felder, die den<br />

Informationen entsprechen, welche auf zwei Buchungszeilen in einer<br />

Rechnung stehen könnten.<br />

67


Ein Java-Seminar<br />

Erklärung von Methoden<br />

68<br />

public class Invoice {<br />

}<br />

// Felder einer Rechnung mit Rechnungsdaten<br />

public String lineItem1Description;<br />

public int lineItem1Cost;<br />

public String lineItem2Description;<br />

public int lineItem2Cost;<br />

Es gibt zwei Kategorien von Java-Methoden:<br />

♦ Instanzmethoden Eine totalSum-Methode in der Klasse "Invoice"<br />

muss die Steuer ausrechnen und hinzuaddieren, damit alle Kosten<br />

enthalten sind. Sie ist aber nur sinnvoll, wenn Sie im Zusammenhang<br />

mit einem Invoice-Objekt aufgerufen wird, bei dem die einzelnen<br />

Rechnungsposten zusätzliche Steuer- oder Kostenposten enthalten. Die<br />

Berechnung kann nur <strong>für</strong> ein Objekt ausgeführt werden, da das Objekt<br />

die beiden Rechnungszeilen enthält, nicht die Klasse.<br />

♦ Klassenmethoden Klassenmethoden (auch als statische Methoden<br />

bekannt) können aufgerufen werden, ohne dass erst ein Objekt erstellt<br />

werden muss. Nur der Name der Klasse und der Methode sind<br />

erforderlich, um eine Klassenmethode aufzurufen.<br />

Ähnlich wie bei Instanzmethoden akzeptieren die Klassenmethoden<br />

Argumente und Rückgabewerte. In der Regel führen Klassenmethoden<br />

eine Art von Dienstprogramm oder Informationsfunktion aus, die mit<br />

der Allgemeinfunktion der Klasse in Beziehung stehen.<br />

Klassenmethoden können auf Instanzenfelder nicht zugreifen.<br />

Um eine Methode zu deklarieren, geben Sie ihren Rückgabetyp, ihren<br />

Namen und alle von ihr übernommenen Parameter an. Wie eine<br />

Klassendeklaration benutzt die Methode eine geöffnete und geschlossene<br />

geschweifte Klammer, um den Hauptteil der Methode zu definieren, in den<br />

der Programmcode gesetzt wird.


Beispiel<br />

Beispiel<br />

public class Invoice {<br />

Kapitel 3 Einführung in Java <strong>für</strong> Datenbanken<br />

// Felder<br />

public String lineItem1Description;<br />

public double lineItem1Cost;<br />

}<br />

public String lineItem2Description;<br />

public double lineItem2Cost;<br />

//Eine Methode<br />

public double totalSum() {<br />

double runningsum;<br />

}<br />

runningsum = lineItem1Cost +<br />

lineItem2Cost;<br />

runningsum = runningsum * 1,16;<br />

return runningsum;<br />

Im Hauptteil der Methode totalSum wird eine Variable namens runningsum<br />

deklariert. Sie wird zunächst verwendet, um die Zwischensumme der ersten<br />

und der zweiten Zeile aufzunehmen. Diese Zwischensumme wird dann mit<br />

16 Prozent (z.B. Mehrwertsteuer) multipliziert, um die Gesamtsumme zu<br />

erhalten.<br />

Die lokale Variable (die im Hauptteil der Methode bekannt ist), wird dann an<br />

die aufrufende Funktion zurückgegeben. Wenn die Methode totalSum<br />

aufgerufen wird, gibt sie die Summe der zwei Zeilen plus die Steuer auf<br />

diese Summe zurück.<br />

Die Methode parseInt der Klasse java.lang.Integer, die mit <strong>Adaptive</strong><br />

Server <strong>Anywhere</strong> mitgeliefert wird, ist ein Beispiel <strong>für</strong> eine Klassenmethode.<br />

Wenn ihr ein Zeichenfolgenargument übergeben wird, gibt die Methode<br />

parseInt eine Ganzzahl-Version der Zeichenfolge zurück.<br />

Beispiel: Gegeben sei der Zeichenfolgenwert "1". Die Methode parseInt<br />

gibt den Ganzzahlwert 1 zurück, ohne eine Instanz der Klasse<br />

java.lang.Integer erstellen zu müssen. Das Beispiel wird im nachstehenden<br />

Java-Codefragment veranschaulicht:<br />

String num = "1";<br />

int i = java.lang.Integer.parseInt( num );<br />

Die folgende Version der Rechnungsklasse enthält nun eine Instanzmethode<br />

und eine Klassenmethode. Die Klassenmethode namens rateOfTaxation<br />

gibt die Steuerrate zurück, die von der Klasse benutzt wird, um die<br />

Gesamtsumme der Rechnung zu kalkulieren.<br />

69


Ein Java-Seminar<br />

70<br />

Dass die Methode rateOfTaxation zur Klassenmethode (und nicht zur<br />

Instanzmethode oder zu einem Feld) gemacht wurde, liegt darin, dass andere<br />

Klassen und Prozeduren den Wert benutzen können, der von dieser Methode<br />

zurückgegeben wird, ohne erst eine Instanz der Klasse erstellen zu müssen.<br />

Nur der Name der Klasse und der Methode sind erforderlich, um den<br />

Steuersatz auszugeben, der von dieser Klasse verwendet wird.<br />

Dadurch dass der Steuersatz rateOfTaxation zu einer Methode, und nicht zu<br />

einem Feld gemacht wird, kann der Anwendungsentwickler den Steuersatz<br />

ändern, ohne dass dies Auswirkungen auf Objekte, Anwendungen oder<br />

Prozeduren hätte, die den Rückgabewert dieser Methode verwenden.<br />

Zukünftige Versionen der Klasse "Invoice" können den Rückgabewert der<br />

Klassenmethode rateOfTaxation auf einer komplizierteren Berechnung<br />

basieren lassen, ohne dass andere Methoden beeinträchtigt werden, die den<br />

Rückgabewert verwenden.<br />

public class Invoice {<br />

// Felder<br />

public String lineItem1Description;<br />

public double lineItem1Cost;<br />

public String lineItem2Description;<br />

public double lineItem2Cost;<br />

// Eine Instanzenmethode<br />

public double totalSum() {<br />

double runningsum;<br />

double taxfactor = 1 + Invoice.rateOfTaxation();<br />

}<br />

runningsum = lineItem1Cost + lineItem2Cost;<br />

runningsum = runningsum * taxfactor;<br />

return runningsum;<br />

}<br />

// Eine Klassenmethode<br />

public static double rateOfTaxation() {<br />

double rate;<br />

rate = .16;<br />

return rate;<br />

}<br />

Objektorientierte und prozedurale Sprachen<br />

Wenn Sie mehr Erfahrung mit prozeduralen Sprachen wie C oder der<br />

Sprache <strong>für</strong> gespeicherte Prozeduren haben als mit objektorientierten<br />

Sprachen, finden Sie in diesem Abschnitt eine Erörterung der Ähnlichkeiten<br />

und Unterschiede zwischen prozeduralen und objektorientierten Sprachen.


Java basiert auf<br />

Klassen<br />

Ein Glossar der Java-Begriffe<br />

Pakete<br />

Kapitel 3 Einführung in Java <strong>für</strong> Datenbanken<br />

Die wichtigste strukturelle Einheit eines Codes in Java ist eine Klasse.<br />

Eine Java-Klasse ist im Prinzip eine Sammlung von Prozeduren und<br />

Variablen, die gruppiert wurden, weil sie alle zu einer bestimmten,<br />

identifizierbaren Kategorie gehören.<br />

Die Art und Weise, wie eine Klasse benutzt wird, unterscheidet aber die<br />

objektorientierten Sprachen von prozeduralen Sprachen. Eine in einer<br />

prozeduralen Sprache geschriebene Anwendung wird ausgeführt, indem sie<br />

einmal in den Speicher geladen wird und eine genau vorgegebene<br />

Abwicklungsfolge einhält.<br />

In objektorientierten Sprachen wie Java wird eine Klasse wie eine Vorlage<br />

benutzt: Eine Definition einer potenziellen Programmausführung. Mehrere<br />

Kopien der Klasse können je nach Anforderung erstellt und dynamisch<br />

geladen werden, wobei jede Instanz der Klasse eigene Daten, Werte und<br />

Ablaufprozeduren enthalten kann. Jede geladene Klasse wird unabhängig<br />

von anderen im Speicher geladenen Klassen behandelt und ausgeführt.<br />

Eine Klasse, die zum Ausführen in den Speicher geladen wurde, wird als<br />

instanziert bezeichnet. Eine instanzierte Klasse wird "Objekt" genannt: Dabei<br />

handelt es sich um eine Anwendung, die von der Klasse abgeleitet wurde, die<br />

vorbereitet wurde, um eindeutige Werte zu enthalten bzw. um zu bewirken,<br />

dass ihre Methoden unabhängig von anderen Klasseninstanzen ausgeführt<br />

werden.<br />

Im folgenden Abschnitt werden einige Begriffe im Zusammenhang mit Java-<br />

Klassen erklärt. Dies ist natürlich keine erschöpfende Behandlung der Java-<br />

Sprache, sondern soll das Konzept der Java-Klassen in <strong>Adaptive</strong> Server<br />

<strong>Anywhere</strong> vorstellen.<br />

$ Weitere Hinweise über die Sprache Java finden Sie in der Online-<br />

Dokumentation Thinking in Java von Bruce Eckel. Sie gehört zum<br />

Lieferumfang von <strong>Adaptive</strong> Server <strong>Anywhere</strong>, und Sie finden sie in der<br />

Datei Samples\ASA\Java\Tjava.pdf.<br />

Ein Paket ist eine Gruppe von Klassen, die einen gemeinsamen Zweck oder<br />

eine gemeinsame Kategorie haben. Ein Mitglied eines Pakets hat spezielle<br />

Berechtigungen <strong>für</strong> den Zugriff auf Daten und Methoden bei anderen<br />

Mitgliedern des Pakets, und daher gibt es den Zugriffsmodifizierer<br />

protected.<br />

71


Ein Java-Seminar<br />

"Public" und<br />

"Private"<br />

Konstruktoren<br />

Sammlung der<br />

Abfalldaten<br />

72<br />

Ein Paket ist in Java das, was sonst unter einer Bibliothek oder Library<br />

bekannt ist. Es handelt sich dabei um eine Sammlung von Klassen, die mit<br />

der import-Anweisung verfügbar gemacht werden können. Die folgende<br />

Java-Anweisung importiert die Dienstprogramm-Bibliothek aus der Java-<br />

API:<br />

import java.util.*<br />

Pakete werden normalerweise in JAR-Dateien gespeichert, mit der<br />

Erweiterung .jar oder .zip.<br />

Ein Zugriffsmodifizierer (im Wesentlichen die Schlüsselwörter public,<br />

private oder protected vor jeder Deklaration) bestimmt die Sichtbarkeit<br />

eines Feldes, einer Methode oder einer Klasse <strong>für</strong> andere Java-Objekte.<br />

♦ Mit public bezeichnete Klassen, Methoden oder Felder sind überall<br />

sichtbar.<br />

♦ Mit private bezeichnete Klassen, Methoden oder Felder sind nur in<br />

Methoden sichtbar, die in dieser Klasse definiert wurden.<br />

♦ Mit protected bezeichnete Methoden oder Felder sind <strong>für</strong> Methoden<br />

sichtbar, die innerhalb dieser Klasse, in Unterklassen dieser Klassen<br />

oder in anderen Klassen des selben Pakets definiert wurden.<br />

♦ Die Standardsichtbarkeit (Paket) bedeutet, dass die Methoden oder<br />

Felder innerhalb der Klasse oder <strong>für</strong> andere Klassen im Paket sichtbar<br />

sind.<br />

Ein Konstruktor ist eine spezielle Methode einer Java-Klasse, die<br />

aufgerufen wird, wenn eine Instanz der Klasse erstellt wird.<br />

Klassen können ihre eigenen Konstruktoren definieren, darunter mehrfache,<br />

einander aufhebende Konstruktoren. Welcher Konstruktor verwendet wird,<br />

hängt davon ab, welche Argumente beim Versuch der Erstellung des Objekts<br />

verwendet wurden. Wenn der Typ, die Anzahl und die Reihenfolge der<br />

Argumente, die <strong>für</strong> die Erstellung einer Instanz der Klasse verwendet<br />

werden, zu einem der Konstruktoren der Klasse passen, wird dieser<br />

Konstruktor verwendet, um das Objekt zu erstellen.<br />

Die Abfalldatensammlung entfernt automatisch alle Objekte, <strong>für</strong> die keine<br />

Referenzen bestehen, mit Ausnahme der Objekte, die als Werte in einer<br />

Tabelle gespeichert sind.<br />

In Java gibt es keine Destruktorenmethode wie in C++. Java-Klassen können<br />

ihre eigene Abschluss-Methode ("finalize") <strong>für</strong> das Aufräumen definieren,<br />

nachdem ein Objekt nach der Abfalldatensammlung entfernt wurde.


Schnittstellen oder<br />

Interfaces<br />

Fehlerbehandlung in Java<br />

Fehlertypen in<br />

Java<br />

Kapitel 3 Einführung in Java <strong>für</strong> Datenbanken<br />

Java-Klassen können nur von einer Klasse erben. Java benutzt Interfaces<br />

(Schnittstellen) anstelle von mehrfacher Vererbung. Eine Klasse kann<br />

mehrere Schnittstellen implementieren. Jede Schnittstelle definiert eine<br />

Reihe von Methoden und Methodenprofilen, die von der Klasse<br />

implementiert werden müssen, damit die Klasse kompiliert werden kann.<br />

Eine Schnittstelle definiert, welche Methoden und statischen Felder die<br />

Klasse deklarieren muss. Die Implementierung der Methoden und Felder, die<br />

in einer Schnittstelle deklariert werden, erfolgt in der Klasse, die die<br />

Schnittstelle benutzt: Die Schnittstelle definiert, was die Klasse deklarieren<br />

muss, und es obliegt der Klasse, festzulegen, wie die Implementierung vor<br />

sich geht.<br />

Der Fehlerbehandlungscode ist in Java von der normalen Verarbeitung<br />

getrennt.<br />

Fehler generieren ein Ausnahmebedingungsobjekt, das den Fehler darstellt.<br />

Dies wird als throwing an exception (Ausnahmefehler auslösen) bezeichnet.<br />

Eine ausgelöste Ausnahmebedingung beendet ein Java-Programm, wenn sie<br />

nicht in der Anwendung abgefangen und entsprechend verarbeitet wird.<br />

Sowohl Java-API-Klassen, als auch benutzerdefinierte Klassen können einen<br />

Ausnahmefehler auswerfen. Benutzer können ihre eigenen Ausnahmeklassen<br />

erstellen, die ihre eigenen benutzerdefinierten Klassen auswerfen können.<br />

Wenn im Hauptteil der Methode, in der der Ausnahmefehler auftrat, keine<br />

Ausnahmeroutine vorgesehen ist, wird die Suche nach einer<br />

Ausnahmeroutine über den kompletten Aufrufstack fortgesetzt. Wenn die<br />

Spitze des Aufrufstacks erreicht ist und noch immer keine Ausnahmeroutine<br />

gefunden wurde, wird die Standard-Ausnahmeroutine des Java-Interpreters<br />

aufgerufen und das Programm beendet.<br />

In <strong>Adaptive</strong> Server <strong>Anywhere</strong> gilt: Wenn eine SQL-Anweisung eine Java-<br />

Methode aufruft, wird ein SQL-Fehler generiert.<br />

Alle Fehler in Java werden aus zwei Arten von Fehlerklassen abgeleitet:<br />

Ausnahme (Exception) und Fehler (Error). Normalerweise werden Fehler<br />

vom Typ "Exception" durch Fehlerroutinen im Hauptteil der Methode<br />

verarbeitet. Fehler vom Typ "Error" sind <strong>für</strong> interne Fehler und<br />

Fehlerbedingungen wegen Ressourcenmangel im Java-Laufzeitsystem<br />

vorgesehen.<br />

Ausnahmebedingungsfehler werden ausgeworfen und abgefangen. Die<br />

Verarbeitungsroutinen bei Ausnahmefehlern werden durch die Codeblöcke<br />

try, catch und finally gekennzeichnet.<br />

73


Ein Java-Seminar<br />

74<br />

Ein try-Block führt einen Programmcode aus, der einen Fehler generieren<br />

kann. Ein catch-Block ist ein Codeteil, der ausgeführt wird, wenn ein Fehler<br />

während der Ausführung eines try-Blocks generiert (ausgeworfen) wird.<br />

Ein finally-Block definiert einen Codeblock, der unabhängig davon<br />

ausgeführt wird, ob ein Fehler generiert und abgefangen wurde.<br />

Typischerweise wird er <strong>für</strong> Aufräumroutinen verwendet. Er wird <strong>für</strong> Code<br />

benutzt, der unter keinen Umständen ausgelassen werden darf.<br />

Ausnahmebedingungsfehler werden in zwei Typen unterteilt: Laufzeitfehler<br />

und Nicht-Laufzeitfehler.<br />

Fehler, die vom Laufzeitsystem generiert wurden, sind als implizite<br />

Ausnahmefehler bekannt, da sie nicht explizit als Teil jeder Klassen- oder<br />

Methodendeklaration verarbeitet werden müssen.<br />

Beispiel: Der Ausnahmefehler "array out of bounds" kann auftreten, wenn<br />

ein Array benutzt wird, der Fehler muss aber nicht Teil der Deklaration der<br />

Klasse oder Methode sein, die dieses Array benutzen.<br />

Alle anderen Ausnahmebedingungen sind explizit. Wenn die aufgerufene<br />

Methode einen Ausnahmefehler auswerfen kann, muss der Fehler explizit<br />

von der Klasse abgefangen werden, die die Auswurfmethode <strong>für</strong> den Fehler<br />

benutzt, oder diese Klasse muss explizit den Fehler selbst auswerfen, indem<br />

die Ausnahmebedingung, die generiert werden könnte, in ihrer<br />

Klassendeklaration identifiziert wird. Im Wesentlichen heißt das: Explizite<br />

Ausnahmebedingungen müssen explizit behandelt werden. Eine Methode<br />

muss alle expliziten Fehler deklarieren, die sie auswirft, oder alle expliziten<br />

Fehler abfangen, die möglicherweise ausgeworfen werden.<br />

Nicht-Laufzeitfehler werden zum Kompilierungszeitpunkt geprüft.<br />

Laufzeitfehler werden normalerweise durch Programmierungsfehler<br />

verursacht. Java erkennt viele dieser Fehler während der Kompilierung,<br />

bevor der Code ausgeführt wird.<br />

Für jede Java-Methode wird ein alternativer Ausführungspfad definiert,<br />

sodass alle Java-Methoden abgeschlossen werden können, auch wenn der<br />

normale Abschluss nicht möglich ist. Wenn der Typ des ausgeworfenen<br />

Fehlers nicht erfasst ist, wird er an den nächsten Code-Block oder die<br />

nächste Methode im Stack weitergereicht.


Kapitel 3 Einführung in Java <strong>für</strong> Datenbanken<br />

Die Laufzeitumgebung <strong>für</strong> Java in der Datenbank<br />

In diesem Abschnitt wird die <strong>Sybase</strong>-Laufzeitumgebung <strong>für</strong> Java<br />

beschrieben, und wie sie sich von einer Standard-Java-Laufzeitumgebung<br />

unterscheidet.<br />

Unterstützte Versionen von Java und JDBC<br />

Die Laufzeit-Java-Klassen<br />

Die <strong>Sybase</strong> Java VM bietet die Auswahl zwischen den<br />

Programmierschnittstellen JDK 1.1, JDK 1.2, und JDK 1.3. Die tatsächlich<br />

gelieferte Version ist JDK 1.1.8. und 1.3.<br />

Zwischen Version 1.0 des JDK und Version 1.1 wurden einige neue APIs<br />

eingeführt. Außerdem wurden einige APIs entfernt. Die Verwendung<br />

bestimmter APIs wird nicht länger empfohlen, und die Unterstützung dieser<br />

APIs könnte in kommenden Versionen nicht mehr gesichert sein.<br />

Eine Java-Klassendatei, die nicht mehr empfohlene API verwendet, generiert<br />

beim Kompilieren eine Warnung, kann aber auf einer Java Virtual Machine<br />

ausgeführt werden, die gemäß den Standards der Version 1.1 programmiert<br />

wurde, wie z.B. der <strong>Sybase</strong> VM.<br />

Der interne JDBC-Treiber unterstützt JDBC Version 2.<br />

$ Weitere Hinweise zu den unterstützten JDK APIs finden Sie unter<br />

"Unterstützte Java-Pakete" auf Seite 87 der Dokumentation ASA SQL-<br />

Referenzhandbuch.<br />

$ Hinweise zum Erstellen einer Datenbank, die Java unterstützt, finden<br />

Sie unter "Datenbank <strong>für</strong> Java aktivieren" auf Seite 97.<br />

Die Laufzeit-Java-Klassen sind die Klassen der niedrigen Stufe, die <strong>für</strong> eine<br />

Datenbank verfügbar gemacht werden, wenn Sie erstellt oder <strong>für</strong> Java<br />

aktiviert wird. Diese Klassen enthalten eine Teilmenge der Java-API. Diese<br />

Klassen sind Teil des Sun Java Development Kit.<br />

Die Laufzeit-Klassen bieten Funktionen, auf denen Anwendungen aufbauen<br />

können. Die Laufzeit-Klassen sind <strong>für</strong> Klassen in der Datenbank immer<br />

verfügbar.<br />

75


Die Laufzeitumgebung <strong>für</strong> Java in der Datenbank<br />

Beispiele<br />

Benutzerdefinierte Klassen<br />

76<br />

Sie können die Laufzeit-Java-Klassen in Ihre eigenen benutzerdefinierten<br />

Klassen einbeziehen: Entweder, indem sie deren Funktionen erben oder<br />

indem Sie sie bei einer Berechnung oder einem Vorgang in einer Methode<br />

verwenden.<br />

Einige Java-API-Klassen, die in den Laufzeit-Java-Klassen enthalten sind:<br />

♦ Primitive Java-Datentypen Alle "primitiven" (nativen) Datentypen in<br />

Java haben eine entsprechende Klasse. Um Objekte dieser Typen zu<br />

erstellen, haben die Klassen zusätzliche, oft sehr nützliche Funktionen.<br />

Der Java-Datentyp int hat eine entsprechende Klasse in<br />

java.lang.Integer.<br />

♦ Das Dienstprogramm-Paket Das Paket java.util.* enthält eine Reihe<br />

von sehr hilfreichen Klassen, deren Funktionen keine Entsprechung in<br />

den SQL-Funktionen haben, welche in <strong>Adaptive</strong> Server <strong>Anywhere</strong><br />

verfügbar sind.<br />

Zu diesen Klassen gehören:<br />

♦ Hashtable Eine Zuordnung von Schlüsseln und Werten.<br />

♦ StringTokenizer Diese Klasse zerlegt eine Zeichenfolge in<br />

Einzelwörter.<br />

♦ Vector Diese Klasse enthält ein Array von Objekten, deren Größe<br />

sich dynamisch ändern kann.<br />

♦ Stack Diese Klasse enthält einen Last-in-First-out-Stack von<br />

Objekten.<br />

♦ JDBC <strong>für</strong> SQL-Vorgänge Das Paket java.SQL.* enthält die Klassen die<br />

von Java-Objekten benötigt werden, um Daten mit SQL-Anweisungen<br />

aus der Datenbank zu extrahieren.<br />

Anders als benutzerdefinierte Klassen werden die Laufzeitklassen in der<br />

Datenbank nicht gespeichert. Sie werden vielmehr im Unterverzeichnis java<br />

des <strong>Adaptive</strong> Server <strong>Anywhere</strong>-Installationsverzeichnisses gespeichert.<br />

Benutzerdefinierte Klassen werden in einer Datenbank mit der Anweisung<br />

INSTALL installiert. Nach ihrer Installation stehen sie anderen Klassen in<br />

der Datenbank zur Verfügung. Wenn es sich um öffentliche Klassen handelt,<br />

stehen Sie <strong>für</strong> SQL als Domänen zur Verfügung.<br />

$ Hinweise zur Installation von Klassen finden Sie unter "Java-Klassen in<br />

einer Datenbank installieren" auf Seite 103.


Java-Methoden und Felder identifizieren<br />

Der Punkt in SQL<br />

Der Punkt in Java<br />

Aufruf von Java-<br />

Methoden aus SQL<br />

Kapitel 3 Einführung in Java <strong>für</strong> Datenbanken<br />

In SQL-Anweisungen identifiziert der Punkt Spalten von Tabellen, wie zum<br />

Beispiel in der folgenden Abfrage:<br />

SELECT employee.emp_id<br />

FROM employee<br />

Der Punkt kennzeichnet auch die Eigentümerschaft in qualifizierten<br />

Objektnamen:<br />

SELECT emp_id<br />

FROM DBA.employee<br />

In Java ist der Punkt ein Operator, der die Methoden aufruft oder auf die<br />

Felder einer Java-Klasse oder eines Java-Objekts zugreift. Er ist auch Teil<br />

eines Bezeichners, der benutzt wird, um Klassennamen zu kennzeichnen,<br />

wie im voll qualifizierten Klassennamen java.util.Hashtable.<br />

Im nachstehenden Java-Codefragment ist der Punkt in der ersten Zeile ein<br />

Bezeichner. In der zweiten Zeile des Programmcodes ist er ein Operator.<br />

java.util.Random rnd = new java.util.Random();<br />

int i = rnd.nextInt();<br />

In SQL kann der Punktoperator durch eine doppelte geschlossene spitze<br />

Klammer (>>) ersetzt werden. Der Punktoperator ist <strong>für</strong> Java passender,<br />

kann aber bei bestehenden SQL-Namen zu Verwechslungen führen. Die<br />

Verwendung von >> beseitigt diese Zweideutigkeit.<br />

>> in SQL ist nicht dasselbe wie >> in Java<br />

Die doppelte geschlossene spitze Klammer wird nur in SQL-<br />

Anweisungen verwendet, wo sonst ein Java-Punktoperator erwartet wird.<br />

In einer Java-Klasse ist die doppelte geschlossene spitze Klammer kein<br />

Ersatz <strong>für</strong> den Punktoperator und hat eine vollständig andere Bedeutung<br />

in ihrer Rolle als rechter Bitverschiebungs-Operator.<br />

Die folgende SQL-Anweisungsfolge ist beispielsweise gültig:<br />

CREATE VARIABLE rnd java.util.Random;<br />

SET rnd = NEW java.util.Random();<br />

SELECT rnd>>nextInt();<br />

Das Ergebnis der SELECT-Anweisung ist eine zufallsgenerierte Ganzzahl.<br />

Unter Verwendung der Variablen, die im vorhergehenden SQL-Beispiel<br />

erstellt wurde, zeigt die folgende SQL-Anweisung die richtige Verwendung<br />

einer Klassenmethode:<br />

SELECT java.lang.Math>>abs( rnd>>nextInt() );<br />

77


Die Laufzeitumgebung <strong>für</strong> Java in der Datenbank<br />

Java berücksichtigt Groß/Kleinschreibung<br />

Datentypen<br />

Zeichenfolgen in Java und SQL<br />

78<br />

Java-Syntax funktioniert so, wie Sie es von ihr erwarten, und SQL-Syntax<br />

wird durch das Vorhandensein von Java-Klassen nicht verändert. Dies bleibt<br />

auch so, wenn dieselbe SQL-Anweisung sowohl Java, als auch SQL-Syntax<br />

enthält. Dies ist eine einfache Feststellung, aber mit weit reichenden<br />

Auswirkungen.<br />

Java berücksichtigt die Groß/Kleinschreibung. Die Java-Klasse FindOut ist<br />

nicht dasselbe wie die Klasse Findout. SQL berücksichtigt die Groß-/Kleinschreibung<br />

bei Schlüsselwörtern und Bezeichnern nicht.<br />

Die Berücksichtigung von Groß-/Kleinschreibung durch Java wird auch<br />

beibehalten, wenn der Java-Code in eine SQL-Anweisung eingebettet ist, die<br />

die Groß-/Kleinschreibung nicht berücksichtigt. Die Java-Teile der<br />

Anweisung müssen die Groß/Kleinschreibung berücksichtigen, auch wenn<br />

die Teile vor und nach der Java-Syntax ohne Berücksichtigung der<br />

Schreibweise programmiert werden können.<br />

Beispielsweise werden die nachstehenden SQL-Anweisungen erfolgreich<br />

ausgeführt, da die Schreibweise der Java-Objekte, Klassen und Operatoren<br />

respektiert wird, auch wenn im restlichen Teil der SQL-Anweisung die<br />

Groß-/Kleinschreibung nicht einheitlich ist.<br />

SeLeCt java.lang.Math.random();<br />

Wenn eine Java-Klasse als Datentyp <strong>für</strong> eine Spalte verwendet wird, erfolgt<br />

dies in Form eines benutzerdefinierten SQL-Datentyps. Trotzdem wird die<br />

Groß/Kleinschreibung immer berücksichtigt. Diese Konvention verhindert<br />

Zweideutigkeiten mit Java-Klassen, die sich nur durch die Groß-/Kleinschreibung<br />

voneinander unterscheiden.<br />

Mit Anführungszeichen werden Zeichenfolgenliterale in Java<br />

gekennzeichnet, wie im folgenden Java-Programmfragment gezeigt wird:<br />

String str = "Dies ist eine Zeichenfolge"<br />

In SQL werden Zeichenfolgen hingegen mit Apostrophen gekennzeichnet,<br />

und Anführungszeichen kennzeichnen einen Bezeichner, wie in der<br />

folgenden SQL-Anweisung:<br />

INSERT INTO TABLE DBA.t1<br />

VALUES( ’Hallo’ )<br />

In Java-Quellcode müssen Sie immer Anführungszeichen verwenden, in<br />

SQL-Anweisungen hingegen Apostrophe.<br />

Die folgenden SQL-Anweisungen sind beispielsweise gültig.


Ausgabe in die Befehlszeile<br />

Kapitel 3 Einführung in Java <strong>für</strong> Datenbanken<br />

CREATE VARIABLE str char(20);<br />

set str = new java.lang.String( ’Brandneues Objekt’ )<br />

Das folgende Java-Codefragment ist auch gültig, wenn es in einer Java-<br />

Klasse verwendet wird.<br />

String str = new java.lang.String(<br />

"Brandneues Objekt" );<br />

Die Ausgabe in die Standardausgabe ist eine Technik <strong>für</strong> die schnelle<br />

Prüfung von Variablenwerten und Ausführungsergebnissen an bestimmten<br />

Stellen im Programmcode. Bei Erkennung der Methode in der zweiten Zeile<br />

des folgenden Java-Codefragments wird das Zeichenfolgenargument, das<br />

von der Methode akzeptiert wird, in die Standardausgabe geschrieben.<br />

String str = "Hallo Welt";<br />

System.out.println( str );<br />

In <strong>Adaptive</strong> Server <strong>Anywhere</strong> ist das Serverfenster die Standardausgabe, so<br />

dass die Zeichenfolge dort erscheint. Die Ausführung des oben angegebenen<br />

Java-Programmcodes in der Datenbank ist der folgenden SQL-Anweisung<br />

gleichwertig:<br />

MESSAGE ’Hallo Welt’<br />

Hauptmethode (main) verwenden<br />

Wenn eine Klasse eine main-Methode enthält, die zur folgenden Deklaration<br />

passt, wird sie von den meisten Java-Laufzeitumgebungen, wie zum Beispiel<br />

vom Sun Java-Interpreter, automatisch ausgeführt. Normalerweise wird diese<br />

statische Methode nur ausgeführt, wenn sie die Klasse ist, die vom Java-<br />

Interpreter aufgerufen wurde.<br />

public static void main( String args[ ] ) { }<br />

Die Hauptklasse ist eine nützliche Klasse <strong>für</strong> das Austesten der Funktionen<br />

von Java-Objekten: Sie können immer sicher sein, dass diese Methode als<br />

erste aufgerufen wird, wenn Sie das Sun Java Laufzeitsystem starten.<br />

In <strong>Adaptive</strong> Server <strong>Anywhere</strong> ist das Java-Laufzeitsystem jederzeit<br />

verfügbar. Die Funktionen der Objekte und Methoden können mit SQL-<br />

Anweisungen unmittelbar und dynamisch getestet werden. In vielerlei<br />

Hinsicht ist diese Methode <strong>für</strong> das Testen von Java-Klassen-Funktionen viel<br />

flexibler.<br />

79


Die Laufzeitumgebung <strong>für</strong> Java in der Datenbank<br />

Bereich und Dauerhaftigkeit (Persistenz)<br />

80<br />

SQL-Variable sind nur so dauerhaft wie die Verbindung. Dies ist nicht<br />

anders als bei früheren Versionen von <strong>Adaptive</strong> Server <strong>Anywhere</strong> und wird<br />

auch nicht davon berührt, ob die Variable eine Java-Klasse oder ein nativer<br />

SQL-Datentyp ist.<br />

Die Dauerhaftigkeit (oder "Persistenz") von Java-Klassen entspricht der der<br />

Tabellen in einer Datenbank: Tabellen existieren in einer Datenbank so<br />

lange, bis sie gelöscht werden, gleichgültig ob sie Daten enthalten oder<br />

niemals benutzt werden. Java-Klassen, die in einer Datenbank installiert<br />

wurden, sind ähnlich: Man kann sie benutzen, bis sie explizit durch eine<br />

REMOVE-Anweisung entfernt werden.<br />

$ Weitere Hinweise zum Entfernen von Klassen finden Sie unter<br />

"REMOVE-Anweisung" auf Seite 547 der Dokumentation ASA SQL-<br />

Referenzhandbuch.<br />

Eine Klassenmethode in einer installierten Java-Klasse kann jederzeit aus<br />

einer SQL-Anweisung aufgerufen werden. Sie können die folgende<br />

Anweisung überall ausführen, wo Sie SQL-Anweisungen ausführen können.<br />

Select java.lang.Math.abs(-342)<br />

Ein Java-Objekt ist nur in zwei Formen verfügbar: als Wert einer Variablen<br />

oder als Wert in einer Tabelle.<br />

Java-Escapezeichen in SQL-Anweisungen<br />

Im Java-Programmcode können Sie Escapezeichen verwenden, um<br />

bestimmte Sonderzeichen in Zeichenfolgen einzufügen. Ein Beispiel ist der<br />

folgende Programmcode, der ein Zeichen <strong>für</strong> Neue Zeile und ein<br />

Tabulatorzeichen vor einem Satz einführt, der ein Apostroph enthält.<br />

String str = "\n\t\Eine Zeichenfolge ist\’s, die mir<br />

fehlt";<br />

Die Verwendung von Java-Escapezeichen ist im <strong>Adaptive</strong> Server <strong>Anywhere</strong><br />

nur erlaubt, wenn sie von Java-Klassen benutzt werden. Aus SQL müssen<br />

hingegen die Regeln befolgt werden, die <strong>für</strong> Zeichenfolgen in SQL gelten:<br />

Beispiel: Um einen Zeichenfolgenwert an ein Feld zu übergeben, das eine<br />

SQL-Anweisung benutzt, kann folgende Anweisung benutzt werden, das<br />

Java-Escapezeichen hingegen nicht.<br />

set obj.str = ’\nDie Zeichenfolge ist’’s, die fehlte!’;<br />

$ Weitere Hinweise über die Regeln <strong>für</strong> SQL-Zeichenfolgen finden Sie<br />

unter "Zeichenfolgen" auf Seite 10 der Dokumentation ASA SQL-<br />

Referenzhandbuch.


Schlüsselwortkonflikte<br />

Import-Anweisungen verwenden<br />

Die Klassen weiter<br />

oben in der<br />

Hierarchie müssen<br />

ebenfalls installiert<br />

sein.<br />

Kapitel 3 Einführung in Java <strong>für</strong> Datenbanken<br />

SQL-Schlüsselwörter können im Konflikt mit Namen von Java-Klassen,<br />

einschließlich API-Klassen stehen. Dies tritt ein, wenn der Name einer<br />

Klasse, wie z.B. der Klasse "Date", die ein Teil des Pakets java.util.* ist,<br />

referenziert wird. SQL reserviert das Wort Date <strong>für</strong> den Einsatz als<br />

Schlüsselwort, auch wenn es gleichzeitig der Name einer Java-Klasse ist.<br />

Wenn solche Zweideutigkeiten auftreten, können Sie Anführungszeichen<br />

verwenden, um anzuzeigen, dass Sie das betreffende Wort nicht mehr als <strong>für</strong><br />

SQL reserviertes Wort verwenden. Beispiel: Die folgende SQL-Anweisung<br />

verursacht einen Fehler, da "Date" ein Schlüsselwort und seine Verwendung<br />

<strong>für</strong> SQL reserviert ist.<br />

-- Diese Anweisung ist unzulässig<br />

CREATE VARIABLE dt java.util.Date<br />

Die folgenden beiden Anweisungen funktionieren hingegen richtig, weil das<br />

Wort "Date" in Anführungszeichen steht.<br />

CREATE VARIABLE dt java.util."Date";<br />

SET dt = NEW java.util."Date"(1997, 11, 22, 16, 11, 01)<br />

Die Variable dt enthält jetzt das Datum: November 22, 1997, 4:11 p.m.<br />

Es ist allgemein üblich, in einer Java-Klassen-Deklaration eine Import-<br />

Anweisung <strong>für</strong> den Zugriff auf andere, externe Klassen einzubeziehen. Sie<br />

können importierte Klassen mit unqualifizierten Klassennamen<br />

referenzieren.<br />

Beispiel: Sie können die Stack-Klasse des Pakets java.util auf zwei Arten<br />

referenzieren:<br />

♦ Explizit mit dem Namen java.util.Stack<br />

♦ Oder mit dem Namen Stack, und Einschluss der folgenden Import-<br />

Anweisung:<br />

import java.util.*;<br />

Eine von einer anderen Klasse explizit mit einem voll qualifizierten Namen<br />

oder implizit mit einer Import-Anweisung referenzierte Klasse muss<br />

ebenfalls in der Datenbank installiert sein.<br />

81


Die Laufzeitumgebung <strong>für</strong> Java in der Datenbank<br />

CLASSPATH-Variable verwenden<br />

CLASSPATH<br />

während der<br />

Laufzeit ignoriert<br />

CLASSPATH zur<br />

Installation von<br />

Klassen<br />

82<br />

Die Import-Anweisung funktioniert in kompilierten Klassen wie<br />

beabsichtigt. In der Laufzeitumgebung von <strong>Adaptive</strong> Server <strong>Anywhere</strong> gibt<br />

es allerdings keine der Import-Anweisung gleichwertige Anweisung. Alle<br />

Klassennamen, die in SQL-Anweisungen oder in gespeicherten Prozeduren<br />

verwendet werden, müssen voll qualifiziert sein. Beispiel: Um eine Variable<br />

des Typs "Zeichenfolge" zu erstellen, wird diese Klasse mit dem voll<br />

qualifizierten Namen referenziert: java.lang.String.<br />

Die Java-Laufzeitumgebung von Sun und der Sun JDK Java Compiler<br />

benutzen die classpath-Umgebungsvariable, um Klassen zu ermitteln, die im<br />

Java-Programmcode angesprochen werden. Eine classpath-Variable stellt<br />

eine Verbindung zwischen dem Java-Programmcode und dem tatsächlichen<br />

Dateipfad oder dem URL der referenzierten Klassen her. Zum Beispiel<br />

können mit import java.io.* alle Klassen im Paket java.io ohne voll<br />

qualifizierten Namen referenziert werden. Nur der Klassenname ist im<br />

folgenden Java-Code erforderlich, um Klassen aus dem Paket java.io zu<br />

verwenden. Die Umgebungsvariable classpath auf dem System, in dem die<br />

Java-Klassendeklaration kompiliert werden soll, muss den Standort des Java-<br />

Verzeichnisses, also des Stammverzeichnisses des Pakets java.io, enthalten.<br />

Die Umgebungsvariable classpath beeinträchtigt die Laufzeitumgebung von<br />

<strong>Adaptive</strong> Server <strong>Anywhere</strong> <strong>für</strong> Java nicht während des Ausführens von Java-<br />

Vorgängen, da die Klassen in der Datenbank, und nicht in externen Dateien<br />

oder Archiven gespeichert sind.<br />

Die Variable classpath kann jedoch verwendet werden, um den Standort<br />

einer Datei während der Installation von Klassen zu ermitteln. Beispiel: Die<br />

folgende Anweisung installiert eine benutzererstellte Java-Klasse in der<br />

Datenbank, gibt aber nur den Namen der Datei an, nicht ihren vollen<br />

Suchpfad plus Namen. (Beachten Sie, dass in dieser Anweisung keine Java-<br />

Vorgänge enthalten sind.)<br />

INSTALL JAVA NEW<br />

FROM FILE ’Invoice.class’<br />

Wenn die angegebene Datei in einem Verzeichnis oder in einer ZIP-Datei<br />

liegt, die von der Umgebungsvariablen classpath definiert wurden, findet<br />

<strong>Adaptive</strong> Server <strong>Anywhere</strong> die Datei und installiert die Klasse.


Öffentliche Felder<br />

Kapitel 3 Einführung in Java <strong>für</strong> Datenbanken<br />

Beim objektorientierten Programmieren ist es allgemein üblich,<br />

Klassenfelder als "private" zu definieren und ihre Werte nur über öffentliche<br />

Methoden verfügbar zu machen.<br />

Viele Beispiele, die in dieser Dokumentation verwendet werden, geben<br />

Felder als "public" an, sodass die Beispiele kompakter und leichter zu lesen<br />

sind. Die Verwendung öffentlicher Felder in <strong>Adaptive</strong> Server <strong>Anywhere</strong><br />

bietet Performancevorteile gegenüber der Verwendung öffentlicher<br />

Methoden.<br />

Die in dieser Dokumentation allgemein eingehaltene Konvention besteht<br />

darin, dass eine benutzererstellte Java-Klasse, die <strong>für</strong> den Einsatz in<br />

<strong>Adaptive</strong> Server <strong>Anywhere</strong> gedacht ist, ihre Hauptwerte in ihren Feldern<br />

auswirft. Methoden enthalten Berechnungsautomation und Logik, die mit<br />

diesen Feldern arbeiten.<br />

83


Praktische Einführung: Eine Übung mit Java in der Datenbank<br />

Praktische Einführung: Eine Übung mit Java in<br />

der Datenbank<br />

Anforderungen<br />

Ressourcen<br />

84<br />

Diese praktische Einführung soll die Grundlagen <strong>für</strong> den Aufruf von Java-<br />

Vorgängen mit Java-Klassen und Objekten über SQL-Anweisungen<br />

vermitteln. Es wird beschrieben, wie Java-Klassen in der Datenbank<br />

installiert werden. Darüber hinaus wird beschrieben, wie auf die Klasse und<br />

ihre Mitglieder und Methoden von SQL-Anweisungen aus zugegriffen wird.<br />

In der praktischen Einführung wird die in "Ein Java-Seminar" auf Seite 64<br />

erstellte Klasse verwendet.<br />

Die praktische Einführung geht davon aus, dass Java in der Datenbank-<br />

Software installiert wurde. Außerdem wird vorausgesetzt, dass Sie ein Java<br />

Development Kit (JDK) installiert haben, einschließlich dem Java Compiler<br />

(javac).<br />

Quellcode und Anweisungsfolgen <strong>für</strong> dieses Beispiel finden Sie im<br />

Verzeichnis Samples\ASA\JavaInvoice in Ihrem SQL <strong>Anywhere</strong>-<br />

Verzeichnis.<br />

Beispiel-Java-Klasse erstellen und kompilieren<br />

Der erste Schritt besteht darin, den Java-Code zu schreiben und zu<br />

kompilieren. Dies geschieht außerhalb der Datenbank.<br />

v So wird die Klasse erstellt und kompiliert:<br />

1 Erstellen Sie eine Datei mit dem Namen Invoice.java mit dem folgenden<br />

Code:


public class Invoice {<br />

}<br />

Kapitel 3 Einführung in Java <strong>für</strong> Datenbanken<br />

// Felder<br />

public String lineItem1Description;<br />

public double lineItem1Cost;<br />

public String lineItem2Description;<br />

public double lineItem2Cost;<br />

// Eine Instanzmethode<br />

public double totalSum() {<br />

double runningsum;<br />

double taxfactor = 1 + Invoice.rateOfTaxation();<br />

}<br />

runningsum = lineItem1Cost + lineItem2Cost;<br />

runningsum = runningsum * taxfactor;<br />

return runningsum;<br />

// Eine Klassenmethode<br />

public static double rateOfTaxation() {<br />

double rate;<br />

rate = .15;<br />

}<br />

return rate;<br />

Beispiel-Java-Klasse installieren<br />

Den Quellcode <strong>für</strong> diese Klasse finden Sie in der Datei<br />

Samples\ASA\JavaInvoice\Invoice.java in Ihrem SQL <strong>Anywhere</strong>-<br />

Verzeichnis.<br />

2 Kompilieren Sie die Datei, damit die Datei Invoice.class erstellt wird.<br />

Führen Sie von der Befehlszeile im selben Verzeichnis wie Invoice.java<br />

den folgenden Befehl aus.<br />

javac *.java<br />

Die Klasse ist jetzt kompiliert und kann in der Datenbank installiert<br />

werden.<br />

Java-Klassen können erst verwendet werden, nachdem sie in einer<br />

Datenbank installiert wurden. Sie können Java-Klassen aus <strong>Sybase</strong> Central<br />

oder Interactive SQL installieren. Dieser Abschnitt enthält Anweisungen <strong>für</strong><br />

beide Möglichkeiten. Wählen Sie selbst.<br />

85


Praktische Einführung: Eine Übung mit Java in der Datenbank<br />

Hinweise<br />

86<br />

v So installieren Sie die Klasse in der Beispieldatenbank<br />

(<strong>Sybase</strong> Central):<br />

1 Starten Sie <strong>Sybase</strong> Central und stellen Sie eine Verbindung zur<br />

Beispieldatenbank her.<br />

2 Öffnen Sie den Ordner "Java-Objekte" und doppelklicken Sie auf "Java-<br />

Klasse hinzufügen". Der Assistent <strong>für</strong> die Erstellung von Java-Klassen<br />

wird angezeigt.<br />

3 Klicken Sie auf die Schaltfläche "Durchsuchen" und wechseln Sie zur<br />

Klasse Invoice.class im Unterverzeichnis Samples\ASA\JavaInvoice in<br />

Ihrem Installationsverzeichnis von SQL <strong>Anywhere</strong>.<br />

4 Klicken Sie auf "Fertig stellen", damit der Assistent geschlossen wird.<br />

v So installieren Sie die Klasse in der Beispieldatenbank<br />

(Interactive SQL):<br />

1 Starten Sie Interactive SQL und stellen Sie eine Verbindung mit der<br />

Beispieldatenbank her.<br />

2 Geben Sie im Fensterausschnitt "SQL-Anweisungen" in Interactive SQL<br />

den folgenden Befehl ein.<br />

INSTALL JAVA NEW<br />

FROM FILE<br />

’Suchpfad\\samples\\ASA\\JavaInvoice\\Invoice.class’<br />

wobei Suchpfad Ihr SQL <strong>Anywhere</strong>-Verzeichnis ist.<br />

Die Klasse ist jetzt in der Beispieldatenbank installiert.<br />

♦ Bis jetzt haben in der Datenbank keine Java-Vorgänge stattgefunden.<br />

Die Klasse wurde in der Datenbank installiert. Sie kann nun als<br />

Datentyp einer Variablen oder Spalte in einer Tabelle verwendet<br />

werden.<br />

♦ In einer Klassendatei durchgeführte Änderungen werden nicht<br />

automatisch auch in die Kopie der Klasse in der Datenbank übertragen.<br />

Sie müssen die Klassen neu installieren, wenn die Änderungen<br />

wiedergegeben werden sollen.<br />

$ Weitere Hinweise zur Installation der Klassen und zur Aktualisierung<br />

einer installierten Klasse finden Sie unter "Java-Klassen in einer Datenbank<br />

installieren" auf Seite 103.


SQL-Variable vom Typ "Invoice" erstellen<br />

Kapitel 3 Einführung in Java <strong>für</strong> Datenbanken<br />

In diesem Abschnitt wird eine SQL-Variable erstellt, die sich auf ein Java-<br />

Objekt vom Typ Invoice bezieht.<br />

Berücksichtigung von Groß-/Kleinschreibung<br />

Java berücksichtigt die Groß/Kleinschreibung, sodass die Teile der<br />

nachstehenden Beispiele, die Java-Syntax beinhalten, genauso<br />

geschrieben werden müssen wie gezeigt. Die SQL-Syntax wird mit<br />

Großbuchstaben geschrieben.<br />

1 Führen Sie von Interactive SQL aus die folgende Anweisung aus und<br />

erstellen Sie eine SQL-Variable mit dem Namen Inv vom Typ Invoice,<br />

wobei Invoice die Java-Klasse ist, die Sie in der Datenbank installiert<br />

haben:<br />

CREATE VARIABLE Inv Invoice<br />

Nach dem Erstellen einer Variablen kann ihr erst dann ein Wert<br />

zugewiesen werden, wenn Datentyp und deklarierter Datentyp identisch<br />

sind oder wenn der Wert eine Unterklasse des deklarierten Datentyps ist.<br />

Im vorliegenden Fall kann die Variable Inv nur eine Referenz auf ein<br />

Objekt des Typs Invoice oder eine Unterklasse von Invoice enthalten.<br />

Anfangs ist die Variable Inv gleich NULL, weil kein Wert an sie<br />

weitergeleitet wurde.<br />

2 Führen Sie die folgende Anweisung aus, damit der aktuelle Wert der<br />

Variablen Inv identifiziert wird.<br />

select IfNull(Inv,<br />

’Kein Objekt referenziert’,<br />

'Variable ist nicht null: enthält eine<br />

Objektreferenz')<br />

Die Variable referenziert derzeit kein Objekt.<br />

3 Weisen Sie Inv einen Wert zu.<br />

Sie müssen die Klasse Invoice mit dem Schlüsselwort NEW<br />

instanzieren.<br />

SET Inv = NEW Invoice();<br />

Die Variable Inv hat jetzt eine Referenz auf das Java-Objekt. Zur<br />

Überprüfung können Sie die Anweisung aus Schritt 2 ausführen.<br />

Die Variable Inv enthält eine Referenz auf ein Java-Objekt vom Typ<br />

Invoice. Mit dieser Referenz können Sie auf viele Felder des Objekts<br />

zugreifen oder eine ihrer Methoden aufrufen.<br />

87


Praktische Einführung: Eine Übung mit Java in der Datenbank<br />

Auf Felder und Methoden des Java-Objekts zugreifen<br />

88<br />

Wenn eine Variable (oder ein Spaltenwert in einer Tabelle) eine Referenz auf<br />

ein Java-Objekt enthält, können den Feldern des Objekts Werte übergeben<br />

werden, und ihre Methoden sind aufrufbar.<br />

Beispiel: Eine Variable vom Typ "Invoice", die Sie im vorigen Abschnitt<br />

erstellt haben, enthält eine Referenz auf ein Objekt Invoice und hat vier<br />

Felder, deren Werte durch SQL-Anweisungen festgelegt werden können.<br />

v So greifen Sie auf die Felder des Objekts "Invoice" zu:<br />

1 Führen Sie von Interactive SQL die folgenden SQL-Anweisungen aus,<br />

damit die Feldwerte <strong>für</strong> die Variable Inv gesetzt werden.<br />

SET Inv.lineItem1Description = ’Gummistiefel’;<br />

SET Inv.lineItem1Cost = ’79.99’;<br />

SET Inv.lineItem2Description = ’Heugabel’;<br />

SET Inv.lineItem2Cost = ’37.49’;<br />

Jede der oben stehenden SQL-Anweisungen gibt einen Wert an ein Feld<br />

im Java-Objekt weiter, das durch Inv referenziert wird.<br />

2 Führen Sie SELECT-Anweisungen mit der Variablen aus. Jede<br />

nachstehende SQL-Anweisung gibt den aktuellen Wert eines Feldes im<br />

Java-Objekt zurück, das von Inv referenziert wird.<br />

SELECT Inv.lineItem1Description;<br />

SELECT Inv.lineItem1Cost;<br />

SELECT Inv.lineItem2Description;<br />

SELECT Inv.lineItem2Cost;<br />

3 Verwenden Sie ein Feld der Variablen Inv in einem SQL-Ausdruck.<br />

Führen Sie die folgende SQL-Anweisung aus und lassen Sie die obigen<br />

SQL-Anweisungen ausführen.<br />

SELECT * FROM PRODUCT<br />

WHERE unit_price < Inv.lineItem2Cost;<br />

Zusätzlich zu den öffentlichen Feldern hat die Klasse Invoice eine<br />

Instanzmethode, die Sie aufrufen können.<br />

v So rufen Sie die Methoden des Objekts "Invoice" auf:<br />

♦ Führen Sie von Interactive SQL aus die folgende SQL-Anweisung aus,<br />

die die Methode totalSum() des Objekts aufruft, das von der Variablen<br />

Inv referenziert wird. Sie gibt die Summe der beiden Kostenfelder plus<br />

der Steuer zurück.


Methoden aufrufen<br />

und Felder<br />

referenzieren<br />

SELECT Inv.totalSum();<br />

Kapitel 3 Einführung in Java <strong>für</strong> Datenbanken<br />

Hinter Methodennamen stehen immer Klammern, auch wenn sie keine<br />

Argumente annehmen. Nach Feldnamen stehen keine Klammern.<br />

Die Methode totalSum() akzeptiert keine Argumente, sondern gibt einen<br />

Wert zurück. Die Klammern werden verwendet, da eine Java-Operation<br />

aufgerufen wird, obwohl die Methode keine Argumente annimmt.<br />

Bei Java in der Datenbank ist der direkte Feldzugriff schneller als der Aufruf<br />

von Methoden. Für den Zugriff auf ein Feld ist der Aufruf der Java VM nicht<br />

erforderlich, während <strong>für</strong> eine Methode die VM benötigt wird, um die<br />

Methode auszuführen.<br />

Wie in der am Anfang dieses Kapitels beschriebenen Invoice-<br />

Klassendefinition gezeigt, nutzt die totalSum-Instanzenmethode die<br />

Klassenmethode rateOfTaxation.<br />

Auf diese Klassenmethode kann direkt aus einer SQL-Anweisung<br />

zugegriffen werden.<br />

SELECT Invoice.rateOfTaxation();<br />

Beachten Sie, dass der Name der Klasse verwendet wird, und nicht der Name<br />

einer Variablen, die eine Referenz auf ein Invoice-Objekt enthält. Dies<br />

stimmt mit der Art überein, wie Java Klassenmethoden verarbeitet, auch<br />

wenn sie in SQL-Anweisungen verwendet werden. Eine Klassenmethode<br />

kann aufgerufen werden, auch wenn kein auf dieser Klasse basierendes<br />

Objekt instanziert wurde.<br />

Klassenmethoden benötigen keine Instanz der Klasse, um richtig zu<br />

funktionieren, können aber immer noch <strong>für</strong> ein Objekt aufgerufen werden.<br />

Die folgende SQL-Anweisung bringt dieselben Ergebnisse wie die vorher<br />

ausgeführte SQL-Anweisung.<br />

SELECT Inv.rateOfTaxation();<br />

Java-Objekte in Tabellen speichern<br />

Wenn eine Klasse in einer Datenbank installiert wird, steht sie als neuer<br />

Datentyp zur Verfügung. Spalten in einer Tabelle können den Typ Javaclass<br />

haben, wobei Javaclass der Name einer installierten öffentlichen Java-Klasse<br />

ist. Dann können Sie ein Java-Objekt erstellen und es als Wert einer Spalte in<br />

eine Tabelle einfügen.<br />

v So wird die Klasse "Invoice" in einer Tabelle verwendet:<br />

1 Tabelle mit einer Spalte vom Typ Invoice erstellen.<br />

Führen Sie von Interactive SQL die folgende SQL-Anweisung aus.<br />

89


Praktische Einführung: Eine Übung mit Java in der Datenbank<br />

90<br />

CREATE TABLE T1 (<br />

ID int,<br />

JCol Invoice<br />

);<br />

Die Spalte namens JCol akzeptiert nur Objekte des Typs Invoice oder<br />

einer ihrer Unterklassen.<br />

2 Führen Sie mit der Variablen Inv, die eine Referenz auf ein Java-Objekt<br />

vom Typ Invoice enthält, die folgende SQL-Anweisung aus, damit der<br />

Tabelle T1 eine Zeile hinzugefügt wird.<br />

INSERT INTO T1<br />

VALUES( 1, Inv );<br />

Sobald ein Objekt der Tabelle T1 hinzugefügt wurde, können Sie<br />

Auswahlanweisungen benutzen, die die Felder und Methoden der<br />

Objekte in der Tabelle einbeziehen.<br />

3 Führen Sie die folgende SQL-Anweisung aus, die den Wert des Feldes<br />

ineItem1Description <strong>für</strong> alle Objekte in der Tabelle T1 zurück (derzeit<br />

sollte nur ein Objekt in der Tabelle sein).<br />

SELECT ID, JCol.lineItem1Description<br />

FROM T1;<br />

Sie können ähnliche Auswahlanweisungen ausführen, die andere Felder<br />

und Methoden des Objekts einbeziehen.<br />

4 Eine zweite Methode, ein Java-Objekt zu erstellen und einer Tabelle<br />

hinzuzufügen, bezieht den folgenden Ausdruck ein, der immer ein Java-<br />

Objekt erstellt und ihm eine Referenz zurückgibt.<br />

NEW Java-Klassenname()<br />

5 Dieser Ausdruck kann auf verschiedene Arten benutzt werden.<br />

Beispielsweise wird mit der folgenden SQL-Anweisung ein Java-Objekt<br />

erstellt und in die Tabelle T1 eingefügt.<br />

INSERT INTO T1<br />

VALUES ( 2, NEW Invoice() );<br />

6 Führen Sie die folgende SQL-Anweisung aus, damit geprüft wird, ob<br />

diese beiden Objekte als Werte der Spalte JCol in der Tabelle T1<br />

gespeichert wurden.<br />

select id, JCol.totalSum()<br />

FROM t1<br />

Die Ergebnisse der Spalte JCol (zweite von der oben genannten<br />

Anweisung zurückgegebene Zeile) sollte 0 sein, da die Felder in diesem<br />

Objekt keine Werte haben und die Methode totalSum eine Berechnung<br />

dieser Felder ist.


Objekt mit einer Abfrage zurückgeben<br />

Kapitel 3 Einführung in Java <strong>für</strong> Datenbanken<br />

Außer auf Felder und Methoden zuzugreifen, können Sie mit einer Abfrage<br />

auch ein ganzes Objekt aus der Tabelle abrufen.<br />

v So greifen Sie auf Invoice-Objekte zu, die in einer Tabelle<br />

gespeichert sind:<br />

♦ Führen Sie von Interactive SQL aus die folgenden Anweisungen aus,<br />

erstellen Sie eine neue Variable und übergeben Sie ihr einen Wert (Sie<br />

kann nur eine Referenz auf ein Objekt vom Typ "Invoice" enthalten).<br />

Die an die Variable übergebene Objektreferenz wurde mit der Tabelle<br />

T1 erstellt.<br />

CREATE VARIABLE Inv2 Invoice;<br />

set Inv2 = (select JCol from T1 where ID = 2);<br />

SET Inv2.lineItem1Description = 'Süßigkeiten';<br />

SET Inv2.lineItem2Description = 'Sicherheitsgurt';<br />

Der Wert <strong>für</strong> das Feld lineItem1Description und lineItem2Description<br />

wurde in der Variablen Inv2 geändert, jedoch nicht in der Tabelle, die<br />

die Quelle <strong>für</strong> den Wert dieser Variablen war.<br />

Dies ist konsistent mit der Art, in der SQL-Variable derzeit verarbeitet<br />

werden: Die Variable Inv enthält eine Referenz auf ein Java-Objekt. Der<br />

Wert in der Tabelle, die als Quelle <strong>für</strong> die Variablenreferenz diente, wird<br />

erst geändert, wenn eine UPDATE-Anweisung ausgeführt wird.<br />

91


Praktische Einführung: Eine Übung mit Java in der Datenbank<br />

92


KAPITEL 4<br />

Java in der Datenbank benutzen<br />

Über dieses<br />

Kapitel<br />

Inhalt<br />

Bevor Sie<br />

beginnen<br />

In diesem Kapitel wird beschrieben, wie Sie Java-Klassen und Objekte Ihrer<br />

Datenbank hinzufügen und wie Sie diese Objekte in einer relationalen<br />

Datenbank einsetzen.<br />

Thema Seite<br />

Einleitung 94<br />

Datenbank <strong>für</strong> Java aktivieren 97<br />

Java-Klassen in einer Datenbank installieren 103<br />

Spalten <strong>für</strong> die Aufnahme von Java-Objekten erstellen 109<br />

Java-Objekte einfügen, aktualisieren und löschen 111<br />

Java-Objekte abfragen 117<br />

Java-Felder und Objekte vergleichen 119<br />

Besondere Funktionen von Java-Klassen in der Datenbank 123<br />

So werden Java-Objekte gespeichert 130<br />

Java-Datenbankdesign 133<br />

Berechnete Spalten mit Java-Klassen verwenden 137<br />

Speicher <strong>für</strong> Java konfigurieren 140<br />

Vor den Beispielen in diesem Kapitel müssen Sie die Datei<br />

Samples\ASA\Java\jdemo.sql in Ihrem SQL <strong>Anywhere</strong>-Verzeichnis<br />

ausführen.<br />

$ Weitere Hinweise und vollständige Anweisungen finden Sie unter<br />

"Java-Beispiele einrichten" auf Seite 94.<br />

93


Einleitung<br />

Einleitung<br />

Java-Beispiele einrichten<br />

94<br />

Dieses Kapitel erläutert, wie Sie Aufgaben mit Java in der Datenbank<br />

ausführen:<br />

♦ Datenbank <strong>für</strong> Java aktivieren Sie müssen bestimmte Maßnahmen<br />

treffen, damit Ihre Datenbank <strong>für</strong> die Arbeit mit Java aktiviert wird.<br />

♦ Java-Klassen installieren Sie müssen Java-Klassen in einer Datenbank<br />

installieren, damit sie <strong>für</strong> Aufgaben auf dem Server zur Verfügung<br />

stehen.<br />

♦ Eigenschaften der Java-Spalten Dieser Abschnitt erläutert, wie<br />

Spalten mit Java-Klassen-Datentypen in das relationale<br />

Datenbankmodell passen.<br />

♦ Datenbankdesign <strong>für</strong> Java In diesem Abschnitt werden Tipps <strong>für</strong> das<br />

Design von Datenbanken gegeben, die Java-Klassen benutzen.<br />

Viele Beispiele in diesem Kapitel werden mit einer Gruppe von Klassen und<br />

Tabellen ausgeführt, die der Beispieldatenbank hinzugefügt wurden. Die<br />

Tabellen enthalten dieselben Daten wie Tabellen desselben Namens in der<br />

Beispieldatenbank, nur gehören sie einem Benutzer namens jdba. Sie<br />

benutzen Java-Klassen-Datentypen anstelle von einfachen relationalen<br />

Typen <strong>für</strong> die Daten. Das Beispiel finden Sie im Unterverzeichnis<br />

Samples\ASA\Java Ihres SQL <strong>Anywhere</strong>-Verzeichnisses.<br />

Beispieltabellen sind nur <strong>für</strong> die praktische Einführung gedacht<br />

Die Beispieltabellen sollen unterschiedliche Java-Funktionen darstellen.<br />

Sie sind keinesfalls als Muster <strong>für</strong> das Design Ihrer Datenbank zu<br />

empfehlen. Überlegen Sie sich die konkreten Anforderungen in Ihrem<br />

Datenbanksystem, wenn Sie ermitteln wollen, an welchen Stellen Java-<br />

Datentypen und andere Java-Merkmale in die Datenbank eingebaut<br />

werden sollen.<br />

Die Java-Beispiele werden in zwei Schritten eingerichtet:<br />

1 Aktivieren Sie die Beispieldatenbank <strong>für</strong> Java.<br />

2 Fügen Sie die Java-Beispielklassen und –tabellen hinzu.


Kapitel 4 Java in der Datenbank benutzen<br />

v So wird die Beispieldatenbank <strong>für</strong> Java aktiviert:<br />

1 Starten Sie Interactive SQL und stellen Sie eine Verbindung mit der<br />

Beispieldatenbank her.<br />

2 Geben Sie im Fensterausschnitt "SQL-Anweisungen" in Interactive SQL<br />

die folgende Anweisung ein.<br />

ALTER DATABASE UPGRADE JAVA JDK ’1.3’<br />

3 Schließen Sie Interactive SQL und die Beispieldatenbank.<br />

Die Beispieldatenbank asademo.db muss zunächst heruntergefahren<br />

werden, damit Sie die Java-Funktionen benutzen können.<br />

v So fügen Sie Java-Klassen und Tabellen der Beispieldatenbank<br />

hinzu:<br />

1 Starten Sie Interactive SQL und stellen Sie eine Verbindung mit der<br />

Beispieldatenbank her.<br />

2 Geben Sie im Fensterausschnitt "SQL-Anweisungen" in Interactive SQL<br />

die folgende Anweisung ein:<br />

READ "Suchpfad\\Samples\\ASA\\Java\\jdemo.sql"<br />

wobei Suchpfad Ihr SQL <strong>Anywhere</strong>-Verzeichnis ist. Damit werden die<br />

Instruktionen in der Befehlsdatei jdemo.sql ausgeführt. Die<br />

Instruktionen benötigen eventuell einige Zeit, bis sie abgeschlossen sind.<br />

Sie können das Skript Samples\ASA\Java\jdemo.sql mit einem Texteditor<br />

öffnen. Es führt folgende Programmschritte aus:<br />

1 Es installiert die Klasse JDBCExamples.<br />

2 Es erstellt einen Benutzer namens JDBA mit dem Kennwort SQL und<br />

DBA-Berechtigung, und setzt den aktuellen Benutzer als JDBA ein.<br />

3 Es installiert eine JAR-Datei namens asademo.jar. Diese Datei enthält<br />

die Klassendefinitionen, die in den Tabellen verwendet werden.<br />

4 Es erstellt die folgenden Tabellen unter der Benutzer-ID JDBA:<br />

♦ product<br />

♦ contact<br />

♦ customer<br />

♦ employee<br />

♦ sales_order<br />

♦ sales_order_items<br />

95


Einleitung<br />

96<br />

Dies ist eine Teilmenge der Tabellen in der Beispieldatenbank.<br />

5 Es fügt die Daten aus den Standardtabellen mit identischen Namen in<br />

die Java-Tabellen ein. Dieser Verfahrensschritt benutzt INSERT- und<br />

SELECT-Anweisungen. Dieser Schritt kann einige Zeit in Anspruch<br />

nehmen.<br />

6 Es erstellt einige Indizes und Fremdschlüssel, um dem Schema<br />

Integritätsregeln hinzuzufügen.<br />

Laufzeitumgebung <strong>für</strong> Java verwalten<br />

Aufgaben bei der<br />

Verwaltung von<br />

Java<br />

Tools zum<br />

Verwalten von<br />

Java<br />

Die Laufzeitumgebung <strong>für</strong> Java besteht aus folgenden Komponenten:<br />

♦ <strong>Sybase</strong> Java Virtual Machine Die VM läuft im Datenbankserver,<br />

interpretiert kompilierte Java-Klassen und führt sie aus.<br />

♦ Integrierte Java-Klassen Wenn Sie eine Datenbank erstellen, wird eine<br />

Serie von Java-Klassen <strong>für</strong> die Datenbank verfügbar. Für Java-<br />

Anwendungen in der Datenbank müssen diese Klassen fehlerfrei<br />

funktionieren.<br />

Um eine Laufzeitumgebung <strong>für</strong> Java bereitzustellen, müssen Sie folgende<br />

Aufgaben durchführen:<br />

♦ Datenbank <strong>für</strong> Java aktivieren Bei dieser Aufgabe müssen Sie die<br />

Verfügbarkeit von integrierten Klassen und das Upgrade auf Standards<br />

der Version 8 prüfen.<br />

$ Weitere Hinweise finden Sie unter "Datenbank <strong>für</strong> Java aktivieren"<br />

auf Seite 97.<br />

♦ Installieren Sie andere Klassen, die die Benutzer brauchen Im<br />

Verlauf dieser Aufgabe sorgen Sie da<strong>für</strong>, dass andere Klassen als die<br />

Laufzeitklassen installiert werden und auf dem letzten Stand sind.<br />

$ Weitere Hinweise finden Sie unter "Java-Klassen in einer<br />

Datenbank installieren" auf Seite 103.<br />

♦ Konfiguration des Servers Sie müssen Ihren Server so konfigurieren,<br />

dass der erforderliche Speicher <strong>für</strong> das Ausführen von Java-Aufgaben<br />

vorhanden ist.<br />

$ Weitere Hinweise finden Sie unter "Speicher <strong>für</strong> Java<br />

konfigurieren" auf Seite 140.<br />

Sie können alle diese Aufgaben aus <strong>Sybase</strong> Central oder Interactive SQL<br />

ausführen.


Datenbank <strong>für</strong> Java aktivieren<br />

Java-Aktivierung<br />

der Datenbank<br />

manchmal nicht<br />

erforderlich<br />

Kapitel 4 Java in der Datenbank benutzen<br />

Die <strong>Adaptive</strong> Server <strong>Anywhere</strong> Laufzeitumgebung <strong>für</strong> Java benötigt eine<br />

Java VM und die Java-Laufzeitklassen von <strong>Sybase</strong>. Erst nachdem Sie eine<br />

Datenbank <strong>für</strong> Java aktiviert haben, können Sie sie mit Java-Laufzeitklassen<br />

benutzen.<br />

Java in der Datenbank ist eine separat lizenzierte Komponente von<br />

SQL <strong>Anywhere</strong> Studio.<br />

Neue Datenbanken sind standardmäßig nicht <strong>für</strong> Java aktiviert<br />

Standardmäßig ist eine Datenbank nicht <strong>für</strong> Java aktiviert, wenn Sie sie in<br />

<strong>Adaptive</strong> Server <strong>Anywhere</strong> neu erstellen.<br />

Java ist eine Programmiersprache mit einer Einzelhierarchie. Das bedeutet,<br />

dass alle Klassen, die Sie erstellen oder benutzen, von einer Klasse erben.<br />

Das bedeutet weiterhin, dass die Klassen der niedrigsten Ebene (also in der<br />

Hierarchie weiter oben angesiedelt) vorhanden sein müssen, bevor Klassen<br />

der oberen Ebene benutzt werden können. Die Basisgruppe der<br />

erforderlichen Klassen <strong>für</strong> Java-Anwendungen wird als Laufzeit-Java-<br />

Klassen oder Java-API bezeichnet.<br />

Durch das Bereitstellen einer Datenbank <strong>für</strong> Java werden in die<br />

Systemtabellen zahlreiche Einträge eingefügt. Dies vergrößert die Datenbank<br />

und erfordert rund 200 KByte mehr Speicher zum Ausführen der Datenbank,<br />

auch wenn Sie keine Java-Funktionen verwenden.<br />

Wenn Sie Java nicht verwenden werden und eine Umgebung mit begrenzter<br />

Speicherkapazität haben, sollten Sie die Datenbank nicht <strong>für</strong> Java aktivieren.<br />

Die Java-Laufzeitklassen <strong>für</strong> <strong>Sybase</strong><br />

Die Java-Laufzeitklassen <strong>für</strong> <strong>Sybase</strong> befinden sich auf der Festplatte, und<br />

nicht in der Datenbank wie andere Klassen. Die folgenden Dateien enthalten<br />

die Java-Laufzeitklassen <strong>für</strong> <strong>Sybase</strong>. Sie werden im Unterverzeichnis Java<br />

Ihres SQL <strong>Anywhere</strong>-Verzeichnisses gespeichert.<br />

♦ 1.1\classes.zip Diese Datei, lizenziert von Sun Microsystems, enthält<br />

einen Teil der Java-Laufzeitklassen <strong>für</strong> JDK 1.1.8 von Sun<br />

Microsystems.<br />

♦ 1.3\rt.jar Diese Datei, lizenziert von Sun Microsystems, enthält einen<br />

Teil der Java-Laufzeitklassen <strong>für</strong> JDK 1.3 von Sun Microsystems.<br />

97


Datenbank <strong>für</strong> Java aktivieren<br />

JAR-Dateien<br />

Installierte Pakete<br />

98<br />

♦ asajdbc.zip Diese Datei enthält interne JDBC-Treiber-Klassen von<br />

<strong>Sybase</strong> <strong>für</strong> JDK 1.1.<br />

♦ asajrt12.zip Diese Datei enthält interne JDBC-Treiber-Klassen von<br />

<strong>Sybase</strong> <strong>für</strong> JDK 1.2 und JDK 1.3.<br />

Wenn Sie eine Datenbank <strong>für</strong> Java aktivieren, werden die Systemtabellen mit<br />

einer Liste verfügbarer Klassen aus den System-JAR-Dateien aktualisiert.<br />

Sie können dann die Klassenhierarchie aus <strong>Sybase</strong> Central durchsuchen, die<br />

Klassen selbst aber sind in der Datenbank nicht vorhanden.<br />

Die Datenbank speichert Laufzeit-Klassennamen unter folgenden JAR-<br />

Dateien:<br />

♦ ASAJRT Klassennamen aus asajdbc.zip werden hier gespeichert.<br />

♦ ASAJDBCDRV Klassennamen aus jdbcdrv.zip werden hier gespeichert.<br />

♦ ASASystem Klassennamen aus classes.zip werden hier gespeichert.<br />

Diese Laufzeitklassen enthalten die folgenden Pakete:<br />

♦ java Die hier gespeicherten Pakete sind die unterstützten Java-<br />

Laufzeitklassen von Sun Microsystems.<br />

$ Eine Liste der unterstützten Java-Laufzeitklassen finden Sie unter<br />

"Unterstützte Java-Pakete" auf Seite 87 der Dokumentation ASA SQL-<br />

Referenzhandbuch.<br />

♦ com.sybase Die hier gespeicherten Pakete bieten serverseitige JDBC-<br />

Unterstützung.<br />

♦ sun Sun Microsystems bietet die hier gespeicherten Pakete an.<br />

♦ sybase.sql Die hier gespeicherten Pakete sind Teil der serverseitigen<br />

JDBC-Unterstützung von <strong>Sybase</strong>.<br />

Vorsicht: Installieren Sie keine Klassen von einer anderen<br />

Version des Sun JDK<br />

Klassen im Sun JDK haben identische Namen wie die Java-<br />

Laufzeitklassen <strong>für</strong> <strong>Sybase</strong>, die in jeder Datenbank installiert werden<br />

müssen, in denen Java-Vorgänge ausgeführt werden sollen.<br />

Sie dürfen die Datei classes.zip, die mit <strong>Adaptive</strong> Server <strong>Anywhere</strong><br />

mitgeliefert wird, nicht ersetzen. Wenn Sie eine andere Version dieser<br />

Klassen verwenden, könnten sich daraus Kompatibilitätsprobleme mit der<br />

<strong>Sybase</strong> Java Virtual Machine ergeben.<br />

Eine Aktivierung einer Datenbank <strong>für</strong> Java dürfen Sie nur so vornehmen,<br />

wie dies in diesem Abschnitt beschrieben wird.


Methoden zur Java-Aktivierung einer Datenbank<br />

Datenbanken<br />

erstellen<br />

Upgrade einer<br />

Datenbank<br />

Kapitel 4 Java in der Datenbank benutzen<br />

Sie können Datenbanken bei der Erstellung, beim Upgrade oder zu einem<br />

späteren Zeitpunkt in einem separaten Vorgang <strong>für</strong> Java aktivieren.<br />

Sie können eine <strong>für</strong> Java aktivierte Datenbank wie folgt erstellen:<br />

♦ Benutzen Sie die Anweisung CREATE DATABASE.<br />

$ Hinweise zur Syntax finden Sie unter "CREATE DATABASE-<br />

Anweisung" auf Seite 298 der Dokumentation ASA SQL-<br />

Referenzhandbuch.<br />

♦ Benutzen Sie das Dienstprogramm dbinit.<br />

$ Hinweise finden Sie unter "Datenbank mit dem<br />

Befehlszeilenprogramm ""dbinit"" erstellen" auf Seite 516 der<br />

Dokumentation ASA Datenbankadministration.<br />

♦ <strong>Sybase</strong> Central<br />

$ Hinweise finden Sie unter "Datenbank erstellen" auf Seite 31 der<br />

Dokumentation ASA SQL-Benutzerhandbuch.<br />

Ein Upgrade einer Datenbank auf eine <strong>für</strong> Java aktivierte Datenbank der<br />

Version 8 können Sie wie folgt durchführen:<br />

♦ Benutzen Sie die Anweisung ALTER DATABASE.<br />

$ Hinweise zur Syntax finden Sie unter "ALTER DATABASE-<br />

Anweisung" auf Seite 224 der Dokumentation ASA SQL-<br />

Referenzhandbuch.<br />

♦ Benutzen Sie das Upgrade-Dienstprogramm dbupgrad.exe.<br />

$ Hinweise finden Sie unter "Upgrade einer Datenbank mit dem<br />

Befehlszeilenprogramm ""dbupgrad""" auf Seite 583 der Dokumentation<br />

ASA Datenbankadministration.<br />

♦ <strong>Sybase</strong> Central.<br />

$ Weitere Hinweise finden Sie unter "Datenbank <strong>für</strong> Java aktivieren"<br />

auf Seite 101.<br />

Wenn Sie Java in der Datenbank nicht installieren, bleiben alle<br />

Datenbankvorgänge, die keine Java-Vorgänge einschließen, voll<br />

funktionsfähig und laufen wie vorgesehen ab.<br />

99


Datenbank <strong>für</strong> Java aktivieren<br />

Neue Datenbanken und Java<br />

CREATE<br />

DATABASE-<br />

Optionen<br />

Dienstprogramm<br />

<strong>für</strong> die<br />

Initialisierung der<br />

Datenbank<br />

100<br />

Die Java-Laufzeitklassen <strong>für</strong> <strong>Sybase</strong> werden bei <strong>Adaptive</strong> Server <strong>Anywhere</strong><br />

standardmäßig nicht jedesmal installiert, wenn Sie eine Datenbank erstellen.<br />

Die Installation dieser separat zu lizenzierenden Komponente ist fakultativ<br />

und wird über die Methode gesteuert, mit der Sie die Datenbank erstellen.<br />

Die SQL-Anweisung CREATE DATABASE hat eine Option namens JAVA.<br />

Wenn Sie die Datenbank <strong>für</strong> Java aktivieren wollen, setzen Sie diese Option<br />

auf ON. Wenn Sie Java deaktivieren wollen, setzen Sie die Option auf OFF.<br />

Standardmäßig ist die Option auf OFF gesetzt.<br />

Beispielsweise erstellt die folgende Anweisung eine Datei <strong>für</strong> eine Javaaktivierte<br />

Datenbank namens temp.db:<br />

CREATE DATABASE ’c:\\sybase\\asa8\\temp’ JAVA ON<br />

Die folgende Anweisung erstellt eine Datenbankdatei temp2.db, die Java<br />

nicht unterstützt:<br />

CREATE DATABASE ’c:\\sybase\\asa8\\temp2’<br />

Datenbanken können mit dem Dienstprogramm dbinit.exe erstellt werden.<br />

Das Dienstprogramm verfügt über Parameter, mit denen gesteuert wird, ob<br />

die Java-Laufzeitklassen in der neu installierten Datenbank installiert<br />

werden. Standardmäßig werden diese Klassen nicht installiert.<br />

Die gleichen Optionen sind verfügbar, wenn Sie eine Datenbank mit <strong>Sybase</strong><br />

Central erstellen.<br />

Upgrade von Datenbanken und Java<br />

Dienstprogramm<br />

<strong>für</strong> das Datenbank-<br />

Upgrade<br />

Für vorhandene Datenbanken, die mit früheren Versionen der Software<br />

erstellt wurden, kann ein Upgrade durchgeführt werden, und zwar mit dem<br />

Dienstprogramm <strong>für</strong> den Datenbank-Upgrade oder mit der Anweisung<br />

ALTER DATABASE.<br />

Das Upgrade <strong>für</strong> Datenbanken auf den Standard von <strong>Adaptive</strong> Server<br />

<strong>Anywhere</strong> Version 8 erfolgt mit dem Dienstprogramm dbupgrad.exe. Der<br />

Parameter –jr verhindert die Installation der Java-Laufzeitklassen von<br />

<strong>Sybase</strong>.<br />

$ Hinweise über die Bedingungen <strong>für</strong> das Einbeziehen von Java in die<br />

Upgrade-Datenbank finden Sie unter "Upgrade einer Datenbank mit dem<br />

Befehlszeilenprogramm ""dbupgrad""" auf Seite 583 der Dokumentation<br />

ASA Datenbankadministration.


Datenbank <strong>für</strong> Java aktivieren<br />

Kapitel 4 Java in der Datenbank benutzen<br />

Wenn Sie eine Datenbank erstellt oder ein Upgrade einer Datenbank<br />

durchgeführt, dabei aber die Option so gesetzt haben, dass die Datenbank<br />

nicht <strong>für</strong> Java aktiviert wurde, können Sie die erforderlichen Java-Klassen<br />

über <strong>Sybase</strong> Central oder Interactive SQL auch zu einem späteren Zeitpunkt<br />

hinzufügen.<br />

v Um der Datenbank die Java-Laufzeitklassen <strong>für</strong> <strong>Sybase</strong><br />

hinzuzufügen, gehen Sie wie folgt vor (<strong>Sybase</strong> Central):<br />

1 Stellen Sie von <strong>Sybase</strong> Central aus als Benutzer mit DBA-Berechtigung<br />

eine Verbindung her.<br />

2 Rechtsklicken Sie auf die Datenbank und wählen Sie "Upgrade einer<br />

Datenbank".<br />

3 Klicken Sie auf der einführenden Seite des Assistenten auf "Weiter".<br />

4 Wählen Sie die Datenbank, <strong>für</strong> die das Upgrade vorgenommen werden<br />

soll, aus der Liste aus.<br />

5 Sie können gegebenenfalls eine Sicherungskopie der Datenbank anlegen<br />

lassen. Klicken Sie auf "Weiter".<br />

6 Falls erwünscht, kann jConnect-Metadaten-Unterstützung installiert<br />

werden. Klicken Sie auf "Weiter"<br />

7 Wählen Sie die Option "Java-Unterstützung installieren". Sie müssen<br />

außerdem die Version des JDK festlegen, die installiert werden soll. Die<br />

Standardklassen sind JDK 1.3-Klassen. Für Version 7.x-Datenbanken<br />

sind die Standardklassen JDK 1.1.8-Klassen.<br />

8 Befolgen Sie die restlichen Anweisungen im Assistenten.<br />

v Um die Java-Laufzeitklassen <strong>für</strong> <strong>Sybase</strong> der Datenbank<br />

hinzuzufügen, gehen Sie wie folgt vor (Interactive SQL):<br />

1 Verbinden Sie sich mit der Datenbank aus Interactive SQL als Benutzer<br />

mit DBA-Berechtigung.<br />

2 Führen Sie folgende Anweisung aus:<br />

ALTER DATABASE UPGRADE JAVA ON<br />

$ Weitere Hinweise finden Sie unter "ALTER DATABASE-<br />

Anweisung" auf Seite 224 der Dokumentation ASA SQL-<br />

Referenzhandbuch.<br />

3 Starten Sie die Datenbank neu, damit die Java-Unterstützung wirksam<br />

wird.<br />

101


Datenbank <strong>für</strong> Java aktivieren<br />

Mit <strong>Sybase</strong> Central eine Datenbank <strong>für</strong> Java aktivieren<br />

102<br />

Sie können <strong>Sybase</strong> Central <strong>für</strong> die Erstellung von Datenbanken über<br />

Assistenten benutzen. Während der Erstellung oder des Upgrades einer<br />

Datenbank fordert der Assistent Sie auf, auszuwählen, ob die Java-<br />

Laufzeitklassen <strong>für</strong> <strong>Sybase</strong> installiert werden. Standardmäßig ist diese<br />

Option so gesetzt, dass die Datenbank <strong>für</strong> Java aktiviert wird.<br />

Die Erstellung oder das Upgrade einer Datenbank werden in <strong>Sybase</strong> Central<br />

wie folgt vorgenommen:<br />

♦ Wählen Sie "Datenbank erstellen" aus dem Ordner "Dienstprogramme".<br />

♦ Wählen Sie "Upgrade einer Datenbank" aus dem Ordner<br />

"Dienstprogramme", wenn Sie eine Datenbank von einer früheren<br />

Version der Software auf eine Datenbank mit Java-Funktionen umstellen<br />

wollen.


Kapitel 4 Java in der Datenbank benutzen<br />

Java-Klassen in einer Datenbank installieren<br />

Klasse erstellen<br />

Bevor Sie eine Java-Klasse in einer Datenbank installieren, müssen Sie sie<br />

kompilieren. Sie haben mehrere Methoden zur Auswahl, um Java-Klassen zu<br />

installieren:<br />

♦ Einzelne Klasse Sie können eine einzelne Klasse in einer Datenbank<br />

aus einer kompilierten Klassendatei installieren. Klassendateien haben<br />

normalerweise die Erweiterung .class.<br />

♦ JAR-Datei Sie können eine Serie von Klassen auf einmal installieren,<br />

wenn sie in einer komprimierten oder unkomprimierten JAR-Datei<br />

zusammengefasst sind. JAR-Dateien haben normalerweise die<br />

Erweiterung .jar oder .zip. <strong>Adaptive</strong> Server <strong>Anywhere</strong> unterstützt alle<br />

komprimierten JAR-Dateien, die mit dem SUN-JAR-Dienstprogramm,<br />

sowie anderen JAR-Kompressionsschemata, erstellt werden.<br />

Dieser Abschnitt beschreibt, wie Java-Klassen installiert werden, nachdem<br />

Sie sie kompiliert haben. Sie müssen über die DBA-Berechtigung verfügen,<br />

um eine Klasse oder eine JAR-Datei zu installieren.<br />

Die Details der einzelnen Schritte können zwar unterschiedlich sein, wenn<br />

ein Java-Entwicklungstool wie <strong>Sybase</strong> PowerJ verwendet wird, grundsätzlich<br />

sind aber <strong>für</strong> die Erstellung eigener Klassen die nachfolgend beschriebenen<br />

Schritte erforderlich.<br />

v So erstellen Sie eine Klasse:<br />

1 Definieren Sie Ihre Klasse Schreiben Sie den Java-Code, der Ihre<br />

Klasse definiert. Wenn Sie den Sun Java SDK benutzen, können Sie<br />

einen Texteditor verwenden. Wenn Sie ein Entwicklungstool wie <strong>Sybase</strong><br />

PowerJ benutzen, finden Sie entsprechende Anweisungen im<br />

Entwicklungstool.<br />

Verwenden Sie nur unterstützte Klassen<br />

Wenn Ihre Klasse Java-Laufzeitklassen benutzt, müssen Sie darauf<br />

achten, dass sie sich in der Liste der unterstützten Klassen befinden.<br />

Die Liste finden Sie unter "Unterstützte Java-Pakete" auf Seite 87 der<br />

Dokumentation ASA SQL-Referenzhandbuch.<br />

Benutzerklassen müssen 100% Java sein. Native Methoden sind nicht<br />

zulässig.<br />

103


Java-Klassen in einer Datenbank installieren<br />

Klasse installieren<br />

104<br />

2 Benennen und speichern Sie Ihre Klasse Speichern Sie Ihre<br />

Klassendeklaration (Java-Code) in einer Datei mit der Erweiterung .java.<br />

Achten Sie darauf, dass der Name der Datei mit dem Namen der Klasse<br />

übereinstimmt, und dass die Groß-/Kleinschreibung beider Namen<br />

identisch ist.<br />

Beispiel: Eine Klasse namens "Dienstprogramm" muss in einer Datei<br />

namens Dienstprogramm.java gespeichert werden.<br />

3 Kompilieren Sie Ihre Klasse Mit diesem Schritt wird die<br />

Klassendeklaration mit dem Java-Code in eine neue, eigene Datei<br />

verwandelt, die Byte-Code enthält. Der Name der neuen Datei ist gleich<br />

lautend mit dem Namen der Java-Codedatei, hat aber die Erweiterung<br />

.class. Eine kompilierte Java-Klasse kann in einer Java-<br />

Laufzeitumgebung unabhängig von der Plattform ausgeführt werden, auf<br />

der sie kompiliert wurde. Auch das Betriebssystem der Java-<br />

Laufzeitumgebung spielt keine Rolle.<br />

Der Sun JDK enthält den Java-Compiler Javac.exe.<br />

Nur <strong>für</strong> Java aktivierte Datenbanken<br />

Jede kompilierte Java-Klassendatei kann in einer Datenbank<br />

installiert werden. Java-Vorgänge, die eine installierte Klasse<br />

verwenden, können nur ausgeführt werden, wenn die Datenbank <strong>für</strong><br />

Java aktiviert wurde. Siehe unter "Datenbank <strong>für</strong> Java aktivieren" auf<br />

Seite 97.<br />

Um Ihre Java-Klasse innerhalb der Datenbank verfügbar zu machen, können<br />

Sie eine Klasse aus <strong>Sybase</strong> Central einrichten oder mit der Anweisung<br />

INSTALL aus Interactive SQL oder einer anderen Anwendung installieren.<br />

Sie müssen den Suchpfad und den Dateinamen der Klasse kennen, die Sie<br />

installieren wollen.<br />

Sie brauchen die DBA-Berechtigung, um eine Klasse zu installieren.<br />

v So installieren Sie eine Klasse (<strong>Sybase</strong> Central):<br />

1 Stellen Sie mit DBA-Berechtigung eine Verbindung mit einer<br />

Datenbank her.<br />

2 Öffnen Sie den Ordner "Java-Objekte" <strong>für</strong> die Datenbank.<br />

3 Doppelklicken Sie auf "Java-Klasse hinzufügen".<br />

4 Befolgen Sie die Anweisungen im Assistenten.


JAR-Datei installieren<br />

Kapitel 4 Java in der Datenbank benutzen<br />

v So installieren Sie eine Klasse (Interactive SQL):<br />

1 Stellen Sie mit DBA-Berechtigung eine Verbindung mit einer<br />

Datenbank her.<br />

2 Führen Sie folgende Anweisung aus:<br />

INSTALL JAVA NEW<br />

FROM FILE ’Suchpfad\\Klassenname.class’<br />

Dabei gilt: Suchpfad ist das Verzeichnis, in dem die Klassendatei<br />

gehalten wird, und Klassenname.class ist der Name der Klassendatei.<br />

Der doppelte Rückstrich sorgt da<strong>für</strong>, dass der Rückstrich nicht als<br />

Escapezeichen behandelt wird.<br />

Beispiel: Um eine Klasse zu installieren, die in einer Datei namens<br />

Dienstprogramm.class im Verzeichnis c:\Quelle gehalten wird, geben Sie<br />

folgende Anweisung ein:<br />

INSTALL JAVA NEW<br />

FROM FILE ’c:\\Quelle\\Dienstprogramm.class’<br />

Wenn Sie einen relativen Suchpfad verwenden, muss er zum aktuellen<br />

Arbeitsverzeichnis des Datenbankservers relativ sein.<br />

$ Weitere Hinweise finden Sie unter "INSTALL-Anweisung" auf<br />

Seite 504 der Dokumentation ASA SQL-Referenzhandbuch und unter<br />

"Java-Objekte, Klassen und JAR-Dateien löschen" auf Seite 116.<br />

Es ist sinnvoll und allgemein üblich, Gruppen von miteinander verwandten<br />

Klassen in Paketen zu sammeln und diese Pakete in einer JAR-Datei<br />

zusammenzufassen. Informationen über JAR-Dateien und Pakete finden Sie<br />

im Online-Buch Thinking in Java oder anderer Literatur zum Thema Java-<br />

Programmierung.<br />

Eine JAR-Datei wird auf dieselbe Weise installiert wie eine Klassendatei.<br />

Eine JAR-Datei kann die Erweiterung JAR oder ZIP haben. Jede JAR-Datei<br />

muss einen Namen in der Datenbank haben. Normalerweise benutzen Sie<br />

denselben Namen wie die JAR-Datei, ohne die Erweiterung. Beispiel: Wenn<br />

Sie eine JAR-Datei namens meinejar.zip installieren, sollten Sie ihr im<br />

Allgemeinen den JAR-Namen meinejar geben.<br />

$ Weitere Hinweise finden Sie unter "INSTALL-Anweisung" auf<br />

Seite 504 der Dokumentation ASA SQL-Referenzhandbuch und "Java-<br />

Objekte, Klassen und JAR-Dateien löschen" auf Seite 116.<br />

105


Java-Klassen in einer Datenbank installieren<br />

106<br />

v So installieren Sie eine JAR-Datei (<strong>Sybase</strong> Central):<br />

1 Stellen Sie mit DBA-Berechtigung eine Verbindung mit einer<br />

Datenbank her.<br />

2 Öffnen Sie den Ordner "Java-Objekte" <strong>für</strong> die Datenbank.<br />

3 Doppelklicken Sie auf "JAR-Datei hinzufügen".<br />

4 Befolgen Sie die Anweisungen im Assistenten.<br />

v So installieren Sie eine JAR-Datei (Interactive SQL):<br />

1 Stellen Sie mit DBA-Berechtigung eine Verbindung mit einer<br />

Datenbank her.<br />

2 Geben Sie folgende Anweisung ein:<br />

INSTALL JAVA NEW<br />

JAR ’jarname’<br />

FROM FILE ’Suchpfad\\JarName.jar’<br />

Klassen und JAR-Dateien aktualisieren<br />

Bestehende Java-<br />

Objekte und<br />

aktualisierte<br />

Klassen<br />

Gültigkeit<br />

aktualisierter<br />

Klassen<br />

Sie können Klassen und JAR-Dateien mit <strong>Sybase</strong> Central oder durch die<br />

Eingabe einer INSTALL-Anweisung in Interactive SQL bzw. einer anderen<br />

Clientanwendung installieren.<br />

Um eine Klasse oder eine JAR-Datei zu installieren, müssen Sie DBA-<br />

Berechtigung haben und über eine neuere Version der kompilierten Klasse<br />

oder JAR-Datei in einer Datei auf der Festplatte verfügen.<br />

Es kann sein, dass Instanzen einer Java-Klasse in Form von Java-Objekten in<br />

Ihrer Datenbank oder als Werte in einer Spalte gespeichert sind, die die<br />

Klasse als Datentyp verwendet.<br />

Trotz der Aktualisierung der Klasse bleiben diese alten Werte weiterhin<br />

verfügbar, auch wenn die Felder und Methoden, die in den Tabellen<br />

gespeichert werden, mit der neuen Klassendefinition inkompatibel sind.<br />

Alle neu eingefügten Zeilen müssen allerdings mit der neuen Definition<br />

kompatibel sein.<br />

Die neue Definition wird nur von Verbindungen benutzt, die nach der<br />

Installation der Klasse eingerichtet wurden, oder die die Klasse zum ersten<br />

Mal nach der Installation der Klasse verwenden. Wenn die Virtual Machine<br />

die Klassendefinition lädt, bleibt diese im Speicher, bis die Verbindung<br />

geschlossen wird.


In serialisierter<br />

Form gespeicherte<br />

Objekte<br />

Kapitel 4 Java in der Datenbank benutzen<br />

Wenn Sie eine Java-Klasse oder auf einer Klasse basierende Objekte in der<br />

aktuellen Verbindung benutzt haben, müssen Sie die Verbindung trennen<br />

und wieder aufnehmen, damit die neue Klassendefinition wirksam wird.<br />

$ Um zu verstehen, wie aktualisierte Klassen wirksam werden, müssen<br />

Sie mehr über die Arbeitsweise der Virtual Machine wissen. Hinweise dazu<br />

finden Sie unter "Speicher <strong>für</strong> Java konfigurieren" auf Seite 140.<br />

Java-Objekte können die aktualisierte Klassendefinition verwenden, weil sie<br />

in serialisierter Form gespeichert werden. Das benutzte<br />

Serialisierungsformat ist speziell <strong>für</strong> die Datenbank entworfen und entspricht<br />

nicht dem Serialisierungsformat von Sun Microsystems. Die interne <strong>Sybase</strong><br />

VM führt alle Serialisierungen und Deserialisierungen durch, sodass dadurch<br />

keine Kompatibilitätsprobleme entstehen.<br />

v So aktualisieren Sie eine Klasse oder JAR-Datei (<strong>Sybase</strong> Central):<br />

1 Stellen Sie mit DBA-Berechtigung eine Verbindung mit einer<br />

Datenbank her.<br />

2 Öffnen Sie den Ordner "Java-Objekte".<br />

3 Suchen Sie die Klasse oder JAR-Datei, die Sie aktualisieren wollen.<br />

4 Rechtsklicken Sie auf die Klasse oder JAR-Datei und wählen Sie<br />

"Aktualisieren" aus dem Einblendmenü.<br />

5 In dem nun eingeblendeten Dialogfeld geben Sie den Namen und den<br />

Standort der Klasse oder JAR-Datei ein, die Sie aktualisieren wollen. Sie<br />

können mit "Durchsuchen" danach suchen.<br />

Tipp<br />

Sie können eine Java-Klasse oder JAR-Datei auch aktualisieren, indem<br />

Sie im Register "Allgemein" ihres Eigenschaftsfensters auf "Jetzt<br />

aktualisieren" klicken.<br />

v So aktualisieren Sie eine Klasse oder JAR-Datei (Interactive SQL):<br />

1 Stellen Sie mit DBA-Berechtigung eine Verbindung mit einer<br />

Datenbank her.<br />

2 Führen Sie folgende Anweisung aus:<br />

INSTALL JAVA UPDATE<br />

[ JAR ’jarname’ ]<br />

FROM FILE ’Dateiname’<br />

Wenn Sie eine JAR-Datei aktualisieren, müssen Sie den Namen<br />

eingeben, unter dem die JAR in der Datenbank bekannt ist.<br />

107


Java-Klassen in einer Datenbank installieren<br />

108<br />

$ Weitere Hinweise finden Sie unter "INSTALL-Anweisung" auf<br />

Seite 504 der Dokumentation ASA SQL-Referenzhandbuch.


Kapitel 4 Java in der Datenbank benutzen<br />

Spalten <strong>für</strong> die Aufnahme von Java-Objekten<br />

erstellen<br />

Dieser Abschnitt erläutert, wie Spalten mit Datentypen der Java-Klassen in<br />

die standardmäßige SQL-Struktur passen.<br />

Spalten mit Java-Datentypen erstellen<br />

Berücksichtigung<br />

von Groß-/Kleinschreibung<br />

Sie können jede installierte Java-Klasse als Datentyp benutzen. Sie müssen<br />

einen voll qualifizierten Namen <strong>für</strong> den Datentyp verwenden.<br />

Beispiel: Die folgende Anweisung CREATE TABLE enthält Spalten der<br />

Java-Datentypen asademo.Name und asademo.ContactInfo. Hier sind<br />

Name und ContactInfo Klassen im Paket asademo.<br />

CREATE TABLE jdba.customer<br />

(<br />

id integer NOT NULL,<br />

company_name CHAR(35) NOT NULL,<br />

JName asademo.Name NOT NULL,<br />

JContactInfo asademo.ContactInfo NOT NULL,<br />

PRIMARY KEY (id)<br />

)<br />

Anders als bei SQL-Datentypen berücksichtigen Java-Datentypen die Groß-<br />

/Kleinschreibung. Sie müssen die Datentypen immer in der richtigen<br />

Schreibweise eingeben.<br />

Standardwerte und NULLWERTE in Java-Spalten verwenden<br />

Sie können Standardwerte <strong>für</strong> Java-Spalten verwenden, und Java-Spalten<br />

können NULLWERTE enthalten.<br />

Java-Spalten und Standardwerte Spalten können als Standardwert jede<br />

Funktion mit dem richtigen Datentyp oder einen beliebigen voreingestellten<br />

Standardwert enthalten. Sie können jede Funktion mit dem richtigen<br />

Datentyp (d.h. derselben Klasse wie die Spalte) als Standardwert <strong>für</strong> Java-<br />

Spalten verwenden.<br />

Java-Spalten und NULLWERTE Java-Spalten können NULLWERTE<br />

zulassen. Wenn <strong>für</strong> eine nullwertfähige Spalte mit einem Java-Datentyp kein<br />

Standardwert gesetzt ist, enthält die Spalte NULL.<br />

109


Spalten <strong>für</strong> die Aufnahme von Java-Objekten erstellen<br />

110<br />

Wenn ein Java-Wert nicht gesetzt ist, hat er den Java-NULLWERT. Dieser<br />

Java-NULLWERT ist dem SQL-NULLWERT zugeordnet, und Sie können<br />

daher die Suchbedingungen IS NULL und IS NOT NULL <strong>für</strong> diese Werte<br />

verwenden. Beispiel: Wenn die Beschreibung des Java-Objekts "product" in<br />

einer Spalte namens JProd nicht gesetzt wurde, können Sie alle Produkte mit<br />

Nicht-Nullwerten <strong>für</strong> die Beschreibung wie folgt abrufen:<br />

SELECT *<br />

FROM product<br />

WHERE JProd>>description IS NULL


Kapitel 4 Java in der Datenbank benutzen<br />

Java-Objekte einfügen, aktualisieren und<br />

löschen<br />

Java-Beispiel-<br />

Tabellen erstellen<br />

Eine Beispielklasse<br />

In diesem Abschnitt wird beschrieben, wie Standard-SQL-Anweisungen <strong>für</strong><br />

die Datenverarbeitung auf Java-Spalten angewendet werden.<br />

In diesem Abschnitt werden die einzelnen Punkte mit konkreten Beispielen<br />

illustriert, die auf der Tabelle Product der Beispieldatenbank und einer<br />

Klasse namens Product basieren. Als Erstes sollten Sie sich die Datei<br />

Samples\ASA\Java\asademo\Product.java in Ihrem SQL <strong>Anywhere</strong>-<br />

Verzeichnis ansehen.<br />

Die Beispiele in diesem Abschnitt setzen voraus, dass Sie die Java-Tabellen<br />

der Beispieldatenbank hinzugefügt haben und als Benutzer jDBA mit dem<br />

Kennwort SQL verbunden sind.<br />

$ Weitere Hinweise finden Sie unter "Java-Beispiele einrichten" auf<br />

Seite 94.<br />

In diesem Abschnitt wird eine Klasse beschrieben, die in Beispielen aller<br />

folgenden Abschnitte verwendet wird.<br />

Die Klassendefinition Product im Verzeichnis<br />

Samples\ASA\Java\asademo\Product.java in Ihrem SQL <strong>Anywhere</strong>-<br />

Verzeichnis wird teilweise im Folgenden dargestellt (zum besseren<br />

Verständnis werden die Kommentarzeilen, die in der Originaldatei in<br />

Englisch sind, hier in deutscher Übersetzung wiedergegeben):<br />

package asademo;<br />

public class Product implements java.io.Serializable {<br />

// "public"-Felder<br />

public String name ;<br />

public String description ;<br />

public String size ;<br />

public String color;<br />

public int quantity ;<br />

public java.math.BigDecimal unit_price ;<br />

// Standard-Konstruktor<br />

Product () {<br />

unit_price = new java.math.BigDecimal( 10.00 );<br />

name = "Unknown";<br />

size = "One size fits all";<br />

111


Java-Objekte einfügen, aktualisieren und löschen<br />

Hinweise<br />

Java-Objekte einfügen<br />

112<br />

}<br />

// Konstruktor mit allen verfügbaren Argumenten<br />

Product ( String inColor,<br />

String inDescription,<br />

String inName,<br />

int inQuantity,<br />

String inSize,<br />

java.math.BigDecimal inUnit_price<br />

) {<br />

color = inColor;<br />

description = inDescription;<br />

name = inName;<br />

quantity = inQuantity;<br />

size = inSize;<br />

unit_price=inUnit_price;<br />

}<br />

public String toString() {<br />

return size + " " + name + ": " +<br />

unit_price.toString();<br />

}<br />

♦ Die Klasse Product hat einige öffentliche Felder, die einigen Spalten<br />

der Tabelle DBA.Product entsprechen, die in dieser Klasse gesammelt<br />

werden sollen.<br />

♦ Die Methode toString wird der Einfachheit halber bereitgestellt. Wenn<br />

Sie einen Objektnamen in eine Auswahlliste einbeziehen, wird die<br />

Methode toString ausgeführt, und ihre Rückgabezeichenfolgen werden<br />

angezeigt.<br />

♦ Einige Methoden sind vorgesehen, um die Felder zu setzen und<br />

abzurufen. Es ist beim objektorientierten Programmieren auch allgemein<br />

üblich, solche Methoden zu verwenden, und nicht die Felder direkt zu<br />

adressieren. Für die praktische Einführung wurden die Felder zur<br />

einfacheren Durchführung als "öffentliche" Felder zugänglich gemacht.<br />

Wenn Sie eine Zeile in eine Tabelle EINFÜGEN, die eine Java-Spalte hat,<br />

müssen Sie ein Java-Objekt in die Java-Spalte einfügen.<br />

Sie können ein Java-Objekt auf zwei Arten einfügen: aus SQL oder mit<br />

JDBC aus anderen Java-Klassen, die in der Datenbank ausgeführt werden.


Java-Objekte aus SQL einfügen<br />

Objekt mit einem<br />

Konstruktor<br />

einfügen<br />

Objekt aus einer<br />

SQL-Variablen<br />

einfügen<br />

Kapitel 4 Java in der Datenbank benutzen<br />

Sie können ein Java-Objekt mit einem Konstruktor einfügen oder SQL-<br />

Variable verwenden, um ein Java-Objekt aufzubauen, bevor Sie es einfügen.<br />

Wenn Sie einen Wert in eine Spalte einfügen, die einen Java-Klassen-<br />

Datentyp hat, fügen Sie ein Java-Objekt ein. Um ein Objekt mit den richtigen<br />

Eigenschaften einzufügen, muss das neue Objekt die richtigen Werte <strong>für</strong><br />

öffentliche Felder haben, und Methoden, die private Felder setzen, müssen<br />

aufgerufen werden.<br />

v So fügen Sie ein Java-Objekt ein:<br />

♦ INSERT: Verwenden Sie die INSERT-Anweisung, um eine neue<br />

Instanz der Klasse "Product" in die Tabelle product einzufügen:<br />

INSERT<br />

INTO product ( ID, JProd )<br />

VALUES ( 702, NEW asademo.Product() )<br />

Sie können dieses Beispiel in der Beispieldatenbank als Benutzer jdba<br />

ausführen, nachdem Sie das Skript jdemo.sql ausgeführt haben.<br />

Das Schlüsselwort NEW ruft den Standard-Konstruktor <strong>für</strong> die Klasse<br />

Product im Paket asademo auf.<br />

Sie können die Werte der Felder des Objekts in einer SQL-Variablen der<br />

richtigen Klasse auch individuell setzen, und nicht durch den Konstruktor.<br />

v So fügen Sie ein Java-Objekt mit SQL-Variablen ein:<br />

1 Erstellen Sie eine SQL-Variable der Java-Klassentypen:<br />

CREATE VARIABLE ProductVar asademo.Product<br />

2 Weisen Sie der Variablen ein neues Objekt zu, indem Sie den<br />

Klassenkonstruktor verwenden:<br />

SET ProductVar = NEW asademo.Product()<br />

3 Weisen Sie den Feldern des Objekts Werte zu, wo solche erforderlich<br />

sind:<br />

SET ProductVar>>color = ’Black’;<br />

SET ProductVar>>description = ’Steel tipped boots’;<br />

SET ProductVar>>name = ’Work boots’;<br />

SET ProductVar>>quantity = 40;<br />

SET ProductVar>>size = ’Extra Large’;<br />

SET ProductVar>>unit_price = 79.99;<br />

4 Fügen Sie die Variable in die Tabelle ein:<br />

INSERT<br />

INTO Product ( id, JProd )<br />

113


Java-Objekte einfügen, aktualisieren und löschen<br />

Objekt aus Java einfügen<br />

Java-Objekt aktualisieren<br />

Gesamtes Objekt<br />

aktualisieren<br />

114<br />

VALUES ( 800, ProductVar )<br />

5 Prüfen Sie, ob der Wert eingefügt wurde:<br />

SELECT *<br />

FROM product<br />

WHERE id=800<br />

6 Machen Sie die Änderungen rückgängig, die Sie in dieser Übung<br />

vorgenommen haben:<br />

ROLLBACK<br />

Die Verwendung von SQL-Variablen ist typisch <strong>für</strong> gespeicherte Prozeduren<br />

und andere Verwendungsmöglichkeiten von SQL zum Einbau von<br />

programmierter Logik in die Datenbank. Java ist die leistungsfähigere<br />

Sprache <strong>für</strong> solche Aufgaben. Sie können die serverseitigen Java-Klassen<br />

gemeinsam mit JDBC verwenden, um Objekte in Tabellen einzufügen.<br />

Sie können ein Objekt mit einer vorbereiteten Anweisung von JDBC<br />

einfügen.<br />

Eine vorbereitete Anweisung benutzt Platzhalter <strong>für</strong> Variable. Sie können<br />

dann die Methode setObject des Objekts PreparedStatement benutzen.<br />

Sie können vorbereitete Anweisungen verwenden, um Objekte von<br />

clientseitiger oder serverseitiger JDBC einzufügen.<br />

$ Weitere Hinweise über die Verwendung von vorbereiteten<br />

Anweisungen <strong>für</strong> Objekte finden Sie unter "Objekte einfügen und abrufen"<br />

auf Seite 172.<br />

Java-Spaltenwerte können mit einer der folgenden Methoden aktualisiert<br />

werden:<br />

♦ Gesamtes Objekt aktualisieren<br />

♦ Einige der Felder im Objekt aktualisieren<br />

Für die Aktualisierung des Objekts gehen Sie fast genauso vor wie <strong>für</strong> das<br />

Einfügen:<br />

♦ Aus SQL können Sie einen Konstruktor verwenden, um das Objekt auf<br />

ein neues Objekt zu aktualisieren, wenn der Konstruktor es erstellt. Sie<br />

können dann einzelne Felder aktualisieren, wenn Sie dies benötigen.


Felder des Objekts<br />

aktualisieren<br />

set-Methoden<br />

verwenden<br />

Kapitel 4 Java in der Datenbank benutzen<br />

♦ Aus SQL können Sie eine SQL-Variable verwenden, um das benötigte<br />

Objekt aufzunehmen, und dann die Zeile aktualisieren, damit die<br />

Variable darin eingefügt wird.<br />

♦ Aus JDBC können Sie eine vorbereitete Anweisung und die Methode<br />

PreparedStatement.setObject verwenden.<br />

Einzelne Felder eines Objekts haben Datentypen, die SQL-Datentypen<br />

entsprechen. Dabei verwenden Sie die Zuordnung von SQL- zu Java-<br />

Datentypen laut der Beschreibung unter "Umwandlung von JAVA- in SQL-<br />

Datentypen" auf Seite 95 der Dokumentation ASA SQL-Referenzhandbuch.<br />

Sie können einzelne Felder mit einer Standard-UPDATE-Anweisung<br />

aktualisieren:<br />

UPDATE Product<br />

SET JProd.unit_price = 16.00<br />

WHERE ID = 302<br />

In der ersten Version von Java in der Datenbank musste eine spezielle<br />

Funktion (EVALUATE) verwendet werden, um Aktualisierungen<br />

vorzunehmen. Dies ist nicht mehr erforderlich.<br />

Damit ein Java-Feld aktualisiert werden kann, muss der Java-Typ des Feldes<br />

einem SQL-Typ zugeordnet sein: Der Ausdruck auf der rechten Seite der<br />

SET-Klausel muss mit diesem Typ übereinstimmen. Sie müssen eventuell<br />

die CAST-Funktion verwenden, um die Datentypen entsprechend<br />

einzuordnen.<br />

$ Hinweise zur Datentypzuordnung zwischen Java und SQL finden Sie<br />

unter "Umwandlung von JAVA- in SQL-Datentypen" auf Seite 95 der<br />

Dokumentation ASA SQL-Referenzhandbuch.<br />

Bei der Java-Programmmierung ist es allgemein üblich, Felder nicht direkt<br />

anzusprechen, sondern Methoden zu benutzen, um die Werte zu holen und zu<br />

setzen. Außerdem ist es allgemein üblich, dass diese Methoden void<br />

zurückgeben. Sie können in SQL set-Methoden verwenden, um eine Spalte<br />

zu aktualisieren:<br />

UPDATE jdba.Product<br />

SET JProd.setName( ’Tank Top’)<br />

WHERE id=302<br />

Der Einsatz von Methoden anstelle der direkten Ansprache des Feldes ist<br />

langsamer, da die Java VM laufen muss.<br />

$ Weitere Hinweise finden Sie unter "Rückgabewert von Methoden, die<br />

"void" zurückgeben" auf Seite 125.<br />

115


Java-Objekte einfügen, aktualisieren und löschen<br />

Java-Objekte, Klassen und JAR-Dateien löschen<br />

116<br />

Das Löschen von Zeilen mit Java-Objekten unterscheidet sich nicht vom<br />

Löschen anderer Zeilen. Die WHERE-Klausel in der DELETE-Anweisung<br />

kann Java-Objekte oder Java-Felder und Methoden enthalten.<br />

$ Weitere Hinweise finden Sie unter "DELETE-Anweisung" auf<br />

Seite 422 der Dokumentation ASA SQL-Referenzhandbuch.<br />

Mit <strong>Sybase</strong> Central können Sie auch eine ganze Java-Klasse oder JAR-Datei<br />

löschen.<br />

v So löchen Sie eine Java-Klasse oder JAR-Datei (<strong>Sybase</strong> Central):<br />

1 Öffnen Sie den Ordner "Java-Objekte".<br />

2 Suchen Sie die Klasse oder JAR-Datei, die Sie löschen wollen.<br />

3 Rechtsklicken Sie auf die Klasse oder JAR-Datei und wählen Sie<br />

"Löschen" aus dem Einblendmenü.<br />

$ Siehe auch:<br />

♦ "Klasse installieren" auf Seite 104<br />

♦ "JAR-Datei installieren" auf Seite 105


Java-Objekte abfragen<br />

Gesamtes Objekt<br />

abfragen<br />

Felder des Objekts<br />

abrufen<br />

Kapitel 4 Java in der Datenbank benutzen<br />

Java-Spaltenwerte können mit einer der folgenden Methoden abgefragt<br />

werden:<br />

♦ Gesamtes Objekt abfragen<br />

♦ Einige der Felder im Objekt abfragen<br />

Aus SQL können Sie eine Variable des geeigneten Typs erstellen und den<br />

Wert aus dem Objekt in diese Variable auswählen. Vor allem aber werden<br />

Sie das ganze Objekt in einer Java-Anwendung brauchen.<br />

Sie können ein Objekt in eine serverseitige Java-Klasse abrufen, indem Sie<br />

die Methode getObject des ResultSet einer Abfrage verwenden. Sie können<br />

auch ein Objekt in eine clientseitige Java-Anwendung abrufen.<br />

$ Wie Objekte mit JDBC abgerufen werden, finden Sie unter "Abfragen<br />

mit JDBC" auf Seite 169.<br />

Einzelne Felder eines Objekts haben Datentypen, die SQL-Datentypen<br />

entsprechen. Dabei verwenden Sie die Zuordnung von SQL- zu Java-<br />

Datentypen laut der Beschreibung unter "Umwandlung von JAVA- in SQL-<br />

Datentypen" auf Seite 95 der Dokumentation ASA SQL-Referenzhandbuch.<br />

♦ Sie können einzelne Felder abrufen, indem Sie sie in die Auswahlliste<br />

einer Abfrage einschließen, wie dies im folgenden einfachen Beispiel<br />

beschrieben wird.<br />

SELECT JProd>>unit_price<br />

FROM product<br />

WHERE ID = 400<br />

♦ Wenn Sie Methoden verwenden, um die Werte Ihrer Felder zu setzen<br />

und abzurufen, wie es beim objektorientierten Programmieren allgemein<br />

üblich ist, können Sie eine Methode getField in Ihre Abfrage<br />

einbeziehen.<br />

SELECT JProd>>getName()<br />

FROM Product<br />

WHERE ID = 401<br />

$ Informationen über die Verwendung von Objekten in der WHERE-<br />

Klausel und andere Hinweise zum Vergleich von Objekten finden Sie unter<br />

"Java-Felder und Objekte vergleichen" auf Seite 119.<br />

117


Java-Objekte abfragen<br />

Die Ergebnisse der<br />

Anweisung<br />

SELECT<br />

Spaltenname<br />

118<br />

Performance-Tipp<br />

Das direkte Abrufen eines Feldes ist schneller als der Aufruf einer<br />

Methode, die das Feld abruft, da <strong>für</strong> den Aufruf der Methode die Java VM<br />

gestartet werden muss.<br />

Sie können den Spaltennamen in einer Abfrage-Auswahlliste auflisten, wie<br />

in der folgenden Abfrage:<br />

SELECT JProd<br />

FROM jdba.product<br />

Die Abfrage gibt die Sun-Serialisierung des Objekts an die Clientanwendung<br />

zurück.<br />

Wenn Sie in Interactive SQL eine Abfrage ausführen, die ein Objekt abruft,<br />

wird der Rückgabewert der toString-Methode des Objekts angezeigt. Für die<br />

Klasse "Product" listet die Methode toString in einer Zeichenfolge die<br />

Größe, den Namen und den Stückpreis des Objekts auf. Die Ergebnisse der<br />

Abfrage lauten wie folgt:<br />

JProd<br />

Small Tee Shirt: 9.00<br />

Medium Tee Shirt: 14.00<br />

One size fits all Tee Shirt: 14.00<br />

One size fits all Baseball Cap: 9.00<br />

One size fits all Baseball Cap: 10.00<br />

One size fits all Visor: 7.00<br />

One size fits all Visor: 7.00<br />

Large Sweatshirt: 24.00<br />

Large Sweatshirt: 24.00<br />

Medium Shorts: 15.00


Java-Felder und Objekte vergleichen<br />

Art des Vergleichs<br />

von Java-Objekten<br />

Kapitel 4 Java in der Datenbank benutzen<br />

Öffentliche Java-Klassen sind Domänen, die viel umfangreichere Funktionen<br />

bieten als herkömmliche SQL-Domänen. In diesem Zusammenhang ergibt<br />

sich die Frage, wie sich Java-Spalten in einer relationalen Datenbank im<br />

Vergleich zu traditionellen SQL-Datentypen verhalten.<br />

Die Frage des Vergleichs von Objekten hat Auswirkungen insbesondere in<br />

folgenden Bereichen:<br />

♦ Abfragen mit einer ORDER BY Klausel, einer GROUP BY Klausel,<br />

einem DISTINCT Schlüsselwort oder mit einer Aggregatfunktion<br />

♦ Anweisungen, die Gleichheits- oder Ungleichheits-<br />

Vergleichsbedingungen verwenden<br />

♦ Indizes und eindeutige Spalten<br />

♦ Primär- und Fremdschlüsselspalten<br />

Sortieren von Zeilen in einer Abfrage oder in einem Index setzt voraus, dass<br />

die Werte in jeder Zeile miteinander verglichen werden. Wenn Sie eine Java-<br />

Spalte haben, können Sie Vergleiche in der folgenden Weise ausführen:<br />

♦ Vergleich über ein öffentliches Feld Sie können über ein öffentliches<br />

Feld genauso einen Vergleich vornehmen wie über eine normale Zeile.<br />

Beispielsweise könnten Sie folgende Abfrage ausführen:<br />

SELECT name, JProd.unit_price<br />

FROM Product<br />

ORDER BY JProd.unit_price<br />

Diese Art des Vergleichs kann in Abfragen verwendet werden, ist aber<br />

<strong>für</strong> Indizes und Schlüsselspalten nicht anwendbar.<br />

♦ Vergleich mit einer "compareTo"-Methode Java-Objekte, die eine<br />

compareTo-Methode implementiert haben, können verglichen werden.<br />

Die Klasse "Product", auf der die Spalte JProd basiert, hat eine<br />

compareTo-Methode, die Objekte auf Grundlage des Feldes unit_price<br />

miteinander vergleicht. Damit wird folgende Abfrage ermöglicht:<br />

SELECT name, JProd.unit_price<br />

FROM Product<br />

ORDER BY JProd<br />

Der benötigte Vergleich <strong>für</strong> die ORDER BY Klausel erfolgt automatisch<br />

basierend auf der Methode compareTo.<br />

119


Java-Felder und Objekte vergleichen<br />

Java-Objekte vergleichen<br />

Anforderungen der<br />

"compareTo"-<br />

Methode<br />

Beispiel<br />

120<br />

Um zwei Objekte desselben Typs zu vergleichen, müssen Sie eine<br />

compareTo-Methode implementieren:<br />

♦ Damit Spalten mit Java-Datentypen als Primärschlüssel, Indizes oder<br />

eindeutige Spalten verwendet werden können, muss die Spaltenklasse<br />

eine compareTo-Methode implementieren.<br />

♦ Um die Klauseln ORDER BY, GROUP BY oder DISTINCT in einer<br />

Abfrage verwenden zu können, müssen die Werte der Spalte verglichen<br />

werden. Die Spaltenklasse muss eine compareTo-Methode haben,<br />

damit alle diese Klauseln gültig sind.<br />

♦ Funktionen, die Vergleiche verwenden, wie MAX und MIN, können nur<br />

mit einer Java-Klasse benutzt werden, die eine compareTo-Methode<br />

hat.<br />

Die compareTo-Methode muss folgende Eigenschaften haben:<br />

♦ Bereich Die Methode muss extern sichtbar und daher eine öffentliche<br />

Methode sein.<br />

♦ Argumente Die Methode übernimmt ein einzelnes Argument, das ein<br />

Objekt des aktuellen Typs ist. Das aktuelle Objekt wird mit dem<br />

gelieferten Objekt verglichen. Beispiel: Product.compareTo hat<br />

folgendes Argument:<br />

compareTo( Produkt AnderesProdukt )<br />

Die Methode vergleicht das Objekt AnderesProdukt vom Typ<br />

"Produkt" mit dem aktuellen Objekt.<br />

♦ Rückgabewerte Die Methode "compareTo" muss einen int-Datentyp<br />

mit folgenden Bedeutungen zurückgeben:<br />

♦ Negative Ganzzahl Das aktuelle Objekt ist geringer als das<br />

gelieferte Objekt. Es wird empfohlen, dass Sie <strong>für</strong> diesen Fall -1<br />

zurückgeben, um die Kompatibilität mit "compareTo"-Methoden in<br />

Basis-Java-Klassen zu gewährleisten.<br />

♦ Ziffer Null Das aktuelle Objekt hat denselben Wert wie das<br />

gelieferte Objekt.<br />

♦ Positive Ganzzahl Das aktuelle Objekt ist größer als das gelieferte<br />

Objekt. Es wird empfohlen, dass Sie <strong>für</strong> diesen Fall 1 zurückgeben,<br />

um die Kompatibilität mit "compareTo"-Methoden in Basis-Java-<br />

Klassen zu gewährleisten.<br />

Die Klasse Product, die mit den Beispielklassen in der Beispieldatenbank<br />

installiert wird, hat eine compareTo-Methode der folgenden Art:


Methoden<br />

"toString" und<br />

"compareTo"<br />

kompatibel<br />

machen<br />

Kapitel 4 Java in der Datenbank benutzen<br />

public int compareTo( Product anotherProduct ) {<br />

// Erst auf Basis des Preises vergleichen<br />

// und dann auf Basis von toString()<br />

int lVal = unit_price.intValue();<br />

int rVal = anotherProduct.unit_price.intValue();<br />

if ( lVal > rVal ) {<br />

return 1;<br />

}<br />

else if (lVal < rVal ) {<br />

return -1;<br />

}<br />

else {<br />

return toString().compareTo(<br />

anotherProduct.toString() );{<br />

}<br />

}<br />

}<br />

Diese Methode vergleicht den Einheitspreis jedes Objekts. Wenn die<br />

Einheitspreise identisch sind, werden die Namen verglichen (mit Java-<br />

Zeichenfolgenvergleichen, nicht mit Datenbank-Zeichenfolgenvergleichen).<br />

Nur wenn der Einheitspreis und der Name gleich sind, werden die beiden<br />

Objekte beim Vergleich als identisch angesehen.<br />

Wenn Sie eine Java-Spalte in die Auswahlliste einbeziehen und in Interactive<br />

SQL ausführen, wird der Wert der Methode toString zurückgegeben. Wenn<br />

Sie Spalten vergleichen, wird die Methode compareTo verwendet. Wenn die<br />

Methoden toString und compareTo nicht konsistent implementiert sind,<br />

kann es zu unvorhergesehenen Ergebnissen kommen, wie DISTINCT-<br />

Abfragen, die augenscheinlich Duplikat-Zeilen zurückgeben.<br />

Als Beispiel nehmen wir an, dass die Klasse "Product" in der<br />

Beispieldatenbank eine Methode toString hat, die den Produktnamen<br />

zurückgibt, und eine Methode compareTo, die auf dem Preis basiert. Die<br />

folgende, in Interactive SQL eingegebene Abfrage würde in diesem Fall<br />

Doppelwerte ausgeben:<br />

SELECT DISTINCT JProd<br />

FROM product<br />

JProd<br />

Tee Shirt<br />

Tee Shirt<br />

Baseball Cap<br />

Visor<br />

Sweatshirt<br />

Shorts<br />

121


Java-Felder und Objekte vergleichen<br />

122<br />

Hier wird der angezeigte Rückgabewert durch toString festgelegt. Das<br />

DISTINCT-Schlüsselwort eliminiert Duplikate, wie von compareTo<br />

festgelegt. Da hier eine Implementierung der Methoden vorliegt, die die<br />

Beziehungen untereinander nicht berücksichtigt, sieht es so aus, als würden<br />

Duplikatzeilen zurückgegeben.


Kapitel 4 Java in der Datenbank benutzen<br />

Besondere Funktionen von Java-Klassen in der<br />

Datenbank<br />

Unterstützte Klassen<br />

Hauptmethode (main) verwenden<br />

In diesem Abschnitt werden besondere Funktionen von Java-Klassen<br />

beschrieben, die in einer Datenbank eingesetzt werden.<br />

Sie können nicht alle Klassen aus dem JDK verwenden. Die Java-<br />

Laufzeitklassen, die <strong>für</strong> den Einsatz in einem Datenbankserver verfügbar<br />

sind, gehören zu einer Teilmenge der Java-API.<br />

$ Weitere Hinweise über unterstützte Pakete finden Sie unter<br />

"Unterstützte Java-Pakete" auf Seite 87 der Dokumentation ASA SQL-<br />

Referenzhandbuch.<br />

Sie starten Java-Anwendungen (außerhalb der Datenbank), indem Sie die<br />

Java VM mit einer Klasse ausführen, die eine main-Methode hat.<br />

Zum Beispiel hat die Klasse JDBCExamples in der Datei<br />

Samples\ASA\Java\JDBCExamples.java in Ihrem SQL <strong>Anywhere</strong>-<br />

Verzeichnis eine Hauptmethode (main). Wenn Sie die Klasse von der<br />

Befehlszeile aus mit einem Befehl wie dem folgenden ausführen, wird die<br />

Hauptmethode (main) ausgeführt:<br />

java JDBCExamples<br />

$ Hinweise über das Ausführen der Klasse JDBCExamples finden Sie<br />

unter "JDBC-Verbindungen herstellen" auf Seite 157.<br />

v So wird die Hauptmethode (main) einer Klasse von SQL aus<br />

aufgerufen:<br />

1 Deklarieren Sie die Methode mit einem Array von Zeichenfolgen als<br />

Argument.<br />

public static void main( java.lang.String[] args ){<br />

...<br />

}<br />

2 Rufen Sie die Methode main mit der CALL-Anweisung auf.<br />

123


Besondere Funktionen von Java-Klassen in der Datenbank<br />

Beispiel<br />

124<br />

Jedes Mitglied des Arrays von Zeichenfolgen muss den Datentyp CHAR<br />

oder VARCHAR haben oder muss ein Literal sein.<br />

Die folgende Klasse enthält eine main-Methode, die die Argumente in<br />

umgekehrter Reihenfolge ausgibt:<br />

public class ReverseWrite {<br />

public static void main( String[] args ){<br />

int i:<br />

for( i = args.length; i > 0 ; i-- ){<br />

System.out.print( args[ i-1 ] );<br />

}<br />

}<br />

}<br />

Sie können diese Methode aus SQL wie folgt ausführen:<br />

call ReverseWrite.main( ’ one’, ’ two’, ’three’ )<br />

Das Datenbankserver-Fenster zeigt die Ausgabe:<br />

three two one<br />

Threads in Java-Anwendungen verwenden<br />

Serialisierung von<br />

JDBC-Aufrufen<br />

Sie können mehrere Threads in einer Java-Anwendung benutzen, indem Sie<br />

Funktionen des Pakets java.lang.Thread einsetzen. Jeder Java-Thread ist ein<br />

Engine-Thread und wird aus der Menge der zulässigen Threads gemäß der<br />

Option -gn des Datenbankservers bezogen.<br />

Sie können Threads in Java-Anwendungen synchronisieren, vorläufig<br />

aussetzen, wieder aufnehmen, unterbrechen oder stoppen.<br />

$ Hinweise zu Datenbankserver-Threads finden Sie unter "–gn-<br />

Serveroption" auf Seite 158 der Dokumentation ASA<br />

Datenbankadministration.<br />

Fehler "Prozedur nicht gefunden"<br />

Alle Aufrufe zum serverseitigen JDBC-Treiber sind serialisiert, sodass nur<br />

ein Thread jeweils JDBC ausführt.<br />

Wenn Sie eine falsche Anzahl von Argumenten <strong>für</strong> den Aufruf einer Java-<br />

Methode eingeben oder einen falschen Datentyp verwenden, antwortet der<br />

Server mit der Fehlermeldung Prozedur nicht gefunden. Prüfen Sie in diesem<br />

Fall Anzahl und Typ der Argumente.


Kapitel 4 Java in der Datenbank benutzen<br />

$ Eine Liste der Datentypkonvertierungen zwischen SQL und Java finden<br />

Sie unter "Umwandlung von JAVA- in SQL-Datentypen" auf Seite 95 der<br />

Dokumentation ASA SQL-Referenzhandbuch.<br />

Rückgabewert von Methoden, die "void" zurückgeben<br />

Sie können Java-Methoden in SQL-Anweisungen überall dort verwenden,<br />

wo Sie einen Ausdruck benutzen können. Sie müssen da<strong>für</strong> Sorge tragen,<br />

dass der Rückgabe-Datentyp der Java-Methode zum entsprechenden SQL-<br />

Datentyp passt.<br />

$ Weitere Hinweise über Zuordnungen von Java- und SQL-Datentypen<br />

finden Sie unter "Umwandlung von JAVA- in SQL-Datentypen" auf Seite 95<br />

der Dokumentation ASA SQL-Referenzhandbuch.<br />

Wenn eine Methode jedoch eine leere Menge zurückgibt, wird der Wert this<br />

an SQL zurückgegeben, d.h. das Objekt selbst. Die Funktion betrifft nur<br />

Aufrufe, die von SQL aus ausgeführt werden, nicht von Java aus.<br />

Diese Funktion ist besonders gut in UPDATE-Anweisungen einsetzbar, in<br />

denen set-Methoden in der Regel "void" zurückgeben. Sie können die<br />

folgende UPDATE-Anweisung in der Beispieldatenbank benutzen:<br />

update jdba.product<br />

set JProd = JProd.setName(’Tank Top’)<br />

where id=302<br />

Die Methode setName gibt "void" und daher implizit das Objekt "Product"<br />

an SQL zurück.<br />

Ergebnismengen aus Java-Methoden zurückgeben<br />

Dieser Abschnitt beschreibt, wie Ergebnismengen aus Java-Methoden<br />

verfügbar gemacht werden. Sie müssen eine Java-Methode schreiben, die<br />

eine Ergebnismenge an die aufrufende Umgebung zurückgibt, und diese<br />

Methode in eine in SQL geschriebene gespeicherte Prozedur einbauen, die<br />

als EXTERNAL NAME of LANGUAGE JAVA deklariert sein muss.<br />

v So werden Ergebnismengen aus einer Java-Methode<br />

zurückgegeben:<br />

1 Achten Sie darauf, dass die Java-Methode als öffentlich und statisch in<br />

einer öffentlichen Klasse deklariert wird.<br />

2 Für jede Ergebnismenge, die die Methode zurückgeben soll, muss die<br />

Methode einen Parameter vom Typ java.sql.ResultSet[] haben. Diese<br />

Ergebnismengen-Parameter müssen am Ende der Parameterliste stehen.<br />

125


Besondere Funktionen von Java-Klassen in der Datenbank<br />

Beispiel<br />

126<br />

3 In der Methode erstellen Sie erst eine Instanz von java.sql.ResultSet<br />

und ordnen sie dann einem der ResultSet[]-Parameter zu.<br />

4 Erstellen Sie eine in SQL geschriebene gespeicherte Prozedur des Typs<br />

EXTERNAL NAME LANGUAGE JAVA. Dieser Prozedurtyp ist ein<br />

Mantel <strong>für</strong> eine Java-Methode. Sie können einen Cursor <strong>für</strong> die<br />

Ergebnismenge der SQL-Prozedur auf dieselbe Weise verwenden wie<br />

jede andere Prozedur, die Ergebnismengen zurückgibt.<br />

$ Hinweise zur Syntax <strong>für</strong> gespeicherte Prozeduren, die als Mantel<br />

<strong>für</strong> Java-Methoden verwendet werden, finden Sie unter "CREATE<br />

PROCEDURE-Anweisung" auf Seite 331 der Dokumentation ASA SQL-<br />

Referenzhandbuch.<br />

Die folgende Beispielklasse hat eine einzige Methode, die eine Abfrage<br />

ausführt und die Ergebnismenge an die aufrufende Umgebung zurückgibt.<br />

import java.sql.*;<br />

public class MyResultSet {<br />

public static void return_rset( ResultSet[] rset1 )<br />

throws SQLException {<br />

Connection conn = DriverManager.getConnection(<br />

"jdbc:default:connection" );<br />

Statement stmt = conn.createStatement();<br />

ResultSet rset =<br />

stmt.executeQuery (<br />

"SELECT CAST( JName.lastName " +<br />

"AS CHAR( 50 ) )" +<br />

"FROM jdba.contact " );<br />

rset1[0] = rset;<br />

}<br />

}<br />

Die Ergebnismenge wird in SQL mit der Anweisung CREATE<br />

PROCEDURE exponiert, womit die Anzahl der von der Prozedur<br />

zurückgegebenen Ergebnismengen und die Signatur der Java-Methode<br />

angezeigt werden.<br />

Eine Anweisung vom Typ CREATE PROCEDURE, die eine Ergebnismenge<br />

anzeigt, könnte wie folgt definiert werden:<br />

CREATE PROCEDURE result_set()<br />

DYNAMIC RESULT SETS 1<br />

EXTERNAL NAME<br />

’MyResultSet.return_rset ([Ljava/sql/ResultSet;)V’<br />

LANGUAGE JAVA<br />

Ein Cursor kann <strong>für</strong> diese Prozedur genauso wie <strong>für</strong> andere ASA-Prozeduren<br />

geöffnet werden, die Ergebnismengen zurückgeben.


Kapitel 4 Java in der Datenbank benutzen<br />

Die Zeichenfolge (Ljava/sql/ResultSet;)V ist eine Java-Methodensignatur,<br />

also eine kompakte Zeichendarstellung der Anzahl und der Typen der<br />

Parameter und Rückgabewerte.<br />

$ Weitere Hinweise zu Java-Methodensignaturen finden Sie unter<br />

"CREATE PROCEDURE-Anweisung" auf Seite 331 der Dokumentation<br />

ASA SQL-Referenzhandbuch.<br />

Rückgabe von Werten aus Java über gespeicherte Prozeduren<br />

Sie können gespeicherte Prozeduren, die mit EXTERNAL NAME<br />

LANGUAGE JAVA erstellt wurden, als Mantel <strong>für</strong> Java-Methoden<br />

verwenden. In diesem Abschnitt wird beschrieben, wie Sie Ihre Java-<br />

Methode so schreiben, dass OUT- oder INOUT-Parameter in der<br />

gespeicherten Prozedur benutzt werden können.<br />

Java hat keine explizite Unterstützung <strong>für</strong> INOUT- oder OUT-Parameter.<br />

Anstelle dessen können Sie ein Array des Parameters verwenden. Beispiel:<br />

Um einen Ganzzahl-OUT-Parameter zu benutzen, erstellen Sie ein Array von<br />

genau einer Ganzzahl:<br />

public class TestClass {<br />

public static boolean testOut( int[] param ){<br />

param[0] = 123;<br />

return true;<br />

}<br />

}<br />

Die folgende Prozedur benutzt die testOut-Methode:<br />

CREATE PROCEDURE sp_testOut ( OUT p INTEGER )<br />

EXTERNAL NAME ’TestClass/testOut ([I)Z’<br />

LANGUAGE JAVA<br />

Die Zeichenfolge ([I)Z ist eine Java-Methodensignatur, die anzeigt, dass die<br />

Methode einen einzelnen Parameter hat, der ein Array von Ganzzahlen<br />

darstellt und einen Boolschen Wert zurückgibt. Sie müssen die Methoden so<br />

definieren, damit der Methodenparameter, den Sie als OUT- oder INOUT-<br />

Parameter verwenden wollen, ein Array eines Java-Datentyps ist, der dem<br />

SQL-Datentyp des OUT- oder INOUT-Parameters entspricht.<br />

$ Hinweise zur Syntax, einschließlich der Methodensignatur, finden Sie<br />

unter "CREATE PROCEDURE-Anweisung" auf Seite 331 der<br />

Dokumentation ASA SQL-Referenzhandbuch.<br />

$ Weitere Hinweise finden Sie unter "Umwandlung von JAVA- in SQL-<br />

Datentypen" auf Seite 95 der Dokumentation ASA SQL-Referenzhandbuch.<br />

127


Besondere Funktionen von Java-Klassen in der Datenbank<br />

Sicherheits-Management <strong>für</strong> Java<br />

Der Standard-<br />

Sicherheits-<br />

Manager<br />

Java-Datei-I/O-<br />

Vorgänge mit dem<br />

standardmäßigen<br />

Sicherheits-<br />

Manager steuern<br />

128<br />

Java bietet Sicherheits-Manager, die Sie zur Steuerung des Benutzerzugriffs<br />

auf vertrauliche Funktionen Ihrer Anwendungen, wie etwa Dateizugriff und<br />

Netzwerkzugriff, einsetzen können. <strong>Adaptive</strong> Server <strong>Anywhere</strong> bietet die<br />

folgende Unterstützung <strong>für</strong> Java-Sicherheitsmanager in der Datenbank:<br />

♦ <strong>Adaptive</strong> Server <strong>Anywhere</strong> liefert einen standardmäßigen Sicherheits-<br />

Manager.<br />

♦ Sie können Ihren eigenen Sicherheitsmanager stellen.<br />

$ Hinweise dazu finden Sie unter "Eigenen Sicherheits-Manager<br />

implementieren" auf Seite 129.<br />

Der standardmäßige Sicherheits-Manager ist die Klasse<br />

com.sybase.asa.jrt.SAGenericSecurityManager. Er führt die folgenden<br />

Aufgaben durch:<br />

1 Er prüft den Wert der Datenbankoption JAVA_INPUT_OUTPUT.<br />

2 Er prüft, ob der Datenbankserver mit der Datenbankserveroption -sc im<br />

C2-Sicherheitsmodus gestartet wurde.<br />

3 Falls die Verbindungseigenschaft auf OFF steht, wird damit der Zugriff<br />

auf Java-Datei-I/O-Funktionen deaktiviert.<br />

4 Wenn der Datenbankserver im C2-Sicherheitsmodus läuft, wird der<br />

Zugriff auf java.net-Pakete verwehrt.<br />

5 Wenn der Sicherheits-Manager einen Benutzer am Zugriff auf eine<br />

Funktion hindert, wird eine java.lang.SecurityException<br />

zurückgegeben.<br />

$ Weitere Hinweise finden Sie unter "JAVA_INPUT_OUTPUT-Option"<br />

auf Seite 642 der Dokumentation ASA Datenbankadministration, und "–sc-<br />

Serveroption" auf Seite 167 der Dokumentation ASA<br />

Datenbankadministration.<br />

Die Java-Datei-I/O-Vorgänge werden über die Datenbankoption<br />

JAVA_INPUT_OUTPUT gesteuert. Standardmäßig wird diese Option auf<br />

OFF gesetzt, sodass Datei-I/O-Vorgänge nicht zulässig sind.<br />

v So wird der Dateizugriff mit dem standardmäßigen Sicherheits-<br />

Manager zugelassen:<br />

♦ Setzen Sie die Option JAVA_INPUT_OUTPUT auf ON:<br />

SET OPTION JAVA_INPUT_OUTPUT=’ON’


Eigenen Sicherheits-Manager implementieren<br />

Beispiel<br />

Kapitel 4 Java in der Datenbank benutzen<br />

Ein eigener Sicherheits-Manager wird mit mehreren Schritten implementiert.<br />

v So wird Ihr eigener Sicherheits-Manager verfügbar gemacht:<br />

1 Implementieren Sie eine Klasse, die java.lang.SecurityManager<br />

erweitert.<br />

Die Klasse SecurityManager umfasst eine Reihe von Methoden, die<br />

prüfen, ob ein bestimmter Vorgang zulässig ist. Falls die Aktion zulässig<br />

ist, kehrt die Methode stillschweigend zurück. Falls die Methode einen<br />

Wert zurückgibt, wird eine SecurityException ausgegeben.<br />

Sie müssen Methoden aufheben, die Aktionen mit stillschweigend<br />

zurückkehrenden Methoden steuern. Sie können dies durch<br />

Implementieren einer Methode public void erreichen.<br />

2 Ordnen Sie Ihrem Sicherheits-Manager die betreffenden Benutzer zu.<br />

Verwenden Sie die gespeicherten Systemprozeduren<br />

add_user_security_manager, update_user_security_manager und<br />

delete_user_security_manager, um einem Benutzer Sicherheits-<br />

Manager zuzuordnen. Wenn Sie z.B. die Klasse<br />

MeinSicherheitsManager einem Benutzer als Sicherheits-Manager<br />

zuordnen wollen, würden Sie den folgenden Befehl ausführen.<br />

call dbo.add_user_security_manager(<br />

Benutzername, ’MeinSicherheitsManager’, NULL )<br />

Mit der folgenden Klasse können Sie das Lesen aus Dateien zulassen, jedoch<br />

das Schreiben untersagen:<br />

public class MeinSicherheitsManager extends<br />

SecurityManager<br />

{ public void checkRead(FileDescriptor) {}<br />

public void checkRead(String) {}<br />

public void checkRead(String, Object) {}<br />

}<br />

Die Methoden SecurityManager.checkWrite werden nicht aufgehoben und<br />

verhindern Schreibvorgänge in den Dateien. Die Methoden checkRead<br />

kehren stillschweigend zurück und lassen die Aktion zu.<br />

129


So werden Java-Objekte gespeichert<br />

So werden Java-Objekte gespeichert<br />

Hinweise<br />

130<br />

Java-Werte werden in serialisierter Form gespeichert. Das bedeutet, dass<br />

jede Zeile folgende Informationen enthält:<br />

♦ Einen Versionsbezeichner<br />

♦ Einen Bezeichner <strong>für</strong> die Klasse (oder Unterklasse), die gespeichert wird<br />

♦ Die Werte von nicht-statischen, nicht-zeitweiligen Feldern in der Klasse<br />

♦ Andere Overhead-Informationen<br />

Die Klassendefinition wird nicht <strong>für</strong> jede Zeile gespeichert. Anstelle dessen<br />

enthält der Bezeichner eine Referenz auf die Klassendefinition, die nur<br />

einmal gehalten wird.<br />

Sie können Java-Objekte verwenden, ohne im Detail zu wissen, wie diese<br />

Elemente zusammenwirken, aber die Art der Speicherung dieser Objekte hat<br />

einige Auswirkungen auf die Verarbeitungsleistung. Daher werden diese<br />

Informationen hier etwas genauer ausgeführt.<br />

♦ Plattenspeicher Der Overhead pro Zeile ist 10 bis 15 Byte. Falls die<br />

Klasse nur über eine Variable verfügt, kann der erforderliche Overhead<br />

dem <strong>für</strong> die Variable ähneln. Falls die Klasse viele Variablen umfasst,<br />

kann der Overhead vernachlässigt werden.<br />

♦ Performance Wenn Sie einen Java-Wert einfügen oder aktualisieren,<br />

muss die Java VM ihn serialisieren. Jedes Mal, wenn ein Java-Wert in<br />

einer Abfrage abgerufen wird, muss er von der VM deserialisiert<br />

werden. Dies kann bedeutende Performanceeinbußen verursachen.<br />

Sie können die Performanceeinbußen <strong>für</strong> Abfragen vermeiden, indem<br />

Sie berechnete Spalten verwenden.<br />

♦ Indizieren Indizes auf Java-Spalten sind nicht sehr selektiv und bieten<br />

nicht die Performancevorteile wie Indizes auf einfachen SQL-<br />

Datentypen.<br />

♦ Serialisierung Wenn eine Klasse eine readObject- oder writeObject-<br />

Methode hat, wird diese beim Serialisieren oder Deserialisieren der<br />

Instanz aufgerufen. Der Einsatz einer readObject- oder writeObject-<br />

Methode kann sich auf die Performance auswirken, weil die Java VM<br />

aufgerufen wird.


Java-Objekte und Klassenversionen<br />

Zugriff auf Zeilen,<br />

wenn eine Klasse<br />

aktualisiert wird<br />

Unzugängliche<br />

Objekte<br />

Kapitel 4 Java in der Datenbank benutzen<br />

Java-Objekte, die in der Datenbank gespeichert werden, sind beständig - d.h.<br />

sie bestehen, auch wenn kein Programmcode läuft. Das bedeutet, dass Sie<br />

folgende Aktionen ausführen können:<br />

1 Installieren Sie eine Klasse.<br />

2 Tabelle mit dieser Klasse als Datentyp <strong>für</strong> eine Spalte erstellen<br />

3 Zeilen in die Tabelle einfügen<br />

4 Neue Version der Klasse installieren<br />

Funktionsweise der bestehenden Zeilen mit der neuen Version der Klasse<br />

<strong>Adaptive</strong> Server <strong>Anywhere</strong> sieht eine Form der Evidenzhaltung von<br />

Klassenversionen vor, die es ermöglicht, dass die neue Klasse mit den alten<br />

Zeilen arbeiten kann. Die Regeln <strong>für</strong> den Zugriff auf diese älteren Werte<br />

lauten wie folgt:<br />

♦ Wenn ein serialisierbares Feld in der alten Version der Klasse vorhanden<br />

ist, aber in der neuen Version fehlt oder nicht serialisierbar ist, wird das<br />

Feld ignoriert.<br />

♦ Wenn ein serialisierbares Feld in der neuen Version der Klasse<br />

vorhanden ist, aber in der alten Version fehlt oder nicht serialisierbar<br />

war, wird das Feld auf einen Standardwert initialisiert. Der Standardwert<br />

ist 0 <strong>für</strong> native Typen, "false" <strong>für</strong> Boolesche Werte, und "NULL" <strong>für</strong><br />

Objektreferenzen.<br />

♦ Wenn eine Überklasse der alten Version vorhanden war, die nicht eine<br />

Überklasse der neuen Version ist, werden die Daten <strong>für</strong> diese Überklasse<br />

ignoriert.<br />

♦ Wenn eine Überklasse der neuen Version vorhanden ist, die nicht eine<br />

Überklasse der alten Version war, werden die Daten <strong>für</strong> diese<br />

Überklasse auf Standardwerte initialisiert.<br />

♦ Wenn ein serialisierbares Feld zwischen der älteren Version und der<br />

neueren Version den Typ ändert, wird das Feld auf Standardwerte<br />

initialisiert. Typenkonvertierungen werden nicht unterstützt - dies ist<br />

kompatibel mit der Sun Microsystems-Serialisierung.<br />

Ein serialisiertes Objekt ist nicht zugänglich, wenn die Klasse des Objekts<br />

oder eine ihrer Überklassen zu irgendeinem Zeitpunkt aus der Datenbank<br />

entfernt wurde. Dieses Verhalten ist kompatibel mit der Sun Microsystems-<br />

Serialisierung.<br />

131


So werden Java-Objekte gespeichert<br />

Objekte zwischen<br />

Datenbanken<br />

verschieben<br />

Wann die neue<br />

Klasse benutzt<br />

wird<br />

132<br />

Diese Änderungen machen die Verschiebung von Objekten zwischen<br />

Datenbanken möglich, auch wenn die Versionen der Klassen voneinander<br />

abweichen. Die Verschiebung über Datenbanken kann wie nachstehend<br />

beschrieben erfolgen:<br />

♦ Objekte werden in eine entfernte Datenbank verlegt.<br />

♦ Eine Tabelle mit Objekten wird entladen und dann in eine andere<br />

Datenbank eingelesen.<br />

♦ Eine Logdatei mit Objekten wird übersetzt und in einer anderen<br />

Datenbank angewendet.<br />

Die Klassendefinition <strong>für</strong> jede Klasse wird durch die VM jeder Verbindung<br />

geladen, wenn die Klasse zum ersten Mal benutzt wird.<br />

Wenn Sie eine Klasse installieren, wird die VM auf Ihrer Verbindung<br />

implizit gestartet. Daher haben Sie sofort Zugang zu der neuen Klasse.<br />

Für andere Verbindungen als diejenige, die die INSTALL-Anweisung<br />

ausführt, wird die neue Klasse das nächste Mal geladen, wenn die VM auf<br />

die Klasse zugreift. Wenn die Klasse von einer VM bereits geladen ist, sieht<br />

diese Verbindung die neue Klasse erst, wenn die VM <strong>für</strong> diese Verbindung<br />

neu gestartet wird (zum Beispiel mit STOP JAVA und START JAVA).


Java-Datenbankdesign<br />

Kapitel 4 Java in der Datenbank benutzen<br />

Für das Design Ihrer relationalen Datenbanken gibt es einen umfangreichen<br />

theoretischen und praktischen Erfahrungsschatz. Sie können Beschreibungen<br />

zum Design von Entitätsbeziehungen und andere Ansätze nicht nur in<br />

einleitender Form (siehe "Planung Ihrer Datenbank" auf Seite 3 der<br />

Dokumentation ASA SQL-Benutzerhandbuch), sondern auch in der Literatur<br />

<strong>für</strong> fortgeschrittene Anwender finden.<br />

Eine derartige Vielfalt ist <strong>für</strong> die Theorie und Praxis von objekt-relationalen<br />

Datenbanken nicht vorhanden, und dies gilt umso mehr <strong>für</strong> Java-relationale<br />

Datenbanken. Im Folgenden finden Sie einige Vorschläge <strong>für</strong> den Einsatz<br />

von Java zur Erweiterung des praktischen Einsatzes relationaler<br />

Datenbanken.<br />

Entitäten und Attribute in relationalen und objektorientierten Daten<br />

Beim Design relationaler Datenbanken beschreibt jede Tabelle eine Entität.<br />

Beispiel: In der Beispieldatenbank gibt es Tabellen mit dem Namen<br />

Employee, Customer, Sales_order und Department. Die Attribute dieser<br />

Entitäten werden zu den Spalten der Tabelle: Adressen der Mitarbeiter,<br />

Kundennummern, Bestellnummern, und so weiter. Jede Zeile in der Tabelle<br />

kann als getrennte Instanz der Entität bezeichnet werden - ein bestimmter<br />

Mitarbeiter, eine Bestellung eine Abteilung.<br />

Beim objektorientierten Programmieren beschreibt jede Klasse eine Entität,<br />

und die Methoden und Felder dieser Klasse beschreiben die Attribute der<br />

Entität. Jede Instanz der Klasse (jedes Objekt) enthält eine eigene Instanz<br />

der Entität.<br />

Es scheint daher unnatürlich, dass relationale Spalten auf Java-Klassen<br />

basieren. Eine natürlichere Entsprechung liegt zwischen Tabellen und<br />

Klassen vor.<br />

Entitäten und Attribute in der realen Welt<br />

Die Unterscheidung zwischen Entität und Attribut scheint klar, aber bei<br />

näherem Hinsehen zeigt sich, dass sie in der Praxis nicht ganz so eindeutig<br />

ausfällt.<br />

♦ Eine Adresse kann als Attribut eines Kunden gesehen werden, ist aber<br />

auch eine Entität, die als eigene Attribute die Straße, Stadt etc. hat.<br />

♦ Ein Preis kann als Attribut eines Produkts gesehen werden, ist aber auch<br />

eine Entität mit den Attributen "Summe" und "Währung".<br />

133


Java-Datenbankdesign<br />

134<br />

Der Sinn der objektrelationalen Datenbank ist genau in diesem Faktum zu<br />

suchen, nämlich dass es zwei Möglichkeiten gibt, Entitäten auszudrücken.<br />

Sie können einige Entitäten als Tabellen, und andere Entitäten als Klassen in<br />

einer Tabelle ausdrücken. Im nächsten Abschnitt wird ein Beispiel erläutert.<br />

Einschränkungen der relationalen Datenbanken<br />

Stellen Sie sich ein Versicherungsunternehmen vor, das Überblick über seine<br />

Kunden behalten will. Ein Kunde kann als Entität angesehen werden, sodass<br />

es sinnvoll ist, eine einzelne Tabelle zu entwerfen, in der alle Kunden der<br />

Gesellschaft enthalten sind.<br />

Nun werden aber von Versicherungsgesellschaften verschiedene Arten von<br />

Kunden betreut. Es gibt die Policeninhaber, die Begünstigten und Personen,<br />

die die Prämien zu bezahlen haben. Für alle diese Kundentypen benötigt die<br />

Versicherungsgesellschaft verschiedene Informationen. Für den<br />

Begünstigten braucht sie eigentlich nicht viel mehr als die Adresse. Für den<br />

Policeninhaber sind Informationen über den Gesundheitszustand<br />

erforderlich. Für den Prämienzahler braucht man zusätzliche<br />

Finanzinformationen <strong>für</strong> die steuerlichen Aspekte.<br />

Ist es besser, diese unterschiedlichen Kundentypen als unterschiedliche<br />

Entitäten zu behandeln, oder als Attribut des Kunden? Bei beiden Ansätzen<br />

gibt es Einschränkungen:<br />

♦ Wenn <strong>für</strong> jeden Kundentyp eine eigene Tabelle eingerichtet wird, kann<br />

das Datenbankdesign sehr unübersichtlich werden, und beim Abfragen<br />

von Informationen zu allen Kunden müssen mehrere Tabellen<br />

durchsucht werden.<br />

♦ Und wenn eine einzelne Kundentabelle verwendet wird, ist es nicht<br />

einfach, sicherzustellen, dass <strong>für</strong> jeden Kunden die richtigen<br />

Informationen eingegeben werden. Das Einrichten von Spalten, die <strong>für</strong><br />

einige Kunden nullwertfähig sind, <strong>für</strong> andere aber nicht, ermöglicht die<br />

richtige Dateneingabe, erzwingt sie aber nicht. Es gibt in relationalen<br />

Datenbanken keine einfache Methode, das Standardverhalten an ein<br />

Attribut der neuen Dateneingabe zu binden.<br />

Mit Klassen bestimmte Einschränkungen relationaler Datenbanken<br />

überwinden<br />

Sie können eine einzelne Kundentabelle verwenden, wobei <strong>für</strong> einige<br />

Informationen Java-Klassenspalten benutzt werden, um die Begrenzungen<br />

relationaler Datenbanken zu überwinden.


Kapitel 4 Java in der Datenbank benutzen<br />

Beispiel: Nehmen wir an, Sie brauchen <strong>für</strong> die Policeninhaber andere<br />

Kontaktinformationen als <strong>für</strong> die Begünstigten. Sie können dieses Problem<br />

lösen, indem Sie eine Spalte definieren, die auf der Klasse<br />

Kontaktinformation basiert. Dann definieren Sie Klassen mit den Namen<br />

PolicenhalterKontaktdaten und BegünstigterKontaktdaten, die<br />

Unterklassen der Klasse Kontaktdaten sind. Indem Sie neue Kunden nach<br />

ihrem Typ eingeben, können Sie sicherstellen, dass die richtigen<br />

Informationen eingegeben werden.<br />

Abstraktionsebenen <strong>für</strong> relationale Daten<br />

Daten in einer relationalen Datenbank können nach Zweck kategorisiert<br />

werden. Welche Daten gehören in eine Java-Klasse, und welche sollten<br />

besser in einer einfachen Datentyp-Spalte eingegeben werden?<br />

♦ Spalten <strong>für</strong> die referenzielle Integrität Primärschlüsselspalten und<br />

Fremdschlüsselspalten haben gemeinsame Identifizierungsnummern.<br />

Diese Identifizierungsnummern können als referenzielle Daten<br />

bezeichnet werden. Ihr Hauptzweck ist die Definition der Struktur der<br />

Datenbank und die Definition der Beziehungen zwischen Tabellen.<br />

Referenzielle Daten gehören im Allgemeinen nicht in Java-Klassen.<br />

Obwohl Sie aus einer Java-Klassenspalte eine Primärschlüsselspalte<br />

machen können, sind Ganzzahlen und andere einfache Datentypen <strong>für</strong><br />

diesen Zweck besser geeignet.<br />

♦ Indizierte Daten Spalten, die im Allgemeinen indiziert werden, werden<br />

ebenfalls nicht in Java-Klassen angelegt. Allerdings ist die Trennlinie<br />

zwischen Daten, die indiziert werden sollen, und solchen, bei denen dies<br />

nicht erforderlich ist, eher unscharf.<br />

Bei berechneten Spalten können Sie selektiv ein Java-Feld oder eine<br />

Java-Methode (bzw. auch einen anderen Ausdruck) indizieren. Wenn<br />

Sie eine Java-Klassenspalte definieren und dann feststellen, dass es<br />

sinnvoll wäre, sie auf ein Feld oder eine Methode dieser Spalte zu<br />

indizieren, können Sie berechnete Spalten verwenden, um aus diesem<br />

Feld oder dieser Methode eine eigene Spalte zu erstellen.<br />

$ Weitere Hinweise finden Sie unter "Berechnete Spalten mit Java-<br />

Klassen verwenden" auf Seite 137.<br />

♦ Beschreibende Daten In jeder Zeile gibt es im Allgemeinen auch<br />

beschreibende Daten. Solche Daten werden <strong>für</strong> die referenzielle<br />

Integrität nicht verwendet, meist nicht indiziert, aber häufig in Abfragen<br />

verwendet. Bei einer Mitarbeitertabelle können dies Daten wie<br />

Einstellungsdatum, Adresse, Vergünstigungen, Gehalt usw. sein. Für<br />

diese Daten kann es häufig von Vorteil sein, wenn sie in weniger<br />

Spalten vom Typ Javaklasse kombiniert werden.<br />

135


Java-Datenbankdesign<br />

136<br />

Java-Klassen sind <strong>für</strong> die Abstraktion auf einer Ebene zwischen der der<br />

einzelnen relationalen Spalte und der relationalen Tabelle nützlich.


Berechnete Spalten mit Java-Klassen<br />

verwenden<br />

Einsatzbereich<br />

berechneter<br />

Spalten<br />

Berechnete Spalten festlegen<br />

Tabellen mit<br />

berechneten<br />

Spalten erstellen<br />

Kapitel 4 Java in der Datenbank benutzen<br />

Berechnete Spalten sind ein Merkmal, das entwickelt wurde, um das Design<br />

von Java-Datenbanken einfacher zu gestalten, damit Java-Funktionen in<br />

bestehenden Datenbanken besser genutzt werden können, und um die<br />

Performance von Java-Datentypen zu verbessern.<br />

Eine berechnete Spalte ist eine Spalte, deren Werte aus anderen Spalten<br />

ausgewertet werden. Sie können in berechneten Spalten kein INSERT und<br />

kein UPDATE durchführen. Eine UPDATE-Anweisung, die versucht, den<br />

Wert einer berechneten Spalte zu ändern, löst aber Trigger aus, die mit der<br />

Spalte verbunden sind.<br />

Es gibt zwei Haupteinsatzgebiete <strong>für</strong> berechnete Spalten mit Java-Klassen:<br />

♦ Java-Spalte aufgliedern Wenn Sie eine Spalte mit einem Java-Klassen-<br />

Datentyp erstellen, können Sie mit berechneten Spalten eines der Felder<br />

einer Klasse indizieren. Sie können eine berechnete Spalte hinzufügen,<br />

die den Wert des Feldes enthält, und daher einen Index auf dieses Feld<br />

erstellen.<br />

♦ Java-Spalte einer relationalen Tabelle hinzufügen Wenn Sie einige<br />

der Funktionen von Java-Klassen nutzen, aber in die bestehende<br />

Datenbank so wenig wie möglich eingreifen wollen, können Sie Java-<br />

Spalten als berechnete Spalten hinzufügen, die ihre Werte aus anderen<br />

Spalten in der Tabelle beziehen.<br />

Berechnete Spalten werden in den Anweisungen CREATE TABLE oder<br />

ALTER TABLE deklariert.<br />

Die folgende CREATE TABLE-Anweisung wird benutzt, um die Tabelle<br />

product in den Java-Beispieltabellen zu erstellen:<br />

CREATE TABLE product<br />

(<br />

id INTEGER NOT NULL,<br />

JProd asademo.Product NOT NULL,<br />

name CHAR(15) COMPUTE ( JProd>>name ),<br />

PRIMARY KEY ("id")<br />

)<br />

137


Berechnete Spalten mit Java-Klassen verwenden<br />

Berechnete<br />

Spalten zu<br />

Tabellen<br />

hinzufügen<br />

Ausdruck <strong>für</strong><br />

berechnete<br />

Spalten ändern<br />

138<br />

Die folgende Anweisung ändert die Tabelle product, indem eine weitere<br />

berechnete Spalte hinzugefügt wird:<br />

ALTER TABLE product<br />

ADD inventory_Value INTEGER<br />

COMPUTE ( JProd.quantity * JProd.unit_price )<br />

Sie können mit der Anweisung ALTER TABLE den Ausdruck ändern, der in<br />

einer berechneten Spalte verwendet wird. Die folgende Anweisung ändert<br />

den Ausdruck, auf der eine berechnete Spalte basiert:<br />

ALTER TABLE Tabellenname<br />

ALTER Spaltenname SET COMPUTE ( Ausdruck )<br />

Die Spalte wird neu berechnet, wenn diese Anweisung ausgeführt wird.<br />

Wenn der neue Ausdruck ungültig ist, schlägt die ALTER TABLE-<br />

Anweisung fehl.<br />

Die folgende Anweisung macht aus einer berechneten Spalte wieder eine<br />

normale Spalte.<br />

ALTER TABLE Tabellenname<br />

ALTER Spaltenname DROP COMPUTE<br />

Wenn Sie diese Anweisung ausführen, werden die Werte in der Spalte nicht<br />

verändert.<br />

Berechnete Spalten einfügen und aktualisieren<br />

Berechnete Spalten haben Auswirkungen auf die Gültigkeit von INSERT<br />

und UPDATE. Die Tabelle jdba.product in den Java-Beispieltabellen hat<br />

eine berechnete Spalte (name), die wir zur Erläuterung dieses Problemfeldes<br />

heranziehen. Die Tabellendefinition lautet wie folgt:<br />

CREATE TABLE "jdba"."product"<br />

(<br />

"id" INTEGER NOT NULL,<br />

"JProd" asademo.Product NOT NULL,<br />

"name" CHAR(15) COMPUTE( JProd.name ),<br />

PRIMARY KEY ("id")<br />

)<br />

♦ Keine direkten Einfügungen oder Aktualisierungen Sie können in<br />

eine berechnete Spalte keinen Wert direkt einfügen. Die folgende<br />

Anweisung schlägt mit der Fehlermeldung Duplikat beim Einfügen in<br />

eine Spalte fehl.<br />

-- Falsche Anweisung<br />

INSERT INTO PRODUCT (id, name)<br />

VALUES( 3006, ’bad insert statement’ )


Kapitel 4 Java in der Datenbank benutzen<br />

Eine UPDATE-Anweisung kann eine berechnete Spalte nicht direkt<br />

aktualisieren.<br />

♦ Auflisten von Spaltennamen Sie müssen in INSERT-Anweisungen <strong>für</strong><br />

Tabellen mit berechneten Spalten immer die Spaltennamen angeben. Die<br />

folgende Anweisung schlägt mit der Fehlermeldung Falsche Anzahl von<br />

Werten <strong>für</strong> INSERT fehl:<br />

-- Falsche Anweisung<br />

INSERT INTO PRODUCT<br />

VALUES( 3007,new asademo.Product() )<br />

Anstelle dessen müssen Sie die Spalten wie folgt auflisten:<br />

INSERT INTO PRODUCT( id, JProd )<br />

VALUES( 3007,new asademo.Product() )<br />

♦ Trigger Sie können Trigger <strong>für</strong> eine berechnete Spalte definieren, damit<br />

ein INSERT oder UPDATE in diesen Spalten den Trigger auslöst.<br />

Zeitpunkt der Neuberechnung von Spalten<br />

Die berechneten Spalten werden unter folgenden Bedingungen neu<br />

berechnet:<br />

♦ Eine Spalte wird gelöscht, hinzugefügt oder umbenannt.<br />

♦ Die Spalte wird umbenannt.<br />

♦ Der Datentyp oder die COMPUTE-Klausel einer Spalte wird geändert.<br />

♦ Eine Zeile wird eingefügt.<br />

♦ Eine Zeile wird aktualisiert.<br />

Berechnete Spalten werden nicht neu berechnet, wenn sie abgefragt werden.<br />

Wenn Sie einen Ausdruck verwenden, der zeitabhängig ist oder in anderer<br />

Weise vom Status der Datenbank abhängt, bringt die berechnete Spalte<br />

möglicherweise nicht das gewünschte Ergebnis.<br />

139


Speicher <strong>für</strong> Java konfigurieren<br />

Speicher <strong>für</strong> Java konfigurieren<br />

Datenbank und<br />

Verbindung<br />

Speicherbelegung<br />

140<br />

In diesem Abschnitt wird beschrieben, welche Speichererfordernisse <strong>für</strong> Java<br />

in der Datenbank bestehen, und wie Sie Ihren Server so einrichten, dass diese<br />

Anforderungen erfüllt werden.<br />

Die Java VM benötigt viel Cachespeicher.<br />

$ Hinweise zur Optimierung des Caches finden Sie unter "Performance<br />

durch den Einsatz eines Cachespeichers steigern" auf Seite 170 der<br />

Dokumentation ASA SQL-Benutzerhandbuch.<br />

Die Java VM benutzt Speicher sowohl pro Datenbank, als auch pro<br />

Verbindung.<br />

♦ Der erforderliche Speicher <strong>für</strong> die Datenbank ist nicht auslagerbar: Die<br />

Seiten können nicht auf die Festplatte ausgelagert werden. Sie müssen in<br />

den Servercache passen. Dieser Typ des Speichers ist nicht <strong>für</strong> den<br />

Server vorgesehen, sondern <strong>für</strong> jede Datenbank. Wenn Sie die<br />

Cacheerfordernisse berechnen wollen, müssen Sie die Erfordernisse <strong>für</strong><br />

jede Datenbank zusammenzählen, die auf dem Server laufen soll.<br />

♦ Der erforderliche Speicher pro Verbindung ist auslagerbar, aber nur als<br />

Einheit. Der erforderliche Speicher <strong>für</strong> eine Verbindung ist entweder<br />

komplett im Cache oder komplett in einer temporären Datei.<br />

Java in der Datenbank benötigt Speicher <strong>für</strong> verschiedene Zwecke:<br />

♦ Wenn Java auf einem laufenden Server zum ersten Mal benutzt wird,<br />

holt das System die VM in den Speicher. Die VM braucht dort ca. 1,5<br />

MByte Platz. Dieser Speicherbedarf wird in den erforderlichen Speicher<br />

<strong>für</strong> die Datenbank eingerechnet. Eine zusätzliche VM wird <strong>für</strong> jede<br />

Datenbank geladen, die Java benutzt.<br />

♦ Für jede Verbindung, die Java benutzt, wird eine neue Instanz der VM<br />

<strong>für</strong> diese Verbindung geladen. Die neue Instanz benötigt ca. 200 KByte<br />

pro Verbindung.<br />

♦ Jede in einer Java-Anwendung benutzte Klassendefinition wird in den<br />

Speicher geladen. Sie wird im Datenbankspeicher untergebracht:<br />

Getrennte Kopien sind <strong>für</strong> die einzelnen Verbindungen nicht<br />

erforderlich.<br />

♦ Jede Verbindung benötigt eine arbeitende Gruppe von Java-Variablen<br />

und Anwendungs-Stack-Speicherplatz <strong>für</strong> Methodenargumente etc.).


Verwaltung des<br />

Speichers<br />

VM starten und<br />

stoppen<br />

Kapitel 4 Java in der Datenbank benutzen<br />

Sie können die Speicherbelegung wie folgt steuern:<br />

♦ Gesamtcachegröße setzen Sie müssen die Größe des Caches so<br />

setzen, dass alle Erfordernisse des nicht auslagerbaren Speichers erfüllt<br />

werden.<br />

Die Cachegröße wird mit der Befehlszeilenoption -c beim Serverstart<br />

gesetzt.<br />

In vielen Fällen reicht eine Cachegröße von 8 MByte aus.<br />

♦ Speicher <strong>für</strong> den Namensbereich setzen Der Java-Namensbereich ist<br />

die Maximalgröße der Datenbankspeichererfordernisse in Bytes.<br />

Sie können diesen Wert mit der Option JAVA_NAMESPACE_SIZE<br />

setzen. Diese Option ist global und kann nur von einem Benutzer mit<br />

DBA-Berechtigung gesetzt werden.<br />

♦ Heap-Größe setzen Diese Option JAVA_HEAP_SIZE setzt die<br />

Maximalgröße des pro Verbindung erforderlichen Speichers in Byte.<br />

Diese Option kann <strong>für</strong> einzelne Verbindungen gesetzt werden, betrifft<br />

aber den <strong>für</strong> andere Benutzer verfügbaren Speicher und darf daher nur<br />

von einem Benutzer mit DBA-Berechtigung verwendet werden.<br />

Sie können nicht nur Speicherparameter <strong>für</strong> Java setzen, sondern auch die<br />

VM entladen, wenn Java nicht benutzt wird, indem Sie die Anweisung STOP<br />

JAVA aufrufen. Nur ein Benutzer mit DBA-Berechtigung kann diese<br />

Anweisung ausführen. Die Syntax ist einfach:<br />

STOP JAVA<br />

Die VM wird geladen, wenn ein Java-Vorgang ausgeführt wird. Wenn Sie<br />

die VM explizit laden wollen, damit sie <strong>für</strong> Java-Vorgänge bereit steht,<br />

können Sie folgende Anweisung ausführen:<br />

START JAVA<br />

141


Speicher <strong>für</strong> Java konfigurieren<br />

142


KAPITEL 5<br />

Datenzugriff über JDBC<br />

Über dieses<br />

Kapitel<br />

Inhalt<br />

In diesem Kapitel wird beschrieben, wie JDBC <strong>für</strong> den Zugriff auf Daten<br />

eingesetzt werden kann.<br />

JDBC kann sowohl aus Clientanwendungen als auch innerhalb einer<br />

Datenbank eingesetzt werden. Java-Klassen, die JDBC verwenden, bieten<br />

eine leistungsstärkere Alternative zu gespeicherten Prozeduren in SQL <strong>für</strong><br />

die Einbeziehung von Programmierlogik in die Datenbank.<br />

Thema Seite<br />

Überblick über JDBC 144<br />

jConnect-JDBC-Treiber verwenden 150<br />

JDBC-ODBC-Brücke verwenden 155<br />

JDBC-Verbindungen herstellen 157<br />

JDBC <strong>für</strong> den Zugriff auf Daten verwenden 165<br />

Verteilte Anwendungen erstellen 174<br />

143


Überblick über JDBC<br />

Überblick über JDBC<br />

JDBC und<br />

<strong>Adaptive</strong> Server<br />

<strong>Anywhere</strong><br />

JDBC-Ressourcen<br />

144<br />

JDBC bietet eine SQL-Schnittstelle <strong>für</strong> Java-Anwendungen: Wenn Sie auf<br />

relationale Daten von Java zugreifen wollen, tun Sie dies über JDBC-<br />

Aufrufe.<br />

Dieses Kapitel ist keine detailgenaue Anleitung <strong>für</strong> die JDBC-<br />

Datenbankschnittstelle, sondern liefert einige einfache Beispiele zur<br />

Einführung von JDBC und zur Illustration, wie sie beim Client und in der<br />

Datenbank eingesetzt werden kann.<br />

$ Die Beispiele veranschaulichen die unterschiedlichen Funktionen beim<br />

Einsatz von JDBC in <strong>Adaptive</strong> Server <strong>Anywhere</strong>. Weitere Hinweise zum<br />

Programmieren von JDBC finden Sie in jedem beliebigen JDBC-<br />

Programmierhandbuch.<br />

Sie können JDBC auf folgende Weise mit <strong>Adaptive</strong> Server <strong>Anywhere</strong><br />

verwenden:<br />

♦ JDBC auf dem Client Java-Clientanwendungen können JDBC-Aufrufe<br />

in <strong>Adaptive</strong> Server <strong>Anywhere</strong> ausführen. Die Verbindung erfolgt über<br />

einen JDBC-Treiber. SQL <strong>Anywhere</strong> Studio enthält zwei JDBC-Treiber:<br />

den jConnect-Treiber <strong>für</strong> Anwendungen in reinem Java sowie eine<br />

JDBC-ODBC-Brücke.<br />

In diesem Kapitel bezieht sich der Ausdruck Clientanwendung sowohl<br />

auf Anwendungen, die auf dem Rechner des Benutzers laufen, als auch<br />

auf Mittelschicht-Anwendungsserver.<br />

♦ JDBC in der Datenbank In einer Datenbank installierte Java-Klassen<br />

können JDBC-Aufrufe ausführen, um mit Hilfe eines internen JDBC-<br />

Treibers auf Daten in der Datenbank zuzugreifen und diese zu ändern.<br />

♦ Erforderliche Software Sie benötigen TCP/IP <strong>für</strong> den <strong>Sybase</strong> jConnect-<br />

Treiber.<br />

Der <strong>Sybase</strong> jConnect Treiber kann abhängig von Ihrer Installation von<br />

<strong>Adaptive</strong> Server <strong>Anywhere</strong> bereits verfügbar sein.<br />

$ Weitere Hinweise den jConnect-Treiber und seinen Standort finden Sie<br />

unter "Die Dateien des jConnect-Treibers" auf Seite 150.<br />

♦ Beispiel-Quellcode Quellcode <strong>für</strong> die Beispiele in diesem Kapitel<br />

finden Sie in der Datei Samples\ASA\Java\JDBCExamples.java in Ihrem<br />

SQL <strong>Anywhere</strong>-Verzeichnis.<br />

$ Hinweise zur Installation von Java-Beispielen, einschließlich der<br />

Klasse JDBCExamples, finden Sie unter "Java-Beispiele einrichten"<br />

auf Seite 94.


JDBC-Treiber wählen<br />

JDBC-Programmstruktur<br />

Kapitel 5 Datenzugriff über JDBC<br />

Für <strong>Adaptive</strong> Server <strong>Anywhere</strong> werden zwei JDBC-Treiber bereitgestellt:<br />

♦ jConnect Dieser Treiber ist eine 100% reine Java-Implementierung<br />

des Treiber. Er kommuniziert mit <strong>Adaptive</strong> Server <strong>Anywhere</strong> über das<br />

TDS-Client/Server-Protokoll.<br />

♦ JDBC-ODBC-Brücke Dieser Treiber kommuniziert mit <strong>Adaptive</strong><br />

Server <strong>Anywhere</strong> über das Command Sequence-Client/Server-Protokoll.<br />

Sein Verhalten ist mit ODBC-, Embedded SQL- und OLE DB-<br />

Anwendungen konsistent.<br />

Bei der Auswahl des geeigneten Treibers sollten die folgenden Faktoren<br />

beachtet werden:<br />

♦ Features Beide Treiber sind JDK 2-kompatibel. Die JDBC-ODBC-<br />

Brücke bietet vollständig abrollbare Cursor, die in jConnect nicht<br />

verfügbar sind.<br />

♦ "Pure Java" Der jConnect-Treiber ist eine reine Java-Lösung. Die<br />

JDBC-ODBC-Brücke benötigt den <strong>Adaptive</strong> Server <strong>Anywhere</strong> ODBC-<br />

Treiber und ist keine reine Java-Lösung.<br />

♦ Performance Die JDBC-ODBC-Brücke bietet bessere Performance<br />

<strong>für</strong> die meisten Einsatzbereiche als der jConnect-Treiber.<br />

♦ Kompatibilität Das vom jConnect-Treiber verwendete TDS-Protokoll<br />

wird mit <strong>Adaptive</strong> Server Enterprise gemeinsam genutzt. Einige Aspekte<br />

des Verhaltens dieses Treibers werden durch das Protokoll bestimmt und<br />

sind so konfiguriert, dass die Kompatibilität mit <strong>Adaptive</strong> Server<br />

Enterprise gewährleistet bleibt.<br />

Beide Treiber sind <strong>für</strong> Windows 95/98/Me und Windows NT/2000/XP sowie<br />

die unterstützten UNIX- und Linux-Betriebssystemen verfügbar. Sie sind<br />

nicht <strong>für</strong> NetWare oder Windows CE erhältlich.<br />

In JDBC-Anwendungen sind folgende Abläufe typisch:<br />

1 Verbindungsobjekt erstellen Mit dem Aufruf der getConnection-<br />

Klassenmethode der Klasse DriverManager wird ein Connection-<br />

Objekt erstellt, das eine Verbindung mit einer Datenbank einrichtet.<br />

2 Statement-Objekt erstellen Das Objekt Connection erstellt ein<br />

Statement-Objekt.<br />

145


Überblick über JDBC<br />

146<br />

3 SQL-Anweisung übergeben Eine SQL-Anweisung, die in der<br />

Datenbankumgebung ausgeführt werden soll, wird an das Statement-<br />

Objekt übergeben. Wenn die Anweisung eine Abfrage ist, wird durch<br />

diese Aktion ein ResultSet-Objekt zurückgegeben.<br />

Das ResultSet-Objekt enthält die von der SQL-Anweisung<br />

zurückgegebenen Daten, gibt jedoch jeweils nur eine Zeile aus (ähnlich<br />

wie die Arbeitsweise des Cursors).<br />

4 Schleife über die Zeilen der Ergebnismenge Die next-Methode des<br />

Objekts ResultSet führt zwei Aktionen aus:<br />

♦ Die aktuelle Zeile (die Zeile in der über das Objekt ResultSet<br />

ausgegebenen Ergebnismenge), wird eine Zeile weitergeschoben.<br />

♦ Ein Boolescher Wert wird zurückgegeben (TRUE/FALSE), der<br />

angibt, ob eine Zeile vorhanden ist, zu der weitergeschoben werden<br />

kann.<br />

5 Für jede Zeile Werte abrufen Für jede Zeile im ResultSet-Objekt<br />

werden Werte entweder mit dem Namen oder der Position der Spalte<br />

abgerufen. Sie können die Methode getDate verwenden, um den Wert<br />

einer Spalte in der aktuellen Zeile zu beziehen.<br />

Java-Objekte können JDBC-Objekte verwenden, um mit einer Datenbank zu<br />

interagieren und Daten <strong>für</strong> die eigene Verwendung abzurufen, und zwar <strong>für</strong><br />

die eigene Verarbeitung oder <strong>für</strong> den Einsatz in anderen Abfragen.<br />

JDBC-Funktionen in der Datenbank<br />

Die Version von JDBC, die Sie von Java in der Datenbank benutzen können,<br />

wird von der JDK-Version bestimmt, die <strong>für</strong> die Datenbank eingerichtet<br />

wurde.<br />

♦ Wenn Ihre Datenbank mit JDK 1.2 oder JDK 1.3 initialisiert wurde,<br />

können Sie die JDBC 2.0 API verwenden.<br />

$ Hinweise zum Upgrade der Datenbanken auf JDK 1.2 oder JDK<br />

1.3 finden Sie unter "ALTER DATABASE-Anweisung" auf Seite 224<br />

der Dokumentation ASA SQL-Referenzhandbuch oder "Upgrade einer<br />

Datenbank mit dem Befehlszeilenprogramm ""dbupgrad""" auf<br />

Seite 583 der Dokumentation ASA Datenbankadministration.<br />

♦ Falls Ihre Datenbank mit JDK 1.1 initialisiert wurde, können Sie die<br />

Funktionen von JDBC 1.2 verwenden. Der interne JDBC-Treiber <strong>für</strong><br />

JDK 1.1 (asajdbc) stellt einige Funktionen von JDBC 2.0 von<br />

serverseitigen Java-Anwendungen zur Verfügung, bietet aber keine volle<br />

JDBC 2.0-Unterstützung.


Kapitel 5 Datenzugriff über JDBC<br />

$ Weitere Hinweise finden Sie unter "JDBC 2.0-Funktionen von<br />

JDK 1.1-Datenbanken aus benutzen" auf Seite 147.<br />

JDBC 2.0-Funktionen von JDK 1.1-Datenbanken aus benutzen<br />

Einschränkungen<br />

von JDBC 2.0<br />

In diesem Abschnitt wird beschrieben, wie JDBC 2.0-Funktionen von<br />

Datenbanken aus benutzt werden, die mit JDK 1.1 initialisiert wurden. In<br />

vielen Fällen ist es besser, Ihre Version von Java in der Datenbank auf 1.3<br />

umzustellen.<br />

Bei Datenbanken, die mit JDK 1.1 initialisiert wurden, enthält das Paket<br />

sybase.sql.ASA Funktionen, die Teil von JDBC 2.0 sind. Um diese JDBC<br />

2.0-Funktionen verwenden zu können, müssen Sie Ihre JDBC-Objekte in die<br />

entsprechenden Klassen im Paket sybase.sql.ASA und nicht im Paket<br />

java.sql einbauen. Klassen, die als java.sql deklariert sind, bleiben auf die<br />

JDBC 1.2-Funktionen beschränkt.<br />

Die Klassen in sybase.sql.ASA sind:<br />

JDBC-Klasse Interne <strong>Sybase</strong>-Treiberklasse<br />

java.sql.Connection sybase.sql.ASA.SAConnection<br />

java.sql.Statement sybase.sql.ASA.SAStatement<br />

java.sql.PreparedStatement sybase.sql.ASA.SAPreparedStatement<br />

java.sql.CallableStatement sybase.sql.ASA.SACallableStatement<br />

java.sql.ResultSetMetaData sybase.sql.ASA.SAResultSetMetaData<br />

java.sql.ResultSet sybase.sql.SAResultSet<br />

java.sql.DatabaseMetaData sybase.sql.SADatabaseMetaData<br />

Die folgende Funktion bietet ein ResultSetMetaData-Objekt <strong>für</strong> eine<br />

vorbereitete Anweisung ohne das ResultSet oder das Ausführen der<br />

Anweisung nötig sind. Diese Funktion ist nicht Teil des Standards JDBC 1.2.<br />

ResultSetMetaData<br />

sybase.sql.ASA.SAPreparedStatement.describe()<br />

Der folgende Code ruft die vorherige Zeile in einer Ergebnismenge ab, eine<br />

Funktion, die in JDBC 1.2 nicht unterstützt wird:<br />

import java.sql.*;<br />

import sybase.sql.asa.*;<br />

ResultSet rs;<br />

// hier mehr Code<br />

( ( sybase.sql.asa.SAResultSet)rs ).previous();<br />

Die folgenden Klassen sind Teil der Kernschnittstelle von JDBC 2.0, stehen<br />

aber im Paket sybase.sql.ASA nicht zur Verfügung:<br />

147


Überblick über JDBC<br />

148<br />

♦ java.sql.Blob<br />

♦ java.sql.Clob<br />

♦ java.sql.Ref<br />

♦ java.sql.Struct<br />

♦ java.sql.Array<br />

♦ java.sql.Map<br />

Die folgenden Kernfunktionen von JDBC 2.0 sind im Paket sybase.sql.ASA<br />

nicht verfügbar:<br />

Klasse in<br />

sybase.sql.ASA<br />

Fehlende Funktionen<br />

SAConnection java.util.Map getTypeMap()<br />

void setTypeMap( java.util.Map map )<br />

SAPreparedStatement void setRef( int pidx, java.sql.Ref r )<br />

void setBlob( int pidx, java.sql.Blob b )<br />

void setClob( int pidx, java.sql.Clob c )<br />

void setArray( int pidx, java.sql.Array a )<br />

SACallableStatement Object getObject( pidx, java.util.Map map )<br />

java.sql.Ref getRef( int pidx )<br />

java.sql.Blob getBlob( int pidx )<br />

java.sql.Clob getClob( int pidx )<br />

java.sql.Array getArray( int pidx )<br />

SAResultSet Object getObject( int cidx, java.util.Map map )<br />

java.sql.Ref getRef( int cidx )<br />

java.sql.Blob getBlob( int cidx )<br />

java.sql.Clob getClob( int cidx )<br />

java.sql.Array getArray( int cidx )<br />

Object getObject( String cName, java.util.Map map )<br />

java.sql.Ref getRef( String cName )<br />

java.sql.Blob getBlob( String cName )<br />

java.sql.Clob getClob( String cName )<br />

java.sql.Array getArray( String cName )


Kapitel 5 Datenzugriff über JDBC<br />

Unterschiede zwischen client- und serverseitigen JDBC-<br />

Verbindungen<br />

Der Unterschied zwischen dem JDBC-Treiber auf dem Client bzw. auf dem<br />

Datenbankserver liegt darin, dass eine Verbindung mit der<br />

Datenbankumgebung hergestellt wird.<br />

♦ Clientseitig Beim clientseitigen JDBC-Treiber erfordert die Herstellung<br />

einer Verbindung den <strong>Sybase</strong> jConnect JDBC- Treiber oder der JDBC-<br />

ODBC-Brücke von <strong>Adaptive</strong> Server <strong>Anywhere</strong>. Die Übergabe von<br />

Argumenten an DriverManager.getConnection richtet die Verbindung<br />

ein. Die Datenbankumgebung ist von der Perspektive der<br />

Clientanwendung aus eine externe Anwendung.<br />

♦ Serverseitig Wenn JDBC innerhalb des Datenbankservers eingesetzt<br />

wird, ist bereits eine Verbindung vorhanden. Der Wert<br />

jdbc:default:connection wird an DriverManager.getConnection<br />

übergeben, damit die JDBC-Anwendung die Möglichkeit erhält,<br />

innerhalb der aktuellen Benutzerverbindung zu arbeiten. Dies ist ein<br />

schneller, effizienter und sicherer Vorgang, weil die Clientanwendung<br />

die Sicherheitsprüfung der Datenbank zur Herstellung der Verbindung<br />

bereits bestanden hat. Benutzer-ID und Kennwort wurden angegeben<br />

und brauchen nicht noch einmal angegeben zu werden. Der interne<br />

JDBC-Treiber kann nur mit der Datenbank der aktuellen Verbindung<br />

eine Verbindung herstellen.<br />

JDBC-Klassen können so geschrieben werden, dass sie auf der Client- und<br />

auf der Serverseite ausgeführt werden, indem Sie eine einzige bedingte<br />

Anweisung <strong>für</strong> die Angabe des URL verwenden. Eine externe Verbindung<br />

erfordert den Rechnernamen und die Portnummer, während die interne<br />

Verbindung jdbc:default:connection benötigt.<br />

149


jConnect-JDBC-Treiber verwenden<br />

jConnect-JDBC-Treiber verwenden<br />

150<br />

Wenn Sie JDBC von einer Clientanwendung oder einem Applet aus<br />

verwenden wollen, brauchen Sie den jConnect JDBC-Treiber, um eine<br />

Verbindung mit Datenbanken von <strong>Adaptive</strong> Server <strong>Anywhere</strong> herstellen zu<br />

können.<br />

jConnect gehört zum Lieferumfang von SQL <strong>Anywhere</strong> Studio. Wenn Sie<br />

<strong>Adaptive</strong> Server <strong>Anywhere</strong> als Teil eines anderen Paketes erhalten haben,<br />

besteht die Möglichkeit, dass jConnect nicht enthalten ist. Sie brauchen<br />

jConnect, um JDBC von Clientanwendungen aus einsetzen zu können. Sie<br />

können JDBC in der Datenbank ohne jConnect verwenden.<br />

Die Dateien des jConnect-Treibers<br />

CLASSPATH <strong>für</strong><br />

jConnect einrichten<br />

Der jConnect JDBC-Treiber ist in einer Reihe von Verzeichnissen unter<br />

<strong>Sybase</strong>\Shared installiert. Es werden zwei Versionen von jConnect<br />

bereitgestellt:<br />

♦ jConnect 4.5 Diese Version von jConnect ist <strong>für</strong> die Entwicklung von<br />

JDK 1.1-Anwendungen vorgesehen. jConnect 4.5 ist im Verzeichnis<br />

<strong>Sybase</strong>\Shared\jConnect-4_5 installiert.<br />

jConnect 4.5 wird als Gruppe von Klassen geliefert.<br />

♦ jConnect 5.5 Diese Version von jConnect ist <strong>für</strong> die Entwicklung von<br />

JDK 1.2-Anwendungen vorgesehen. jConnect 5.5 ist im Verzeichnis<br />

<strong>Sybase</strong>\Shared\jConnect-5_5 installiert.<br />

jConnect 5.5 wird als jar-Datei mit dem Namen jconn2.jar geliefert.<br />

Beispiele in diesem Kapitel verwenden jConnect 5.5. Benutzer von jConnect<br />

4.5 müssen die entsprechenden Anpassungen vornehmen.<br />

Damit Ihre Anwendung "jConnect" verwenden kann, müssen die jConnect-<br />

Klassen beim Kompilieren und Ausführen in die Umgebungsvariable<br />

CLASSPATH einbezogen sein, sodass der Java-Compiler und die Java-<br />

Machine die notwendigen Dateien ausfindig machen können.<br />

Der folgende Befehl fügt den jConnect 5.5-Treiber in eine vorhandene<br />

CLASSPATH-Umgebungsvariable ein, wobei Suchpfad Ihr <strong>Sybase</strong>\Shared–<br />

Verzeichnis ist.<br />

set classpath=%classpath%;Suchpfad\jConnect-5_5\classes\jconn2.jar<br />

Mit dem folgenden Befehl wird der jConnect 4.5-Treiber einer vorhandenen<br />

CLASSPATH-Umgebungsvariablen hinzugefügt:<br />

set classpath=%classpath%;Suchpfad\jConnect-4_5\classes


jConnect-Klassen<br />

importieren<br />

Kapitel 5 Datenzugriff über JDBC<br />

Die Klassen in jConnect befinden sich alle im Paket com.sybase.<br />

Wenn Sie jConnect 5.5 verwenden, muss Ihre Anwendung auf Klassen in<br />

com.sybase.jdbc2.jdbc zugreifen. Sie müssen diese Klassen am Anfang<br />

einer jeden Quelldatei importieren:<br />

import com.sybase.jdbc2.jdbc.*<br />

Wenn Sie jConnect 4.5 verwenden, befinden sich die Klassen in<br />

com.sybase.jdbc. Sie müssen diese Klassen am Anfang einer jeden<br />

Quelldatei importieren:<br />

import com.sybase. jdbc.*<br />

jConnect-Systemobjekte in einer Datenbank installieren<br />

Wenn Sie mit jConnect auf Systemtabellendaten zugreifen wollen<br />

(Datenbank-Metadaten), müssen Sie die jConnect-Systemobjekte Ihrer<br />

Datenbank hinzufügen.<br />

Die jConnect-Systemobjekte werden standardmäßig jeder neuen Datenbank<br />

hinzugefügt. Sie können die jConnect-Objekte der Datenbank beim Erstellen,<br />

beim Upgrade oder zu einem späteren Zeitpunkt hinzufügen.<br />

Sie können die jConnect-Systemobjekte über <strong>Sybase</strong> Central oder über<br />

Interactive SQL installieren.<br />

v So fügen Sie jConnect-Systemobjekte einer Datenbank hinzu<br />

(<strong>Sybase</strong> Central):<br />

1 Stellen Sie von <strong>Sybase</strong> Central aus als Benutzer mit DBA-Berechtigung<br />

eine Verbindung her.<br />

2 Im linken Fensterausschnitt von <strong>Sybase</strong> Central rechtsklicken Sie auf<br />

das Datenbanksymbol und wählen "jConnect Metadatenunterstützung<br />

neu installieren" aus dem Einblendmenü.<br />

v So fügen Sie jConnect-Systemobjekte einer Datenbank hinzu<br />

(Interactive SQL):<br />

♦ Stellen Sie über Interactive SQL als Benutzer mit DBA-Berechtigung<br />

eine Verbindung her und geben Sie im Ausschnitt <strong>für</strong> die Eingabe der<br />

SQL-Anweisungen folgenden Befehl ein:<br />

read Suchpfad\scripts\jcatalog.sql<br />

wobei Suchpfad Ihr SQL <strong>Anywhere</strong>-Verzeichnis ist.<br />

151


jConnect-JDBC-Treiber verwenden<br />

jConnect-Treiber laden<br />

152<br />

Tipp<br />

Sie können die jConnect-Systemobjekte einer Datenbank auch über die<br />

Befehlszeile hinzufügen: Die Eingabe bei der Eingabeaufforderung lautet<br />

wie folgt:<br />

dbisql -c "uid=Benutzer;pwd=Kennwort"<br />

Suchpfad\scripts\jcatalog.sql<br />

Dabei gilt: Benutzer und Kennwort gehören zu einem Benutzer mit DBA-<br />

Berechtigung, und Suchpfad ist Ihr SQL <strong>Anywhere</strong>-Verzeichnis.<br />

Bevor Sie jConnect in Ihrer Anwendung benutzen können, müssen Sie die<br />

Treiber laden, indem Sie folgende Anweisung eingeben.<br />

Class.forName("com.sybase.jdbc2.jdbc.SybDriver").newInstance();<br />

Einem Server einen URL liefern<br />

Mit der Methode newInstance werden Probleme in einigen Browsern<br />

vermieden.<br />

Um per jConnect eine Verbindung mit einer Datenbank herzustellen, müssen<br />

Sie einen "Uniform Resource Locator" (URL) <strong>für</strong> die Datenbank angeben.<br />

Ein Beispiel finden Sie im Abschnitt "Von einer JDBC-Clientanwendung aus<br />

mit jConnect eine Verbindung herstellen" auf Seite 157 Die Anweisung<br />

lautet wie folgt:<br />

StringBuffer temp = new StringBuffer();<br />

// jConnect-Treiber verwenden ...<br />

temp.append("jdbc:sybase:Tds:");<br />

// zur Verbindung mit angegebenem Rechnernamen...<br />

temp.append(_coninfo);<br />

// auf der Standard-Portnummer des ASA...<br />

temp.append(":2638");<br />

// und baue Verbindung auf.<br />

System.out.println(temp.toString());<br />

conn = DriverManager.getConnection(temp.toString() ,<br />

_props );<br />

Der URL wird folgendermaßen zusammengesetzt:<br />

jdbc:sybase:Tds:Rechnername:Portnummer<br />

Die einzelnen Komponenten sind:


Kapitel 5 Datenzugriff über JDBC<br />

♦ jdbc:sybase:Tds Der <strong>Sybase</strong> jConnect JDBC Treiber unter<br />

Verwendung des TDS-Anwendungsprotokolls<br />

♦ Rechnername Die IP-Adresse oder der Name des Rechners, auf dem<br />

der Server läuft. Wenn Sie eine Verbindung auf demselben Rechner<br />

herstellen, können Sie localhost benutzen, also den aktuellen Rechner.<br />

♦ Portnummer Die Portnummer, an der der Datenbankserver auf<br />

Verbindungsanforderungen wartet. Die <strong>Adaptive</strong> Server <strong>Anywhere</strong><br />

zugewiesene Portnummer ist 2638. Sie sollten diese Nummer<br />

verwenden, es sei denn, es gibt besondere Gründe, dies nicht zu tun.<br />

Die Verbindungszeichenfolge darf nicht länger als 252 Zeichen sein.<br />

Datenbank auf einem Server angeben<br />

Jeder <strong>Adaptive</strong> Server <strong>Anywhere</strong>-Server kann mehrere Datenbanken<br />

gleichzeitig laden. Der oben angegebene URL legt einen Server fest, nicht<br />

aber eine Datenbank. Der Verbindungsversuch wird mit der<br />

Standarddatenbank auf dem Server vorgenommen.<br />

Sie können eine bestimmte Datenbank angeben, indem Sie die URL-Angabe<br />

wie folgt erweitern:<br />

Mit dem Parameter<br />

ServiceName<br />

Mit dem Parameter<br />

RemotePWD<br />

jdbc:sybase:Tds:Rechnername:Portnummer?ServiceName=DBN<br />

Das Fragezeichen, gefolgt von einer Reihe von Zuordnungen, ist ein<br />

Standardverfahren, um einem URL Argumente zu liefern. Die Groß- und<br />

Kleinschreibung von servicename wird nicht berücksichtigt, und vor bzw.<br />

nach dem =-Zeichen darf es keine Leerstellen geben. Der Parameter DBN ist<br />

der Datenbankname.<br />

Eine allgemeinere Methode ist die Eingabe zusätzlicher<br />

Verbindungsparameter wie Datenbankname oder Datenbankdatei mit dem<br />

Feld RemotePWD: Setzen Sie RemotePWD als Eigenschaftsfeld mit der<br />

Methode setRemotePassword().<br />

Nachstehend wird ein Beispielcode <strong>für</strong> die Verwendung dieses Feldes<br />

gezeigt.<br />

sybDrvr = (SybDriver)Class.forName(<br />

"com.sybase.jdbc2.jdbc.SybDriver" ).newInstance();<br />

props = new Properties();<br />

props.put( "User", "DBA" );<br />

props.put( "Password", "SQL" );<br />

sybDrvr.setRemotePassword(<br />

null, "dbf=asademo.db", props );<br />

Connection con = DriverManager.getConnection(<br />

"jdbc:sybase:Tds:localhost", props );<br />

153


jConnect-JDBC-Treiber verwenden<br />

154<br />

Mit dem Parameter <strong>für</strong> die Datenbankdatei DBF können Sie mit jConnect<br />

eine Datenbank auf einem Server starten. Standardmäßig wird die Datenbank<br />

mit autostop=YES gestartet. Wenn Sie DBF oder DBN mit utility_db<br />

eingeben, wird die Dienstprogramm-Datenbank automatisch gestartet.<br />

$ Weitere Hinweise zur Dienstprogramm-Datenbank finden Sie unter<br />

"Die Dienstprogrammdatenbank verwenden" auf Seite 249 der<br />

Dokumentation ASA Datenbankadministration.<br />

Für jConnect-Verbindungen eingestellte Datenbankoptionen<br />

Wenn sich eine Anwendung mit dem jConnect-Treiber mit der Datenbank<br />

verbindet, werden zwei gespeicherte Prozeduren aufgerufen:<br />

1 sp_tsql_environment stellt einige Datenbankoptionen <strong>für</strong> die<br />

Kompatibilität mit <strong>Adaptive</strong> Server Enterprise ein.<br />

2 Anschließend wird die Prozedur spt_mda aufgerufen, die einige andere<br />

Optionen einstellt. Insbesondere legt die Prozedur spt_mda die<br />

Einstellung der Option QUOTED_IDENTIFIER fest. Zum Ändern des<br />

Standardverhaltens sollten Sie die Prozedur spt_mda ändern.


JDBC-ODBC-Brücke verwenden<br />

Erforderliche<br />

Dateien<br />

Verbindung<br />

herstellen<br />

Kapitel 5 Datenzugriff über JDBC<br />

Die JDBC-ODBC-Brücke bietet einen JDBC-Treiber, der eine bessere<br />

Performance sowie einige zusätzliche Funktionen im Vergleich zum<br />

jConnect JDBC-Treiber ausweist; die JDBC-ODBC-Brücke ist jedoch im<br />

Gegensatz zum jConnect-Treiber keine reine Java-Lösung.<br />

$ Hinweise zur Auswahl des JDBC-Treibers finden Sie unter "JDBC-<br />

Treiber wählen" auf Seite 145.<br />

Die Java-Komponente der JDBC-ODBC-Brücke ist in der Datei jodbc.jar<br />

enthalten, die Sie im Unterverzeichnis Java der SQL <strong>Anywhere</strong>-Installation<br />

finden. Unter Windows ist die systemeigene Komponente in der Datei<br />

dbjodbc8.dll im Unterverzeichnis win32 der SQL <strong>Anywhere</strong>-Installation zu<br />

finden; <strong>für</strong> UNIX und Linux befindet sich die systemeigene Komponente in<br />

dbjodbc8.so. Die Komponente muss im Systempfad enthalten sein. Wenn<br />

Anwendungen mit diesem Treiber eingeführt werden, müssen auch die<br />

ODBC-Treiberdateien installiert werden.<br />

Der folgende Code veranschaulicht, wie eine Verbindung mit der JDBC-<br />

ODBC-Brücke hergestellt wird:<br />

String driver, url;<br />

Connection conn;<br />

driver="ianywhere.ml.jdbcodbc.IDriver";<br />

url = "jdbc:odbc:dsn=ASA 8.0 Sample";<br />

Class.forName( driver );<br />

conn = DriverManager.getConnection( url );<br />

Dieser Code weist folgende Besonderheiten auf:<br />

♦ Da die Klassen mit Class.forName geladen werden, muss das Paket,<br />

das die JDBC-ODBC-Brücke enthält, nicht mit import-Anweisungen<br />

importiert werden.<br />

♦ jodbc.jar muss im Classpath enthalten sein, wenn Sie die Anwendung<br />

ausführen.<br />

♦ Der URL enthält jdbc:odbc:, gefolgt von einer standardmäßigen<br />

ODBC-Verbindungszeichenfolge. Die Verbindungszeichenfolge ist in<br />

der Regel eine ODBC-Datenquelle; Sie können jedoch auch explizit<br />

durch Strichpunkte getrennte, einzelne Verbindungszeichenfolgen<br />

zusätzlich zu oder an Stelle der Datenquelle verwenden. Weitere<br />

Hinweise zu den Optionen, die Sie in einer Verbindungszeichenfolge<br />

verwenden können, finden Sie unter "Verbindungsparameter" auf<br />

Seite 78 der Dokumentation ASA Datenbankadministration.<br />

155


JDBC-ODBC-Brücke verwenden<br />

Zeichensätze<br />

156<br />

Falls Sie keine Datenquelle verwenden, sollen Sie den ODBC-Treiber<br />

angeben, indem Sie die Treiberoption zur Verbindungszeichenfolge<br />

hinzufügen:<br />

url = "jdbc:odbc:";<br />

url += "driver=<strong>Adaptive</strong> Server <strong>Anywhere</strong> 8.0;...";<br />

Unter UNIX verwendet die JDBC-ODBC-Brücke keine ODBC-Unicode-<br />

Bindungen oder -Aufrufe und nimmt keine Zeichensatzkonvertierungen vor.<br />

Das Senden von Nicht-ASCII-Daten über die Brücke führt zur Beschädigung<br />

der Daten.<br />

Unter Windows verwendet die JDBC-ODBC-Brücke ODBC-Unicode-<br />

Bindungen und -Aufrufe, um Zeichensatzkonvertierungen vorzunehmen.


JDBC-Verbindungen herstellen<br />

Kapitel 5 Datenzugriff über JDBC<br />

In diesem Abschnitt werden Klassen vorgestellt, die von einer Java-<br />

Anwendung aus eine JDBC-Datenbankverbindung herstellen. In den<br />

Beispielen in diesem Abschnit werden jConnect (clientseitig) oder Java in<br />

der Datenbank (serverseitig) verwendet. Hinweise zur Herstellung von<br />

Verbindungen mit der JDBC-ODBC-Brücken finden Sie unter<br />

"JDBC-ODBC-Brücke verwenden" auf Seite 155.<br />

Von einer JDBC-Clientanwendung aus mit jConnect eine<br />

Verbindung herstellen<br />

Wenn Sie von einer JDBC-Anwendung auf Datenbank-Systemtabellen<br />

zugreifen wollen (Datenbank-Metadaten), müssen Sie eine Reihe von<br />

jConnect-Systemobjekten in Ihre Datenbank einfügen. Die internen JDBC-<br />

Treiberklassen und jConnect nutzen gemeinsam gespeicherte Prozeduren <strong>für</strong><br />

die Unterstützung der Datenbank-Metadaten. Diese Prozeduren werden in<br />

allen Datenbanken standardmäßig installiert. Der Parameter dbinit -i<br />

verhindert die Installation.<br />

$ Weitere Hinweise zum Hinzufügen von jConnect-Systemobjekten in<br />

eine Datenbank finden Sie unter "jConnect-JDBC-Treiber verwenden" auf<br />

Seite 150.<br />

Die folgende, vollständige Java-Anwendung ist eine<br />

Befehlszeilenanwendung, die eine Verbindung mit einer laufenden<br />

Datenbank herstellt, eine Reihe von Daten auf der Befehlszeile ausgibt und<br />

beendet wird.<br />

Der erste Schritt einer beliebigen JDBC-Anwendung ist die Herstellung der<br />

Verbindung mit der Datenbank, wenn sie mit dieser arbeiten will.<br />

$ Dieses Beispiel veranschaulicht eine externe Verbindung, bei der es<br />

sich um eine reguläre Client/Server-Verbindung handelt. Hinweise zum<br />

Erstellen einer internen Verbindung von Java-Klassen, die im<br />

Datenbankserver laufen, finden Sie unter "Verbindung von einer<br />

serverseitigen JDBC-Klasse herstellen" auf Seite 161.<br />

157


JDBC-Verbindungen herstellen<br />

Beispielcode <strong>für</strong> eine externe Verbindung<br />

158<br />

Es folgt ein Beispiel-Quellcode <strong>für</strong> die Methoden, die zum Herstellen einer<br />

Verbindung eingesetzt werden. Der Quellcode befindet sich in den Methoden<br />

main und ASAConnect in der Datei JDBCExamples.java im Verzeichnis<br />

Samples\ASA\Java in Ihrem SQL <strong>Anywhere</strong>-Verzeichnis. (Die Kommentare<br />

werden zum besseren Verständnis hier in deutscher Übersetzung<br />

wiedergegeben.)<br />

import java.sql.*; // JDBC<br />

import com.sybase.jdbc2.jdbc.*; // <strong>Sybase</strong> jConnect<br />

import java.util.Properties; // Eigenschaften<br />

import sybase.sql.*; // <strong>Sybase</strong> Dienstprogramme<br />

import asademo.*; // Beispielklassen<br />

classes<br />

public class JDBCExamples{<br />

private static Connection conn;<br />

public static void main( String args[] ){<br />

// Verbindung herstellen<br />

conn = null;<br />

String machineName = ( args.length == 1 ? args[0] :<br />

"localhost" );<br />

ASAConnect( "DBA", "SQL", machineName );<br />

if( conn!=null ) {<br />

System.out.println( "Connection successful" );<br />

}else{<br />

System.out.println( "Connection failed" );<br />

}<br />

}<br />

try{<br />

getObjectColumn();<br />

getObjectColumnCastClass();<br />

insertObject();<br />

}<br />

catch( Exception e ){<br />

System.out.println( "Error: " + e.getMessage() );<br />

e.printStackTrace();<br />

}


Kapitel 5 Datenzugriff über JDBC<br />

private static void ASAConnect( String userID,<br />

String password,<br />

String machineName ) {<br />

// Mit einem <strong>Adaptive</strong> Server <strong>Anywhere</strong> verbinden<br />

String coninfo = new String( machineName );<br />

Properties props = new Properties();<br />

props.put( "user", userID );<br />

props.put( "password", password );<br />

props.put("DYNAMIC_PREPARE", "true");<br />

// jConnect laden<br />

try {<br />

Class.forName( "com.sybase.jdbc2.jdbc.SybDriver"<br />

).newInstance();<br />

String dbURL = "jdbc:sybase:Tds:" + machineName +<br />

":2638/?JCONNECT_VERSION=5";<br />

System.out.println( dbURL );<br />

conn = DriverManager.getConnection( dbURL , props<br />

);<br />

}<br />

catch ( Exception e ) {<br />

System.out.println( "Error: " + e.getMessage() );<br />

e.printStackTrace();<br />

}<br />

}<br />

So funktioniert das Beispiel <strong>für</strong> eine externe Verbindung<br />

Pakete importieren<br />

Das Beispiel <strong>für</strong> eine externe Verbindung ist eine Java-<br />

Befehlszeilenanwendung.<br />

Die Anwendung benötigt mehrere Bibliotheken. Deren Import erfolgt in den<br />

ersten Zeilen von JDBCExamples.java:<br />

♦ Das Paket java.sql enthält die JDBC-Klassen von Sun Microsystems,<br />

die <strong>für</strong> alle JDBC-Anwendungen erforderlich sind. Sie finden sie in der<br />

Datei classes.zip im Java-Unterverzeichnis.<br />

♦ Der aus com.sybase.jdbc2.jdbc importierte <strong>Sybase</strong> jConnect JDBC-<br />

Treiber ist <strong>für</strong> alle Anwendungen erforderlich, die Verbindungen über<br />

jConnect herstellen.<br />

♦ Die Anwendung benutzt eine Eigenschaftsliste (property list). Die<br />

Klasse java.util.Properties ist erforderlich, um mit Eigenschaftslisten<br />

arbeiten zu können. Sie finden sie in der Datei classes.zip im Java-<br />

Unterverzeichnis.<br />

♦ Das Paket asademo enthält Klassen, die in einigen Beispielen verwendet<br />

werden. Sie finden es in der Datei Samples\ASA\Java\asademo.jar.<br />

159


JDBC-Verbindungen herstellen<br />

Die Methode<br />

"main"<br />

Die Methode<br />

"ASAConnect"<br />

160<br />

Jede Java-Anwendung erfordert eine Klasse mit einer Methode mit dem<br />

Namen main, die beim Programmstart aufgerufen wird. In diesem einfachen<br />

Beispiel ist JDBCExamples.main die einzige Methode in der Anwendung.<br />

Die Methode JDBCExamples.main führt folgende Aufgaben aus:<br />

1 Sie verarbeitet das Befehlszeilenargument und benutzt dabei den<br />

Rechnernamen, wenn ein solcher übergeben wurde. Standardmäßig ist<br />

der Name des Rechners localhost, der sich <strong>für</strong> den Personal<br />

Datenbankserver eignet.<br />

2 Sie ruft die Methode "ASAConnect" auf, damit eine Verbindung<br />

hergestellt wird.<br />

3 Sie führt mehrere Methoden aus, die Daten in die Befehlszeile abrollen.<br />

Die Methode JDBCExamples.ASAConnect führt folgende Aufgaben aus:<br />

1 Sie stellt über <strong>Sybase</strong> jConnect eine Verbindung mit der laufenden<br />

Standarddatenbank her.<br />

♦ Class.forName lädt jConnect. Mit der Methode newInstance<br />

werden Probleme in einigen Browsern vermieden.<br />

♦ Die StringBuffer-Anweisungen bauen aus der Literal-Zeichenfolge<br />

und dem in der Befehlszeile angegebenen Rechnernamen eine<br />

Verbindungszeichenfolge auf.<br />

♦ DriverManager.getConnection stellt mit der<br />

Verbindungszeichenfolge eine Verbindung her.<br />

2 Sie gibt die Kontrolle an die aufrufende Methode zurück.<br />

Beispiel <strong>für</strong> eine externe Verbindung<br />

In diesem Abschnitt wird beschrieben, wie das Beispiel <strong>für</strong> eine externe<br />

Verbindung ausgeführt wird.<br />

v So wird die Beispielanwendung <strong>für</strong> eine externe Verbindung erstellt<br />

und ausgeführt:<br />

1 Öffnen Sie eine Befehlszeile.<br />

2 Wechseln Sie in Ihr SQL <strong>Anywhere</strong>-Verzeichnis.<br />

3 Wechseln Sie in das Unterverzeichnis Samples\ASA\Java.<br />

4 Die Datenbank muss auf einem Datenbankserver geladen sein, der mit<br />

TCP/IP läuft. Einen solchen Server können Sie auf Ihrem lokalen<br />

Rechner starten, indem Sie folgenden Befehl ausführen (vom<br />

Unterverzeichnis Samples\ASA\Java aus):


start dbeng8 ..\..\..\asademo<br />

Kapitel 5 Datenzugriff über JDBC<br />

5 Führen Sie das Beispiel aus, indem Sie an der Eingabeaufforderung<br />

folgenden Befehl eingeben:<br />

java JDBCExamples<br />

Wenn Sie dies mit einem Server ausprobieren wollen, der auf einem<br />

anderen Rechner läuft, müssen Sie den Namen dieses Rechners<br />

eingeben. Der Standard ist localhost, wobei es sich um ein Alias <strong>für</strong> den<br />

Namen des aktuellen Rechners handelt.<br />

6 Eine Liste von Personen und Produkten muss an der<br />

Eingabeaufforderung angezeigt werden.<br />

Wenn der Verbindungsversuch fehlschlägt, erscheint stattdessen eine<br />

Fehlermeldung. Prüfen Sie, ob Sie alle erforderlichen Schritte ausgeführt<br />

haben. Prüfen Sie, ob Ihr CLASSPATH richtig eingestellt wurde. Ein<br />

falscher CLASSPATH führt dazu, dass eine Klasse nicht gefunden<br />

werden kann.<br />

$ Weitere Hinweise zur Verwendung von jConnect finden Sie unter<br />

"jConnect-JDBC-Treiber verwenden" auf Seite 150 sowie in der Online-<br />

Dokumentation <strong>für</strong> jConnect.<br />

Verbindung von einer serverseitigen JDBC-Klasse herstellen<br />

SQL-Anweisungen werden in JDBC mit Hilfe der Methode<br />

createStatement des Connection-Objekts aufgebaut. Auch Klassen, die<br />

innerhalb des Servers laufen, müssen eine Verbindung herstellen, damit ein<br />

Connection-Objekt erstellt wird.<br />

Eine Verbindung von einer serverseitigen JDBC-Klasse herzustellen ist<br />

einfacher, als eine externe Verbindung einzurichten. Da die serverseitige<br />

Klasse von einem bereits verbundenen Benutzer ausgeführt wird, verwendet<br />

die Klasse einfach die vorhandene Verbindung.<br />

Beispielcode <strong>für</strong> eine serverseitige Verbindung<br />

Nachstehend wird der Quellcode <strong>für</strong> das Beispiel gezeigt. Den Quellcode<br />

finden Sie in der Methode InternalConnect in<br />

Samples\ASA\Java\JDBCExamples.java in Ihrem SQL <strong>Anywhere</strong>-<br />

Verzeichnis:<br />

public static void InternalConnect() {<br />

try {<br />

conn =<br />

DriverManager.getConnection("jdbc:default:connection");<br />

System.out.println("Hello World");<br />

161


JDBC-Verbindungen herstellen<br />

162<br />

}<br />

}<br />

}<br />

catch ( Exception e ) {<br />

System.out.println("Error: " + e.getMessage());<br />

e.printStackTrace();<br />

}<br />

So funktioniert das Beispiel <strong>für</strong> eine serverseitige Verbindung<br />

In diesem einfachen Beispiel ist InternalConnect() die einzige Methode in<br />

der Anwendung.<br />

Die Anwendung erfordert nur eine der Bibliotheken (JDBC), die in der<br />

ersten Zeile der Klasse JDBCExamples.java importiert werden. Die anderen<br />

werden <strong>für</strong> externe Verbindungen benötigt. Das Paket java.sql enthält die<br />

JDBC-Klassen.<br />

Die InternalConnect()-Methode führt folgende Aufgaben aus:<br />

1 Sie stellt über die aktuelle Verbindung eine Verbindung mit der<br />

laufenden Standarddatenbank her:<br />

♦ DriverManager.getConnection stellt eine Verbindung unter<br />

Verwendung der Verbindungszeichenfolge<br />

jdbc:default:connection her.<br />

2 Sie gibt an der aktuellen Standardausgabe, d.h. im Serverfenster, Hello<br />

World aus. System.out.println führt die Ausgabe aus.<br />

3 Wenn bei dem Verbindungsversuch ein Fehler auftritt, erscheint eine<br />

Fehlermeldung im Serverfenster, die Auskunft über die Stelle gibt, an<br />

der der Fehler aufgetreten ist.<br />

Die Anweisungen try und catch bieten den Rahmen <strong>für</strong> die<br />

Fehlerbehandlung.<br />

4 Beendet die Klasse<br />

So wird das Beispiel <strong>für</strong> eine serverseitige Verbindung ausgeführt.<br />

In diesem Abschnitt wird beschrieben, wie das Beispiel <strong>für</strong> eine serverseitige<br />

Verbindung ausgeführt wird.


Kapitel 5 Datenzugriff über JDBC<br />

v So wird die Beispielanwendung <strong>für</strong> eine interne Verbindung erstellt<br />

und ausgeführt:<br />

1 Falls Sie es noch nicht getan haben, kompilieren Sie die Datei<br />

JDBCExamples.java. Wenn Sie das JDK verwenden, können Sie im<br />

Verzeichnis Samples\ASA\Java von einer Befehlszeile aus<br />

folgendermaßen vorgehen:<br />

javac JDBCExamples.java<br />

2 Starten Sie einen Datenbankserver mit der Beispieldatenbank. Einen<br />

solchen Server können Sie auf Ihrem lokalen Rechner starten, indem Sie<br />

folgenden Befehl ausführen (vom Unterverzeichnis Samples\ASA\Java<br />

aus):<br />

start dbeng8 ..\..\..\asademo<br />

In diesem Fall ist das TCP/IP-Netzwerkprotokoll nicht erforderlich, da<br />

jConnect nicht verwendet wird.<br />

3 Installieren Sie die Klasse in der Beispieldatenbank. Wenn die<br />

Verbindung mit der Beispieldatenbank hergestellt ist, können Sie von<br />

Interactive SQL aus folgenden Befehl verwenden:<br />

INSTALL JAVA NEW<br />

FROM FILE<br />

’Suchpfad\Samples\ASA\Java\JDBCExamples.class’<br />

Dabei gilt: Suchpfad ist der Suchpfad zu Ihrem Installationsverzeichnis.<br />

Es besteht außerdem die Möglichkeit, die Klasse mit <strong>Sybase</strong> Central zu<br />

installieren. Öffnen Sie den Ordner mit den Java-Objekten bei<br />

vorhandener Verbindung mit der Datenbank und doppelklicken Sie auf<br />

"Java-Klasse hinzufügen". Befolgen Sie dann die Anweisungen im<br />

Assistenten.<br />

4 Jetzt können Sie die Methode InternalConnect dieser Klasse aufrufen,<br />

als wenn Sie eine gespeicherte Prozedur aufrufen würden:<br />

CALL JDBCExamples>>InternalConnect()<br />

Beim ersten Aufruf einer Java-Klasse muss die Java Virtual Machine<br />

gestartet werden. Dies kann einige Sekunden dauern.<br />

5 Auf dem Serverbildschirm muss Hello World erscheinen.<br />

163


JDBC-Verbindungen herstellen<br />

Hinweise zu JDBC-Verbindungen<br />

164<br />

♦ AutoCommit-Verhalten Die JDBC-Spezifikation erfordert, dass<br />

standardmäßig nach jeder Datenänderungsanweisung ein COMMIT<br />

ausgeführt wird. Derzeit ist das serverseitige JDBC-Verhalten auf<br />

"Festschreiben" eingestellt. Sie können dieses Verhalten steuern, indem<br />

Sie folgende Anweisung verwenden:<br />

conn.setAutoCommit( false ) ;<br />

Dabei gilt: conn ist das aktuelle Verbindungsobjekt.<br />

♦ Standardwerte <strong>für</strong> die Verbindung Bei der serverseitigen JDBC erstellt<br />

nur der erste Aufruf von getConnection( "jdbc:default:connection" )<br />

eine neue Verbindung mit den Standardwerten. Nachfolgende Aufrufe<br />

geben einen Behälter der aktuellen Verbindung mit allen unveränderten<br />

Verbindungseigenschaften zurück. Wenn Sie AutoCommit in Ihrer<br />

ursprünglichen Verbindung auf OFF setzen, geben alle nachfolgenden<br />

getConnection Aufrufe in demselben Java-Code eine Verbindung mit<br />

AutoCommit in Stellung OFF zurück.<br />

Es kann sinnvoll sein, die Verbindungseigenschaften beim Schließen der<br />

Verbindung auf die Standardwerte zurücksetzen zu lassen, damit<br />

nachfolgende Verbindungen mit Standard-JDBC-Werten eingerichtet<br />

werden. Verwenden Sie da<strong>für</strong> den folgenden Programmcode:<br />

Connection conn = DriverManager.getConnection("");<br />

boolean oldAutoCommit = conn.getAutoCommit();<br />

try {<br />

// Code hierher setzen<br />

}<br />

finally {<br />

conn.setAutoCommit( oldAutoCommit );<br />

}<br />

Diese Hinweise gelten nicht nur <strong>für</strong> AutoCommit, sondern auch <strong>für</strong><br />

andere Verbindungseigenschaften wie TransactionIsolation und<br />

isReadOnly.


Kapitel 5 Datenzugriff über JDBC<br />

JDBC <strong>für</strong> den Zugriff auf Daten verwenden<br />

Vorbereitung der Beispiele<br />

Beispielcode<br />

Java-Anwendungen, die einige oder alle Klassen in der Datenbank enthalten,<br />

bieten einen erheblichen Vorteil gegenüber traditionellen in SQL<br />

geschriebenen gespeicherten Prozeduren. Als Einführung kann es jedoch<br />

hilfreich sein, Parallelen zu mit SQL geschriebenen gespeicherten<br />

Prozeduren zu ziehen, um die Fähigkeiten von JDBC zu demonstrieren. In<br />

den folgenden Beispielen werden Java-Klassen geschrieben, die eine Zeile in<br />

die Tabelle Department einfügen.<br />

Wie auch bei anderen Schnittstellen können SQL-Anweisungen in JDBC<br />

entweder statisch oder dynamisch sein. Statische SQL-Anweisungen<br />

werden in der Java-Anwendung aufgebaut und zur Datenbank gesandt. Der<br />

Datenbankserver analysiert die Anweisung syntaktisch, wählt einen<br />

Ausführungsplan und führt die Anweisung aus. Syntaktische Analyse und<br />

Auswahl eines Ausführungsplans werden in der Folge als Vorbereitung der<br />

Anweisung bezeichnet.<br />

Wenn eine ähnliche Anweisung häufig ausgeführt werden soll (z.B. viele<br />

Einfügungen in eine Tabelle), kann dies zu erheblichem Overhead in der<br />

statischen SQL führen, weil jedesmal der Vorbereitungsschritt ausgeführt<br />

werden muss.<br />

Im Gegensatz dazu enthält eine dynamische SQL-Anweisung Platzhalter.<br />

Die Anweisung wird einmal mit Hilfe dieser Platzhalter vorbereitet und kann<br />

dann mehrmals ausgeführt werden, ohne dass sie neuerlich vorbereitet<br />

werden muss.<br />

In diesem Abschnitt verwenden wir statische SQL. Dynamische SQL wird<br />

weiter unten behandelt.<br />

In diesem Abschnitt wird beschrieben, welche Vorbereitungsmaßnahmen <strong>für</strong><br />

die Beispiele im restlichen Teil des Kapitels ergriffen werden müssen.<br />

Die Codefragmente in diesem Abschnitt stammen aus der vollständigen<br />

Klasse Samples\ASA\Java\JDBCExamples.java.<br />

v So wird die Klasse JDBCExamples installiert:<br />

1 Wenn Sie dies noch nicht getan haben, installieren Sie die Datei<br />

JDBCExamples.class in der Beispieldatenbank. Wenn die Verbindung<br />

von Interactive SQL mit der Beispieldatenbank hergestellt ist, können<br />

Sie im Fensterausschnitt <strong>für</strong> die SQL-Anweisungen folgenden Befehl<br />

verwenden:<br />

165


JDBC <strong>für</strong> den Zugriff auf Daten verwenden<br />

166<br />

INSTALL JAVA NEW<br />

FROM FILE<br />

’Suchpfad\Samples\ASA\Java\JDBCExamples.class’<br />

Dabei gilt: Suchpfad ist der Suchpfad zu Ihrem Installationsverzeichnis.<br />

Es besteht außerdem die Möglichkeit, die Klasse mit <strong>Sybase</strong> Central zu<br />

installieren. Öffnen Sie den Ordner mit den Java-Objekten bei<br />

vorhandener Verbindung mit der Datenbank und doppelklicken Sie auf<br />

"Java-Klasse hinzufügen". Befolgen Sie dann die Anweisungen im<br />

Assistenten.<br />

Einfügen, Aktualisieren und Löschen mit JDBC<br />

Das Objekt Statement führt statische SQL-Anweisungen aus. SQL-<br />

Anweisungen wie INSERT, UPDATE, DELETE, die keine Ergebnismengen<br />

zurückgeben, können Sie mit Hilfe der Methode executeUpdate des Objekts<br />

Statement ausführen. Anweisungen wie CREATE TABLE und andere<br />

Anweisungen zur Datendefinition können auch mit executeUpdate<br />

ausgeführt werden.<br />

Das folgende Codefragment veranschaulicht, wie INSERT-Anweisungen<br />

innerhalb von JDBC ausgeführt werden. Es benutzt eine interne Verbindung,<br />

die im Verbindungsobjekt conn definiert ist. Der Programmcode <strong>für</strong> das<br />

Einfügen von Werten aus einer externen Anwendung mit JDBC benötigt eine<br />

andere Verbindung, ist aber ansonsten unverändert.<br />

public static void InsertFixed() {<br />

// Gibt die aktuelle Verbindung zurück<br />

conn =<br />

DriverManager.getConnection("jdbc:default:connection");<br />

// AutoCommit deaktivieren<br />

conn.setAutoCommit( false );<br />

Statement stmt = conn.createStatement();<br />

Integer IRows = new Integer( stmt.executeUpdate<br />

("INSERT INTO Department (dept_id, dept_name )"<br />

+ "VALUES (201, 'Eastern Sales')"<br />

) );<br />

// Anzahl von aktualisierten Zeilen ausgeben<br />

System.out.println(IRows.toString() + " row<br />

inserted" );<br />

}


Hinweise<br />

Kapitel 5 Datenzugriff über JDBC<br />

Quellcode verfügbar<br />

Dieses Codefragment ist Teil der Methode InsertFixed der Klasse<br />

JDBCExamples, die sich im Unterverzeichnis Samples\ASA\Java Ihres<br />

Installationsverzeichnisses befindet.<br />

♦ Die Methode setAutoCommit deaktiviert das AutoCommit-Verhalten,<br />

sodass Änderungen nur festgeschrieben werden, wenn eine explizite<br />

COMMIT-Anweisung ausgeführt wird.<br />

♦ Die Methode executeUpdate gibt eine Ganzzahl zurück, die die Anzahl<br />

der Zeilen ausdrückt, die von dem Vorgang betroffen waren. In diesem<br />

Fall würde ein erfolgreicher INSERT-Vorgang den Wert Eins (1)<br />

zurückgeben.<br />

♦ Der Rückgabetyp "Ganzzahl" wird in ein Objekt Integer konvertiert.<br />

Die Klasse "Integer" ist ein Behälter <strong>für</strong> den grundlegenden Datentyp<br />

int, der einige nützliche Methoden enthält, wie z.B. toString().<br />

♦ Die Ganzzahl IRows wird in eine Zeichenfolge konvertiert, die<br />

ausgegeben werden muss. Die Ausgabe erfolgt im Serverfenster.<br />

v So wird das Beispiel JDBC Insert ausgeführt:<br />

1 Über Interactive SQL stellen Sie als Benutzer DBA eine Verbindung mit<br />

der Beispieldatenbank her.<br />

2 Die Klasse JDBCExamples muss installiert sein. Sie wird gemeinsam<br />

mit den anderen Java-Beispielklassen installiert.<br />

$ Weitere Hinweise, wie Sie die Java-Beispiele installieren können,<br />

finden Sie unter "Java-Beispiele einrichten" auf Seite 94.<br />

3 Rufen Sie die Methode wie folgt auf:<br />

CALL JDBCExamples>>InsertFixed()<br />

4 Vergewissern Sie sich, dass in die Tabelle Department eine zusätzliche<br />

Zeile eingefügt wurde.<br />

SELECT *<br />

FROM department<br />

Die Zeile 201 ist nicht festgeschrieben. Sie können eine ROLLBACK-<br />

Anweisung ausführen, um die Zeile zu entfernen.<br />

In diesem Beispiel haben Sie gesehen, wie eine sehr einfache JDBC-Klasse<br />

erstellt wird. Die nächsten Beispiele bauen darauf auf.<br />

167


JDBC <strong>für</strong> den Zugriff auf Daten verwenden<br />

Argumente an Java-Methoden übergeben<br />

Hinweise<br />

168<br />

Wir können die Methode InsertFixed erweitern, um zu veranschaulichen,<br />

wie Argumente an Java-Methoden übergeben werden.<br />

Die folgende Methode verwendet Argumente, die im Aufruf als die<br />

einzufügenden Werte an die Methode übergeben werden:<br />

public static void InsertArguments(<br />

String id, String name) {<br />

try {<br />

conn = DriverManager.getConnection(<br />

"jdbc:default:connection" );<br />

String sqlStr = "INSERT INTO Department "<br />

+ " ( dept_id, dept_name )"<br />

+ " VALUES (" + id + ", ’" + name + "’)";<br />

// Anweisung ausführen<br />

Statement stmt = conn.createStatement();<br />

Integer IRows = new Integer( stmt.executeUpdate(<br />

sqlStr.toString() ) );<br />

// Anzahl von aktualisierten Zeilen ausgeben<br />

System.out.println(IRows.toString() + " row<br />

inserted" );<br />

}<br />

catch ( Exception e ) {<br />

System.out.println("Error: " + e.getMessage());<br />

e.printStackTrace();<br />

}<br />

}<br />

♦ Die beiden Argumente sind "department ID" (eine Ganzzahl) und<br />

"department name" (eine Zeichenfolge). Hier werden beide Argumente<br />

als Zeichenfolgen an die Methode übergeben, weil sie als Teil der<br />

Zeichenfolge der SQL-Anweisung verwendet werden.<br />

♦ INSERT ist eine statische Anweisung: Sie nimmt außer der SQL selbst<br />

keine Parameter an.<br />

♦ Wenn Sie eine falsche Anzahl oder einen falschen Typ von Argumenten<br />

angeben, erscheint die Fehlermeldung Prozedur nicht gefunden<br />

(Procedure Not Found).<br />

v So wird die Java-Methode mit Argumenten verwendet:<br />

1 Wenn Sie dies noch nicht getan haben, installieren Sie die Datei<br />

JDBCExamples.class in der Beispieldatenbank.


Abfragen mit JDBC<br />

Kapitel 5 Datenzugriff über JDBC<br />

2 Stellen Sie über Interactive SQL eine Verbindung zur Beispieldatenbank<br />

her und geben Sie folgenden Befehl ein:<br />

call JDBCExamples>>InsertArguments( ’203’, ’Northern<br />

Sales’ )<br />

3 Vergewissern Sie sich, dass in die Tabelle "Department" eine<br />

zusätzliche Zeile eingefügt wurde.<br />

SELECT *<br />

FROM Department<br />

4 Setzen Sie die Änderungen zurück, damit die Datenbank unverändert<br />

bleibt:<br />

ROLLBACK<br />

Das Objekt Statement wird <strong>für</strong> die Ausführung von statischen Abfragen und<br />

<strong>für</strong> Anweisungen eingesetzt, die keine Ergebnismengen zurückgeben. Bei<br />

Abfragen verwenden Sie die Methode executeQuery des Objekts<br />

Statement. Dies führt zur Rückgabe der Ergebnismenge in einem Objekt<br />

ResultSet.<br />

Das folgende Codefragment veranschaulicht, wie Abfragen in JDBC<br />

behandelt werden. Das Codefragment setzt den Gesamt-Bestandswert <strong>für</strong> ein<br />

Produkt in eine Variable mit dem Namen Inventory. Die<br />

Artikelbezeichnung wird in der String-Variablen prodname abgelegt.<br />

Dieses Beispiel ist als Methode Query der Klasse JDBCExamples<br />

verfügbar.<br />

Es gilt die Voraussetzung, dass eine interne bzw. externe Verbindung<br />

hergestellt wurde, die sich im Verbindungsobjekt mit der Bezeichnung conn<br />

befindet.<br />

public static int Query () {<br />

int max_price = 0;<br />

try{<br />

conn = DriverManager.getConnection(<br />

"jdbc:default:connection" );<br />

// Abfrage aufbauen<br />

String sqlStr = "SELECT id, unit_price "<br />

+ "FROM product" ;<br />

// Anweisung ausführen<br />

Statement stmt = conn.createStatement();<br />

ResultSet result = stmt.executeQuery( sqlStr );<br />

while( result.next() ) {<br />

169


JDBC <strong>für</strong> den Zugriff auf Daten verwenden<br />

Das Beispiel<br />

ausführen<br />

Hinweise<br />

170<br />

int price = result.getInt(2);<br />

System.out.println( "Price is " + price );<br />

if( price > max_price ) {<br />

max_price = price ;<br />

}<br />

}<br />

}<br />

catch( Exception e ) {<br />

System.out.println("Error: " + e.getMessage());<br />

e.printStackTrace();<br />

}<br />

return max_price;<br />

}<br />

Wenn Sie die Klasse JDBCExamples in der Beispieldatenbank installiert<br />

haben, können Sie diese Methode mit folgender Anweisung in Interactive<br />

SQL ausführen:<br />

select JDBCExamples>>Query()<br />

♦ Die Abfrage wählt Menge und Einheitspreis <strong>für</strong> alle Produkte mit dem<br />

Namen prodname. Diese Ergebnisse werden in das Objekt ResultSet<br />

mit dem Namen result zurückgegeben.<br />

♦ In der Ergebnismenge wird über jeder Zeile eine Schleife ausgeführt.<br />

Die Schleife verwendet die Methode next.<br />

♦ Für jede Zeile wird der Wert jeder Spalte mit der Methode getInt in eine<br />

Ganzzahlvariable abgerufen. ResultSet umfasst ebenfalls Methoden <strong>für</strong><br />

andere Datentypen, wie etwa getString, getDate und getBinaryString.<br />

Das Argument <strong>für</strong> die Methode getInt ist eine Indexnummer <strong>für</strong> die<br />

Spalte, beginnend mit 1.<br />

Die Datentyp-Konvertierung von SQL auf Java wird gemäß den<br />

Angaben im folgenden Abschnitt erklärt: "Datentypkonvertierung von<br />

SQL in Java" auf Seite 96 der Dokumentation ASA SQL-<br />

Referenzhandbuch.<br />

♦ <strong>Adaptive</strong> Server <strong>Anywhere</strong> unterstützt bidirektional abrollende Cursor.<br />

JDBC bietet jedoch nur die Methode next, die dem Vorwärts-Abrollen<br />

durch die Ergebnismenge entspricht.<br />

♦ Die Methode gibt der aufrufenden Umgebung den Wert max_price<br />

zurück, und Interactive SQL zeigt ihn auf dem Register "Ergebnisse" im<br />

Fenster "Ergebnisse" an.


Kapitel 5 Datenzugriff über JDBC<br />

Vorbereitete Anweisungen <strong>für</strong> effizienteren Zugriff verwenden<br />

Beispiel<br />

Wenn Sie ein Statement-Interface verwenden, muss jede Anweisung, die Sie<br />

an die Datenbank senden, syntaktisch analysiert werden. Außerdem ist ein<br />

Zugriffsplan zu generieren und die Anweisung auszuführen. Die Schritte vor<br />

der eigentlichen Ausführung werden als Vorbereitung der Anweisung<br />

bezeichnet.<br />

Sie können Performance-Vorteile erzielen, wenn Sie die<br />

PreparedStatement-Schnittstelle verwenden. Damit haben Sie die<br />

Möglichkeit, eine Anweisung mit Platzhaltern vorzubereiten, und dann beim<br />

Ausführen der Anweisung diesen Platzhaltern Werte zuzuordnen.<br />

Der Einsatz von vorbereiteten Anweisungen ist besonders dann nützlich,<br />

wenn viele ähnliche Aktionen ausgeführt werden, wie etwa das Einfügen von<br />

vielen Zeilen.<br />

$ Weitere Hinweise über vorbereitete Anweisungen finden Sie unter<br />

"Anweisungen vorbereiten" auf Seite 12.<br />

Das folgende Beispiel zeigt, wie die Schnittstelle PreparedStatement<br />

benutzt werden kann, obwohl das Einfügen einer einzelnen Zeile in der<br />

Praxis nicht mit vorbereiteten Anweisungen erfolgen sollte.<br />

Die folgende Methode der Klasse JDBCExamples führt eine vorbereitete<br />

Anweisung aus:<br />

public static void JInsertPrepared(int id, String name)<br />

try {<br />

conn = DriverManager.getConnection(<br />

"jdbc:default:connection");<br />

// INSERT-Anweisung erstellen<br />

// ? ist ein Platzhalterzeichen<br />

String sqlStr = "INSERT INTO Department "<br />

+ "( dept_id, dept_name ) "<br />

+ "VALUES ( ? , ? )" ;<br />

// Anweisung vorbereiten<br />

PreparedStatement stmt = conn.prepareStatement(<br />

sqlStr );<br />

stmt.setInt(1, id);<br />

stmt.setString(2, name );<br />

Integer IRows = new Integer(<br />

stmt.executeUpdate() );<br />

// Anzahl von aktualisierten Zeilen ausgeben<br />

System.out.println(IRows.toString() + " row<br />

inserted" );<br />

}<br />

171


JDBC <strong>für</strong> den Zugriff auf Daten verwenden<br />

Das Beispiel<br />

ausführen<br />

Objekte einfügen und abrufen<br />

Objekte abrufen<br />

172<br />

}<br />

catch ( Exception e ) {<br />

System.out.println("Error: " + e.getMessage());<br />

e.printStackTrace();<br />

}<br />

Wenn Sie die Klasse JDBCExamples in der Beispieldatenbank installiert<br />

haben, können Sie das Beispiel mit folgender Anweisung ausführen:<br />

call JDBCExamples>>InsertPrepared(<br />

202, ’Eastern Sales’ )<br />

Das Zeichenfolgenargument wird entsprechend den SQL-Regeln in<br />

Apostrophe eingeschlossen. Wenn Sie diese Methode von einer Java-<br />

Anwendung aus aktiviert hätten, sind zur Begrenzung der Zeichenfolge<br />

Anführungszeichen zu verwenden.<br />

Als Schnittstelle <strong>für</strong> relationale Datenbanken ist JDBC <strong>für</strong> das Abrufen von<br />

traditionellen SQL-Datentypen sowie <strong>für</strong> das Arbeiten mit diesen Typen<br />

konzipiert. <strong>Adaptive</strong> Server <strong>Anywhere</strong> umfasst auch abstrakte Datentypen in<br />

Form von Java-Klassen. Die Art, wie Sie mit JDBC auf diese Java-Klassen<br />

zugreifen, hängt davon ab, ob Sie die Objekte einfügen oder abrufen.<br />

$ Weitere Hinweise zum Abrufen und Setzen ganzer Objekte finden Sie<br />

unter "Verteilte Anwendungen erstellen" auf Seite 174.<br />

Auf folgende Art und Weise können Sie Objekte, deren Felder und deren<br />

Methoden abrufen:<br />

♦ Auf Methoden und Felder zugreifen Java-Methoden und -Felder<br />

können in die Auswahlliste einer Abfrage einbezogen werden. Eine<br />

Methode oder ein Feld erscheint als eine Spalte in der Ergebnismenge.<br />

Sie können mit einer der standardmäßigen ResultSet-Methoden darauf<br />

zugreifen, wie etwa getInt oder getString.<br />

♦ Objekt abrufen Wenn Sie eine Spalte mit einem Java-Klassen-Datentyp<br />

in die Auswahlliste einer Abfrage einbeziehen, können Sie die<br />

ResultSet-Methode getObject verwenden, um das Objekt in die Java-<br />

Klasse abzurufen. Dann können Sie innerhalb der Java-Klasse auf die<br />

Methoden und Felder des betreffenden Objekts zugreifen.


Objekte einfügen<br />

Gemischte JDBC-Hinweise<br />

Kapitel 5 Datenzugriff über JDBC<br />

Von einer serverseitigen Java-Klasse aus können Sie die JDBC-Methode<br />

setObject benutzen, um ein Objekt in eine Spalte mit Java-Klassen-Datentyp<br />

einzufügen.<br />

Sie können Objekte mit einer vorbereiteten Anweisung einfügen. Das<br />

folgende Codefragment fügt z.B. ein Objekt vom Typ "MyJavaClass" in eine<br />

Spalte der Tabelle T ein:<br />

java.sql.PreparedStatement ps =<br />

conn.prepareStatement("insert T values( ? )" );<br />

ps.setObject( 1, new MyJavaClass() );<br />

ps.executeUpdate();<br />

Eine Alternative wäre, eine SQL-Variable einzurichten, die das Objekt<br />

enthält, und dann die SQL-Variable in die Tabelle einzufügen.<br />

♦ Zugriffsberechtigungen Wie auf alle Java-Klassen in der Datenbank,<br />

kann jeder beliebige Benutzer auch auf Klassen mit JDBC-Anweisungen<br />

zugreifen. Es gibt keine Entsprechung zur Anweisung GRANT<br />

EXECUTE, die die Berechtigung zum Ausführen von Prozeduren erteilt,<br />

und der Name einer Klasse braucht nicht mit dem Namen des<br />

Eigentümers qualifiziert zu werden.<br />

♦ Berechtigung zum Ausführen Java-Klassen werden mit den<br />

Berechtigungen der sie ausführenden Verbindung ausgeführt. Dieses<br />

Verhalten unterscheidet sich von dem der gespeicherten Prozeduren, die<br />

mit den Berechtigungen des Eigentümers ausgeführt werden.<br />

173


Verteilte Anwendungen erstellen<br />

Verteilte Anwendungen erstellen<br />

Dazugehörige<br />

Aufgaben<br />

Anforderungen <strong>für</strong><br />

verteilte<br />

Anwendungen<br />

174<br />

In einer verteilten Anwendung laufen Teile der Anwendungslogik auf<br />

einem Rechner, andere Teile auf einem anderen. In <strong>Adaptive</strong> Server<br />

<strong>Anywhere</strong> können Sie verteilte Java-Anwendungen erstellen, bei denen ein<br />

Teil der Logik auf dem Datenbankserver, und ein Teil auf dem Clientsystem<br />

läuft.<br />

<strong>Adaptive</strong> Server <strong>Anywhere</strong> ist in der Lage, Java-Objekte mit einem externen<br />

Java-Client auszutauschen.<br />

Die Schlüsselaufgabe <strong>für</strong> eine Clientanwendung in einer verteilten<br />

Anwendung besteht darin, ein Java-Objekt von einer Datenbank abzurufen.<br />

In diesem Abschnitt wird beschrieben, wie dies geschieht.<br />

In anderen Teilen dieses Kapitels haben wir beschrieben, wie mehrere<br />

Aufgaben abgerufen werden, die in Beziehung mit abrufenden Objekten<br />

stehen, jedoch nicht mit dem Abrufen des Objekts selbst verwechselt werden<br />

sollten. Zum Beispiel:<br />

♦ "Java-Objekte abfragen" auf Seite 117 Hier wird beschrieben, wie ein<br />

Objekt in eine SQL-Variable abgerufen wird. Damit ist allerdings noch<br />

nicht das Problem gelöst, wie das Objekt in Ihre Java-Anwendung<br />

gelangt.<br />

♦ "Java-Objekte abfragen" auf Seite 117 Hier wird auch beschrieben, wie<br />

die öffentlichen Felder und der Rückgabewert von Java-Methoden<br />

abgerufen werden. Auch dies unterscheidet sich vom Abrufen eines<br />

Objekts in eine Java-Anwendung.<br />

♦ "Objekte einfügen und abrufen" auf Seite 172 Hier wird beschrieben,<br />

wie Objekte in serverseitige Java-Klassen abgerufen werden. Auch dies<br />

unterscheidet sich vom Abrufen von Objekten in eine Clientanwendung.<br />

Beim Aufbau einer verteilten Anwendung müssen mehrere Aufgaben erfüllt<br />

werden.<br />

v So wird eine verteilte Anwendung aufgebaut:<br />

1 Jede auf dem Server laufende Klasse muss die serialisierbare<br />

Schnittstelle implementieren. Dies ist sehr einfach.<br />

2 Die clientseitige Anwendung muss die Klasse importieren, damit das<br />

Objekt auf der Clientseite wieder aufgebaut werden kann.<br />

3 Verwenden Sie die Methode sybase.sql.ASAUtils.toByteArray auf der<br />

Serverseite, um das Objekt zu serialisieren. Dies ist nur <strong>für</strong> <strong>Adaptive</strong><br />

Server <strong>Anywhere</strong> Version 6.0.1 und älter erforderlich.


Kapitel 5 Datenzugriff über JDBC<br />

4 Verwenden Sie die Methode sybase.sql.ASAUtils.fromByteArray auf<br />

der Clientseite, um das Objekt wieder aufzubauen. Dies ist nur <strong>für</strong><br />

<strong>Adaptive</strong> Server <strong>Anywhere</strong> Version 6.0.1 und älter erforderlich.<br />

Diese Aufgaben werden in den folgenden Abschnitten beschrieben.<br />

Serialisierbare Schnittstelle implementieren<br />

Objekte werden in einer so genannten serialisierten Form vom Server an<br />

eine Clientanwendung übergeben. Das bedeutet, dass jede Zeile folgende<br />

Informationen enthält:<br />

♦ Einen Versionsbezeichner<br />

♦ Einen Bezeichner <strong>für</strong> die Klasse (oder Unterklasse), die gespeichert wird<br />

♦ Die Werte von nicht-statischen, nicht-zeitweiligen Feldern in der Klasse<br />

♦ Andere Overhead-Informationen<br />

Damit ein Objekt an eine Clientanwendung gesendet wird, muss zunächst die<br />

serialisierbare Schnittstelle implementiert werden. Dies ist eine sehr einfache<br />

Aufgabe.<br />

v So wird die serialisierbare Schnittstelle implementiert:<br />

♦ Fügen Sie den Text implements java.io.Serializable in Ihre<br />

Klassendefinition ein.<br />

Zum Beispiel implementiert Samples\ASA\Java\asademo\Product.java<br />

die serialisierbare Schnittstelle über die folgende Deklaration:<br />

public class Product implements java.io.Serializable<br />

Die Implementierung der serialisierbaren Schnittstelle besteht lediglich<br />

darin, zu deklarieren, dass diese Klasse serialisiert werden kann.<br />

Die serialisierbare Schnittstelle enthält weder Methoden noch Variable. Die<br />

Serialisierung eines Objekts besteht darin, dass es in einen Byte-Strom<br />

konvertiert wird, wodurch es auf einer Platte gespeichert bzw. an eine andere<br />

Java-Anwendung gesendet werden und wieder aufgebaut bzw. deserialisiert<br />

werden kann.<br />

Ein Java-Objekt, das in einem Datenbankserver serialisiert, an eine<br />

Clientanwendung gesendet und deserialisiert wurde, ist in jeder Hinsicht<br />

identisch mit dem Original. Einige Variable in einem Objekt brauchen nicht,<br />

bzw. sollten aus Sicherheitsgründen nicht serialisiert werden. Diese<br />

Variablen werden wie in der folgenden Deklaration der Variablen mit Hilfe<br />

des Schlüsselworts transient deklariert:<br />

175


Verteilte Anwendungen erstellen<br />

176<br />

transient String password;<br />

Klassen clientseitig importieren<br />

Wenn ein Objekt mit dieser Variablen deserialisiert wird, enthält die<br />

Variable immer ihren Standardwert Null.<br />

Angepasste Serialisierung kann durch Hinzufügen der Methoden<br />

writeObject() und readObject() zu Ihren Klassen erreicht werden.<br />

$ Weitere Hinweise zur Serialisierung finden Sie im Java Development<br />

Kit (JDK) von Sun Microsystems.<br />

Auf der Clientseite muss jede Klasse, die ein Objekt abruft, Zugriff auf die<br />

geeignete Klassendefinition haben, damit sie das Objekt benutzen kann. Um<br />

die Klasse Product verwenden zu können, die Teil des Pakets asademo ist,<br />

müssen Sie folgende Zeile in Ihre Anwendung einbeziehen:<br />

import asademo.*<br />

Die Datei asademo.jar muss in Ihren CLASSPATH einbezogen sein, damit<br />

dieses Paket gefunden werden kann.<br />

Beispiel <strong>für</strong> eine verteilte Anwendung<br />

Die Klasse JDBCExamples.java enthält drei Methoden als Beispiel <strong>für</strong> den<br />

verteilten Einsatz von Java. Sie werden alle von der Methode main<br />

aufgerufen. Diese Methode wird im Verbindungsbeispiel im Abschnitt "Von<br />

einer JDBC-Clientanwendung aus mit jConnect eine Verbindung herstellen"<br />

auf Seite 157 beschrieben und ist ein Beispiel <strong>für</strong> eine verteilte Anwendung.<br />

So sieht die Methode getObjectColumn aus der Klasse JDBCExamples aus:<br />

private static void getObjectColumn() throws Exception {<br />

// Rückgabe einer Ergebnismenge von einer Spalte mit<br />

// Java-Objekten<br />

asademo.ContactInfo ci;<br />

String name;<br />

String sComment ;<br />

if ( conn != null ) {<br />

Statement stmt = conn.createStatement();<br />

ResultSet rs = stmt.executeQuery(<br />

"SELECT JContactInfo FROM jdba.contact"<br />

);


Ältere Methode<br />

Abfrageergebnisse<br />

serialisieren und<br />

deserialisieren<br />

Kapitel 5 Datenzugriff über JDBC<br />

while ( rs.next() ) {<br />

ci = ( asademo.ContactInfo )rs.getObject(1);<br />

System.out.println( "\n\tStreet: " + ci.street +<br />

"City: " + ci.city +<br />

"\n\tState: " + ci.state +<br />

"Phone: " + ci.phone +<br />

"\n" );<br />

}<br />

}<br />

}<br />

Die getObject-Methode wird wie bei einem internen Java-Fall verwendet.<br />

getObject und setObject empfohlen<br />

Die Methoden getObject und setObject machen eine explizite<br />

Serialisierung und Deserialisierung überflüssig, die bei früheren<br />

Versionen der Software erforderlich waren. In diesem Abschnitt wird <strong>für</strong><br />

Benutzer, die den älteren Programmcode benutzen, die ältere Methode<br />

beschrieben.<br />

In diesem Abschnitt wird beschrieben, wie eines dieser Beispiele<br />

funktioniert. Für die anderen Beispiele können Sie sich den Code ansehen.<br />

Dies ist die Methode serializeColumn einer alten Version der Klasse<br />

JDBCExamples.<br />

private static void serializeColumn() throws Exception {<br />

Statement stmt;<br />

ResultSet rs;<br />

byte arrayb[];<br />

asademo.ContactInfo ci;<br />

String name;<br />

if ( conn != null ) {<br />

stmt = conn.createStatement();<br />

rs = stmt.executeQuery( "SELECT<br />

sybase.sql.ASAUtils.toByteArray( JName.getName() )<br />

AS Name,<br />

sybase.sql.ASAUtils.toByteArray(<br />

jdba.contact.JContactInfo )<br />

FROM jdba.contact" );<br />

while ( rs.next() ) {<br />

arrayb = rs.getBytes("Name");<br />

name = ( String<br />

)sybase.sql.ASAUtils.fromByteArray( arrayb );<br />

arrayb = rs.getBytes(2);<br />

177


Verteilte Anwendungen erstellen<br />

178<br />

ci =<br />

(asademo.ContactInfo)sybase.sql.ASAUtils.fromByteArray(<br />

arrayb );<br />

System.out.println( "Name: " + name +<br />

"\n\tStreet: " + ci.street +<br />

"\n\tCity: " + ci.city +<br />

"\n\tState: " + ci.state +<br />

"\n\tPhone: " + ci.phone +<br />

"\n" );<br />

}<br />

System.out.println( "\n\n" );<br />

}<br />

}<br />

Und so funktioniert die Methode:<br />

1 Es ist bereits eine Verbindung vorhanden, wenn die Methode aufgerufen<br />

wird. Das Verbindungsobjekt wird geprüft, und wenn es vorhanden ist,<br />

wird der Code ausgeführt.<br />

2 Eine SQL-Abfrage wird aufgebaut und ausgeführt. Die Abfrage lautet<br />

folgendermaßen:<br />

SELECT<br />

sybase.sql.ASAUtils.toByteArray( JName.getName() )<br />

AS Name,<br />

sybase.sql.ASAUtils.toByteArray(<br />

jdba.contact.JContactInfo )<br />

FROM jdba.contact<br />

Diese Anweisung führt eine Abfrage in der Tabelle jdba.contact aus. Sie<br />

ruft Daten aus den Spalten JName und JContactInfo ab. Anstatt<br />

einfach nur die Spalten selbst bzw. eine Methode der Spalte abzurufen,<br />

wird die Funktion sybase.sql.ASAUtils.toByteArray verwendet.<br />

3 Der Client führt eine Schleife über die Zeilen der Ergebnismenge aus.<br />

Für jede Zeile wird der Wert jeder Spalte in ein Objekt deserialisiert.<br />

4 Die Ausgabe (System.out.println) zeigt, dass die Felder und Methoden<br />

des Objekts ebenso wie im Originalstatus eingesetzt werden können.<br />

Sonstige Funktionen von verteilten Anwendungen<br />

Es gibt zwei weitere Methoden in JDBCExamples.java, die verteilte<br />

Informatinosverarbeitung verwenden:<br />

♦ serializeVariable Diese Methode erstellt ein natives Java-Objekt, das<br />

von einer SQL-Variablen auf dem Datenbankserver referenziert wird,<br />

und gibt es an die Clientanwendung zurück.


Kapitel 5 Datenzugriff über JDBC<br />

♦ serializeColumnCastClass Diese Methode ähnelt der Methode<br />

serializeColumn, veranschaulicht jedoch, wie Unterklassen wieder<br />

aufgebaut werden. Die abgefragte Spalte (JProd aus der Tabelle<br />

product) hat den Datentyp asademo.Product. Einige der Zeilen sind<br />

asademo.Hat, wobei es sich um eine Unterklasse der Klasse "Product"<br />

handelt. Die richtige Klasse wird clientseitig wieder aufgebaut.<br />

179


Verteilte Anwendungen erstellen<br />

180


KAPITEL 6<br />

Programmieren mit Embedded SQL<br />

Über dieses<br />

Kapitel<br />

Inhalt<br />

In diesem Kapitel wird beschrieben, wie die Embedded SQL-Schnittstelle zu<br />

<strong>Adaptive</strong> Server <strong>Anywhere</strong> verwendet wird.<br />

Thema Seite<br />

Überblick 182<br />

Beispielprogramme mit Embedded SQL 190<br />

Datentypen in Embedded SQL 196<br />

Hostvariable benutzen 200<br />

SQL-Kommunikationsbereich (SQLCA) 208<br />

Daten abrufen 214<br />

Statische und dynamische SQL 223<br />

Der SQL-Deskriptor-Bereich (SQLDA) 228<br />

Lange Werte senden und abfragen 237<br />

Gespeicherte Prozeduren verwenden 243<br />

Programmiertechniken <strong>für</strong> Embedded SQL 247<br />

SQL-Präprozessor 249<br />

Referenz der Bibliotheksfunktion 253<br />

Befehlszusammenfassung <strong>für</strong> Embedded SQL 272<br />

181


Überblick<br />

Überblick<br />

182<br />

Embedded SQL ist eine Datenbank-Programmierschnittstelle <strong>für</strong> die<br />

Programmiersprachen C und C++. Es besteht aus SQL-Anweisungen, die in<br />

C- oder C++-Quellcode eingebettet sind. Die SQL-Anweisungen werden von<br />

einem SQL-Präprozessor in C- oder C++-Quellcode konvertiert, die Sie<br />

anschließend kompilieren.<br />

Während der Laufzeit verwenden Embedded SQL-Anwendungen eine<br />

<strong>Adaptive</strong> Server <strong>Anywhere</strong>-Schnittstellenbibliothek <strong>für</strong> die<br />

Kommunikation mit dem Datenbankserver. Die Schnittstellenbibliothek ist<br />

eine dynamische Verknüpfungsbibliothek (dynamic link library - DLL) oder<br />

- auf den meisten Betriebssystemplattformen - eine gemeinsam genutzte<br />

Bibliothek (shared library).<br />

♦ Unter Windows-Betriebssystemen ist die Schnittstellenbibliothek<br />

dblib8.dll.<br />

♦ Bei UNIX-Betriebssystemen heißt die Schnittstellenbibliothek je nach<br />

Betriebssystem libdblib8.so, libdblib8.sl oder libdblib8.a.<br />

<strong>Adaptive</strong> Server <strong>Anywhere</strong> liefert zwei Arten von Embedded SQL.<br />

Statisches Embedded SQL ist einfacher zu verwenden, jedoch weniger<br />

flexibel als dynamisches Embedded SQL. Diese beiden Arten werden in<br />

diesem Kapitel behandelt.


Überblick über den Entwicklungsprozess<br />

Kapitel 6 Programmieren mit Embedded SQL<br />

Sobald das Anwendungsprogramm erfolgreich vom SQL-Präprozessor<br />

konvertiert und anschließend kompiliert ist, wird es mit der<br />

Importbibliothek <strong>für</strong> die Schnittstellenbibliothek von <strong>Adaptive</strong> Server<br />

<strong>Anywhere</strong> verknüpft, um eine ausführbare Programmdatei zu erzeugen.<br />

Wenn die Datenbank läuft, verwendet diese Programmdatei die <strong>Adaptive</strong><br />

Server <strong>Anywhere</strong>-DLL, um mit der Datenbank zu interagieren. Solange das<br />

Programm durch den Präprozessor läuft, braucht die Datenbank nicht zu<br />

laufen.<br />

Unter Windows gibt es verschiedene Importbibliotheken <strong>für</strong> Watcom C/C++,<br />

<strong>für</strong> Microsoft Visual C++, und <strong>für</strong> Borland C++.<br />

$ Die Verwendung von Importbibliotheken ist die Standard-<br />

Entwicklungsmethode <strong>für</strong> Anwendungen, die Funktionen in DLLs aufrufen.<br />

<strong>Adaptive</strong> Server <strong>Anywhere</strong> bietet eine - empfohlene - alternative Methode,<br />

die die Verwendung von Importbibliotheken vermeidet. Weitere Hinweise<br />

finden Sie unter "Die Schnittstellenbibliothek dynamisch laden" auf<br />

Seite 187.<br />

183


Überblick<br />

Den SQL-Präprozessor verwenden<br />

Befehlszeile<br />

Unterstützte Compiler<br />

184<br />

Der SQL-Präprozessor ist eine Programmdatei namens sqlpp.exe.<br />

Die SQLPP-Befehlszeile sieht wie folgt aus:<br />

sqlpp [ Parameter ] SQL-Dateiname [ Ausgabedateiname ]<br />

Der SQL-Präprozessor konvertiert ein C-Programm mit Embedded SQL,<br />

bevor der C- oder C++-Compiler ausgeführt wird. Der Präprozessor<br />

übersetzt die SQL-Anweisungen in C-/C++-Quellcode und schreibt den<br />

Quellcode in eine Ausgabedatei. Die normale Dateinamenerweiterung <strong>für</strong><br />

Quelldateien mit embedded SQL ist .sqc. Der voreingestellte Name <strong>für</strong> die<br />

Ausgabedatei ist der Name der SQL-Datei mit der Erweiterung .c. Falls der<br />

Name der SQL-Datei bereits die Erweiterung .c hat, erhält die Ausgabedeitei<br />

standardmäßig die Erweiterung .cc.<br />

$ Eine vollständige Auflistung der Optionen finden Sie unter "SQL-<br />

Präprozessor" auf Seite 249.<br />

Der SQL-Präprozessor <strong>für</strong> C wird bisher in Verbindung mit folgenden<br />

Compilern benutzt:<br />

Betriebssystem Compiler Version<br />

Windows Watcom C/C++ 9.5 und höher<br />

Windows Microsoft Visual C/C++ 1.0 und höher<br />

Windows Borland C++ 4.5<br />

Windows CE Microsoft Visual C/C++ 5.0<br />

UNIX GNU oder nativer<br />

Compiler<br />

NetWare Watcom C/C++ 10.6, 11<br />

$ Anweisungen zur Erstellung von NetWare NLMs finden Sie unter<br />

"NetWare loadable Modules erstellen" auf Seite 188.<br />

Header-Dateien <strong>für</strong> Embedded SQL<br />

Alle Header-Dateien befinden sich nach der Installation von <strong>Adaptive</strong> Server<br />

<strong>Anywhere</strong> im Unterverzeichnis h des Installationsverzeichnisses.


Importbibliotheken<br />

Dateiname Beschreibung<br />

Kapitel 6 Programmieren mit Embedded SQL<br />

sqlca.h Wichtigste Header-Datei, wird in alle Embedded SQL-<br />

Programme eingefügt. Die Datei fügt die Strukturdefinition <strong>für</strong><br />

den SQL-Kommunikationsbereich ein (SQL Communication<br />

Area - SQLCA), sowie Prototypen <strong>für</strong> alle Embedded SQL-<br />

Datenbankschnittstellenfunktionen.<br />

sqlda.h SQL-Deskriptorbereich-Strukturdefinition, wird in Embedded<br />

SQL-Programme eingefügt, die dynamisches SQL benutzen<br />

sqldef.h Definition der Datentypen <strong>für</strong> die Embedded SQL-<br />

Schnittstelle. Die Datei enthält auch Strukturdefinitionen und<br />

Rückgabewerte, die gebraucht werden, um den<br />

Datenbankserver aus einem C-Programm zu starten.<br />

sqlerr.h Definitionen <strong>für</strong> Fehlercodes, die im Feld sqlcode des<br />

SQLCA-Bereichs zurückgegeben werden<br />

sqlstate.h Definitionen <strong>für</strong> ANSI/ISO SQL-Standardfehlerzustände, die<br />

im Feld sqlstate des SQLCA-Bereichs zurückgegeben werden<br />

pshpk1.h,<br />

pshpk2.h,<br />

poppk.h<br />

Diese Header stellen sicher, dass das Strukturverdichten<br />

(structure packing) korrekt gehandhabt wird. Sie unterstützen<br />

die Compiler Watcom C/C++, Microsoft Visual C++, IBM<br />

Visual Age und Borland C/C++.<br />

Alle Importbibliotheken sind im Unterverzeichnis lib unter dem<br />

Installationsunterverzeichnis von <strong>Adaptive</strong> Server <strong>Anywhere</strong> installiert. Die<br />

Windows-Importbibliotheken sind zum Beispiel im Unterverzeichnis<br />

win32\lib abgelegt.<br />

Betriebssystem Compiler Importbibliothek<br />

Windows Watcom C/C++ dblibtw.lib<br />

Windows Microsoft Visual<br />

C++<br />

Windows CE Microsoft Visual<br />

C++<br />

dblibtm.lib<br />

dblib8.lib<br />

NetWare Watcom C/C++ dblib8.lib<br />

Solaris (nicht verkettete<br />

Anwendungen)<br />

Solaris (verkettete<br />

Anwendungen)<br />

Alle Compiler libdblib8.so,<br />

libdbtasks8.so<br />

Alle Compiler libdblib8_r.so,<br />

libdbtasks8_r.so<br />

185


Überblick<br />

Ein einfaches Beispiel<br />

186<br />

Die Bibliotheken libdbtasks8 werden von der Bibliothek libdblib8 aufgerufen.<br />

Einige Compiler ermitteln die Position von libdbtasks8 automatisch, während<br />

Sie dies <strong>für</strong> andere explizit angeben müssen.<br />

Es folgt ein sehr einfaches Beispiel <strong>für</strong> ein Embedded SQL-Programm.<br />

#include <br />

EXEC SQL INCLUDE SQLCA;<br />

main()<br />

{<br />

db_init( &sqlca );<br />

EXEC SQL WHENEVER SQLERROR GOTO error;<br />

EXEC SQL CONNECT "DBA" IDENTIFIED BY "SQL";<br />

EXEC SQL UPDATE employee<br />

SET emp_lname = ’Plankton’<br />

WHERE emp_id = 195;<br />

EXEC SQL COMMIT WORK;<br />

EXEC SQL DISCONNECT;<br />

db_fini( &sqlca );<br />

return( 0 );<br />

}<br />

error:<br />

printf( "update unsuccessful -- sqlcode = %ld.n",<br />

sqlca.sqlcode );<br />

db_fini( &sqlca );<br />

return( -1 );<br />

Dieses Beispiel stellt eine Verbindung mit der Datenbank her, aktualisiert<br />

den Nachnamen des Angestellten mit der Nummer 195, schreibt die<br />

Änderung fest und beendet das Programm. Es gibt praktisch keine<br />

Interaktion zwischen dem SQL-Code und dem C-Code. C-Code wird in<br />

diesem Beispiel ausschließlich zur Ablaufsteuerung benutzt. Die Anweisung<br />

WHENEVER wird <strong>für</strong> Fehlerüberprüfung benutzt. Die Fehleraktion (in<br />

diesem Beispiel GOTO) wird nach jeder SQL-Anweisung ausgeführt, die<br />

einen Fehler verursacht.<br />

$ Weitere Hinweise zum Abrufen von Daten finden Sie unter "Daten<br />

abrufen" auf Seite 214.


Struktur von Embedded SQL-Programmen<br />

Kapitel 6 Programmieren mit Embedded SQL<br />

In Embedded-SQL-Programmen sind SQL-Anweisungen in normalen Coder<br />

C++-Code eingebettet. Alle Embedded SQL-Anweisungen beginnen<br />

mit den Worten EXEC SQL und enden mit einem Semikolon (;). Normale<br />

Kommentare der Sprache C sind innerhalb von Embedded SQL-<br />

Anweisungen erlaubt.<br />

Der Quellcode eines C-Programms, das Embedded SQL benutzt, muss vor<br />

der ersten Embedded SQL-Anweisung in der Quelldatei folgende Anweisung<br />

enthalten:<br />

EXEC SQL INCLUDE SQLCA;<br />

Die erste Embedded SQL-Anweisung, die von dem C-Programm ausgeführt<br />

wird, muss eine CONNECT-Anweisung sein. Die CONNECT-Anweisung<br />

stellt eine Verbindung mit dem Datenbankserver her und spezifiziert die<br />

Benutzer-ID <strong>für</strong> alle Anweisungen, die während der Verbindung ausgeführt<br />

werden.<br />

Die CONNECT-Anweisung muss als erste Embedded SQL-Anweisung<br />

ausgeführt werden. Ausnahme: Einige Embedded SQL-Befehle erzeugen<br />

keinen C-Code oder benötigen keine Verbindung mit der Datenbank. Diese<br />

Befehle sind daher vor der CONNECT-Anweisung erlaubt. Die wichtigsten<br />

sind die INCLUDE-Anweisung und die WHENEVER-Anweisung <strong>für</strong> die<br />

Fehlerbehandlung.<br />

Die Schnittstellenbibliothek dynamisch laden<br />

Um Anwendungen zu entwickeln, die Funktionen aus DLLs aufrufen, ist es<br />

üblich, die Anwendung mit einer Importbibliothek zu verknüpfen, die die<br />

erforderlichen Funktionsdefinitionen enthält.<br />

Dieser Abschnitt beschreibt eine alternative Methode, um Anwendungen <strong>für</strong><br />

<strong>Adaptive</strong> Server <strong>Anywhere</strong> zu entwickeln. Die <strong>Adaptive</strong> Server <strong>Anywhere</strong><br />

Schnittstellenbibliothek kann dynamisch geladen werden, ohne dass sie mit<br />

der Importbibliothek verknüpft werden muss, und zwar mit Hilfe des Moduls<br />

esqldll.c im Unterverzeichnis src Ihres Installationsverzeichnisses. Wir<br />

empfehlen, esqldll.c zu benutzen, denn diese Methode ist einfacher<br />

anzuwenden und findet die Schnittstellen-DLL zuverlässiger.<br />

187


Überblick<br />

Beispiel<br />

188<br />

v Um die Schnittstellen-DLL dynamisch zu laden, gehen Sie wie folgt<br />

vor:<br />

1 Ihr Programm muss db_init_dll aufrufen, um die DLL zu laden, und es<br />

muss db_fini_dll aufrufen, um die DLL wieder freizugeben. db_init_dll<br />

muss vor jeder anderen Funktion der Datenbankschnittstelle aufgerufen<br />

werden. Nach db_fini_dll kann keine Funktion der<br />

Datenbankschnittstelle mehr aufgerufen werden.<br />

Sie müssen trotzdem die Bibliotheksfunktionen db_init und db_fini<br />

aufrufen.<br />

2 Fügen Sie vor der Anweisung EXEC SQL INCLUDE SQLCA mit<br />

#include die Header-Datei esqldll.h ein, oder fügen Sie #include <<br />

sqlca.h> in Ihr Embedded SQL-Programm ein.<br />

3 Ein SQL OS (Operating System - Betriebssystem)-Makro muss definiert<br />

werden. Die Header-Datei sqlca.h, die mit esqdll.c eingefügt wird,<br />

versucht das passende Makro zu bestimmen und zu definieren. Bei<br />

bestimmten Kombinationen von Betriebssystemen und Compilern kann<br />

dieser Versuch allerdings fehlschlagen. In diesem Fall müssen Sie<br />

entweder mit #define eine Definition am Beginn Ihrer Datei einfügen,<br />

oder die Definition mit einer Compiler-Option liefern.<br />

Makro Unterstützte Plattformen<br />

_SQL_OS_WINNT Alle Windows-Betriebssysteme<br />

_SQL_OS_UNIX UNIX<br />

_SQL_OS_UNIX NetWare<br />

4 Kompilieren Sie esqldll.c.<br />

5 Statt mit der Importbibliothek verknüpfen Sie Ihre Embedded SQL-<br />

Anwendung mit dem Objektmodul esqldll.obj.<br />

Ein Beispielprogramm, aus dem ersichtlich ist, wie die<br />

Schnittstellenbibliothek dynamisch geladen werden kann, finden Sie im<br />

Unterverzeichnis Samples\ASA\ESQLDynamicLoad in Ihrem<br />

SQL <strong>Anywhere</strong>-Verzeichnis. Der Quellcode befindet sich in<br />

Samples\ASA\ESQLDynamicLoad\sample.sqc.<br />

NetWare loadable Modules erstellen<br />

Sie müssen den Watcom C/C++-Compiler, Version 10.6 oder 11.0<br />

verwenden, um Embedded SQL-Programme als NetWare loadable Modules<br />

(NLM) zu kompilieren.


v So erstellen Sie ein Embedded SQL-NLM:<br />

Kapitel 6 Programmieren mit Embedded SQL<br />

1 Auf einem Windows-basierten System müssen Sie die Embedded SQL-<br />

Datei mit folgendem Befehl vorverarbeiten:<br />

sqlpp -o NETWARE srcfile.sqc<br />

Diese Anweisung erstellt eine Datei mit der Erweiterung .c.<br />

2 Kompilieren Sie file.c mit dem Watcom-Compiler (10.6 oder 11.0) unter<br />

Verwendung der Option /bt=netware.<br />

3 Verknüpfen Sie die sich ergebende Objektdatei mit Hilfe des Watcom-<br />

Linkers mit den folgenden Optionen:<br />

FORMAT NOVELL<br />

MODULE dblib8<br />

OPTION CASEEXACT<br />

IMPORT @dblib8.imp<br />

LIBRARY dblib8.lib<br />

Die Dateien dblib8.imp und dblib8.lib werden mit <strong>Adaptive</strong> Server<br />

<strong>Anywhere</strong> ausgeliefert und befinden sich im Verzeichnis nlm. Für die<br />

Zeilen IMPORT und LIBRARY ist eventuell der vollständige Suchpfad<br />

notwendig.<br />

189


Beispielprogramme mit Embedded SQL<br />

Beispielprogramme mit Embedded SQL<br />

190<br />

Die Embedded SQL-Beispiele sind Teil der <strong>Adaptive</strong> Server <strong>Anywhere</strong>-<br />

Installation. Sie werden im Unterverzeichnis Samples\ASA\C Ihres<br />

Verzeichnisses SQL <strong>Anywhere</strong> gespeichert.<br />

♦ Das Beispiel <strong>für</strong> statische Cursor Samples\ASA\C\cur.sqc zeigt die<br />

Verwendung von statischen SQL-Anweisungen.<br />

♦ Das Beispiel <strong>für</strong> dynamische Cursor und Embedded SQL<br />

Samples\ASA\C\dcur.sqc zeigt die Verwendung von dynamischen SQL-<br />

Anweisungen.<br />

Um die Anzahl der Codezeilen zu verringern, die in den<br />

Beispielprogrammen cur und dcur (und dem odbc-Beispiel) mehrmals<br />

vorkommen, sind die Mainlines und die Druckfunktionen in einer separaten<br />

Datei enthalten. Und zwar in mainch.c <strong>für</strong> zeichenbasierte Systeme und in<br />

mainwin.c <strong>für</strong> fensterbasierte Systeme.<br />

Die Beispielprogramme liefern jeweils folgende drei Routinen, die von den<br />

Mainlines aufgerufen werden.<br />

♦ WSQLEX_Init Stellt eine Verbindung zur Datenbank her und öffnet den<br />

Cursor<br />

♦ WSQLEX_Process_Command Verarbeitet Benutzerbefehle und<br />

bedient den Cursor<br />

♦ WSQLEX_Finish Schließt den Cursor und trennt die Verbindung zur<br />

Datenbank<br />

Die Funktion der Mainline ist:<br />

1 Die Routine WSQLEX_Init aufzurufen<br />

2 Sie ist eine Schleife, die Befehle vom Benutzer abholt, und<br />

WSQL_Process_Command aufruft, bis der Benutzer das Programm<br />

beendet<br />

3 Die Routine WSQLEX_Finish aufzurufen<br />

Die Verbindung mit der Datenbank wird mit dem Embedded SQL-Befehl<br />

CONNECT hergestellt, der die erforderliche Benutzer-ID und das Kennwort<br />

bereitstellt.<br />

Zusätzlich zu diesen Beispielen können Sie als Teil von SQL <strong>Anywhere</strong><br />

Studio weitere Programme und Quelldateien finden, die Eigenschaften des<br />

Servers <strong>für</strong> bestimmte Betriebssystemplattformen veranschaulichen.


Beispielprogramme erstellen<br />

Beispielprogramme ausführen<br />

Kapitel 6 Programmieren mit Embedded SQL<br />

Dateien <strong>für</strong> den Aufbau der Beispielprogramme werden mit dem<br />

Beispielcode geliefert.<br />

♦ Bei Windows- und NetWare-Betriebssystemen mit Windows als Host-<br />

Betriebssystem, verwenden Sie makeall.bat zum Kompilieren der<br />

Beispielprogramme.<br />

♦ Für UNIX verwenden Sie das Shell-Skript makeall.<br />

♦ Für Windows CE verwenden Sie die dcur.dsp-Projektdatei <strong>für</strong> Microsoft<br />

Visual C++.<br />

Die Syntax des Befehls ist wie folgt:<br />

makeall {Beispiel} {Plattform} {Compiler}<br />

Der erste Parameter ist der Name des Beispielprogramms, das Sie<br />

kompilieren wollen. Es ist eines der folgenden Programme:<br />

♦ CUR Beispiel <strong>für</strong> statischen Cursor<br />

♦ DCUR Beispiel <strong>für</strong> dynamischen Cursor<br />

♦ ODBC Beispiel <strong>für</strong> ODBC<br />

Der zweite Parameter ist die Zielplattform. Sie ist eines der folgenden<br />

Programme:<br />

♦ WINNT Für Windows kompilieren<br />

♦ NETWARE Für NetWare NLM kompilieren<br />

Der dritte Parameter ist der Compiler, mit dem das Programm kompiliert<br />

werden soll. Der Compiler kann einer der folgenden sein:<br />

♦ WC - Watcom C/C++<br />

♦ MC Microsoft C<br />

♦ BC Borland C<br />

Die ausführbaren Dateien befinden sich gemeinsam mit dem Quellcode im<br />

Verzeichnis Samples\ASA\C.<br />

v So wird das Beispielprogramm <strong>für</strong> einen statischen Cursor<br />

ausgeführt:<br />

1 Starten Sie das Programm:<br />

191


Beispielprogramme mit Embedded SQL<br />

Windows Beispiele<br />

192<br />

♦ Starten Sie die Personal Server Beispieldatenbank von <strong>Adaptive</strong><br />

Server <strong>Anywhere</strong>.<br />

♦ Führen Sie die Datei Samples\ASA\C\curwnt.exe aus.<br />

2 Befolgen Sie die Anweisungen auf dem Bildschirm.<br />

Die verschiedenen Befehle verändern einen Datenbankcursor und geben<br />

Abfrageergebnisse am Bildschirm aus. Geben Sie einfach den<br />

Buchstaben des Befehls ein, den Sie ausführen wollen. Bei einigen<br />

Systemen müssen Sie anschließend die Eingabetaste (ENTER) drücken,<br />

um den Befehl auszuführen.<br />

v So wird das Beispielprogramm <strong>für</strong> einen dynamischen Cursor<br />

ausgeführt:<br />

1 Starten Sie das Programm:<br />

♦ Führen Sie die Datei Samples\ASA\C\dcurwnt.exe aus.<br />

2 Stellen Sie eine Verbindung zu einer Datenbank her:<br />

♦ Alle Beispielprogramme haben eine Konsolen-Benutzeroberfläche<br />

mit einer Eingabeaufforderung. Geben Sie die nachstehende<br />

Zeichenfolge ein, damit eine Verbindung mit der Beispieldatenbank<br />

hergestellt wird:<br />

DSN=ASA 8.0 Sample<br />

3 Wählen Sie eine Tabelle:<br />

♦ Jedes einzelne Beispielprogramm fordert Sie auf, eine Tabelle<br />

anzugeben. Wählen Sie eine der Tabellen in der Beispieldatenbank.<br />

Sie können z.B. Customer oder Employee eingeben.<br />

4 Befolgen Sie die Anweisungen auf dem Bildschirm.<br />

Die verschiedenen Befehle verändern einen Datenbankcursor und geben<br />

Abfrageergebnisse am Bildschirm aus. Geben Sie einfach den<br />

Buchstaben des Befehls ein, den Sie ausführen wollen. Bei einigen<br />

Systemen müssen Sie anschließend die Eingabetaste (ENTER) drücken,<br />

um den Befehl auszuführen.<br />

Die Windows-Versionen der Beispielprogramme sind echte Windows-<br />

Programme. Um allerdings den Code <strong>für</strong> die Benutzeroberfläche nicht zu<br />

kompliziert zu gestalten, wurden einige Vereinfachungen vorgenommen. Im<br />

Besonderen schreiben diese Programme auf WM_PAINT-Nachrichten hin<br />

nicht die Fenster neu, sondern nur die Eingabeaufforderung.


Beispiel <strong>für</strong> statischen Cursor<br />

Beispiel <strong>für</strong> dynamischen Cursor<br />

Kapitel 6 Programmieren mit Embedded SQL<br />

Dieses Beispiel zeigt die Verwendung von Cursorn. Der Cursor, der hier<br />

verwendet wurde, ruft bestimmte Informationen aus der Tabelle employee in<br />

der Beispieldatenbank ab. Der Cursor wird statisch deklariert, das heißt, die<br />

SQL-Anweisung, die die Information abruft, ist im Quellprogramm<br />

enthalten. Dies ist ein gutes Beispiel, um zu lernen, wie Cursor<br />

funktionieren. Das nächste Beispiel ("Beispiel <strong>für</strong> dynamischen Cursor" auf<br />

Seite 193) konvertiert dieses erste Beispiel und verwendet dynamische SQL-<br />

Anweisungen.<br />

$ Wo der Quellcode zu finden ist und wie Sie dieses Beispielprogramm<br />

kompilieren, finden Sie unter "Beispielprogramme mit Embedded SQL" auf<br />

Seite 190.<br />

Die open_cursor-Routine deklariert einen Cursor <strong>für</strong> den jeweiligen SQL-<br />

Befehl und öffnet ebenfalls den Cursor.<br />

Die print-Routine druckt eine Seite mit Informationen. Sie führt pagesizemal<br />

eine Schleife aus, die eine einzelne Zeile vom Cursor abruft und druckt.<br />

Beachten Sie, dass die Abrufroutine überprüft, ob eine Warnsituation<br />

vorliegt (wie Row not found), und gegebenenfalls die erforderliche<br />

Fehlermeldung ausgibt. Außerdem positioniert das Programm den Cursor<br />

neu in der Zeile vor derjenigen, die am Anfang der aktuellen Datenseite<br />

ausgegeben wurde.<br />

Die Routinen move, top und bottom benutzen die geeignete Form der<br />

FETCH-Anweisung, um den Cursor zu positionieren. Beachten Sie bitte,<br />

dass diese Form der FETCH-Anweisung nicht tatsächlich die Daten abruft,<br />

die Anweisung positioniert lediglich den Cursor. Außerdem wurde eine<br />

allgemeine Routine namens move zur relativen Positionierung<br />

implementiert, die abhängig vom Vorzeichen des Parameters den Cursor in<br />

die eine oder andere Richtung bewegt.<br />

Beendet der Benutzer das Programm, wird der Cursor geschlossen und die<br />

Datenbankverbindung getrennt. Der Cursor wird durch eine ROLLBACK<br />

WORK-Anweisung geschlossen und die Verbindung mit DISCONNECT<br />

getrennt.<br />

Dieses Beispiel veranschaulicht, wie Cursor <strong>für</strong> eine dynamische SQL-<br />

SELECT-Anweisung verwendet werden. Es ist eine leichte Änderung des<br />

vorangehenden Beispiels. Bitte sehen Sie sich das vorangehende "Beispiel<br />

<strong>für</strong> statischen Cursor" auf Seite 193 an, bevor Sie sich mit diesem Beispiel<br />

befassen.<br />

193


Beispielprogramme mit Embedded SQL<br />

194<br />

$ Wo der Quellcode zu finden ist und wie Sie dieses Beispielprogramm<br />

kompilieren, finden Sie unter "Beispielprogramme mit Embedded SQL" auf<br />

Seite 190.<br />

Das Programm dcur erlaubt dem Benutzer, mit dem n-Befehl eine Tabelle<br />

auszuwählen, die er anschauen möchte. Das Programm zeigt dann so viele<br />

Informationen aus dieser Tabelle an, wie auf den Bildschirm passen.<br />

Wenn dieses Programm ausgeführt wird, erwartet es eine Zeichenfolge <strong>für</strong><br />

die Verbindung der Form:<br />

uid=DBA;pwd=SQL;dbf=c:\Programme\<strong>Sybase</strong>\SQL<br />

<strong>Anywhere</strong> 8\asademo.db<br />

Das C-Programm mit Embedded SQL befindet sich im Unterverzeichnis<br />

Samples\ASA\C Ihres SQL <strong>Anywhere</strong>-Installationsverzeichnisses.<br />

Abgesehen von den Funktionen connect, open_cursor und print gleicht das<br />

Programm weitgehend dem vorigen Beispiel.<br />

Die Funktion connect benutzt die Embedded SQL-Schnittstellenfunktion<br />

db_string_connect, um die Verbindung zur Datenbank herzustellen. Diese<br />

Funktion liefert die zusätzliche Funktionalität, um die Zeichenfolge <strong>für</strong> die<br />

Verbindung zu unterstützen, die benutzt wird, um die Verbindung zur<br />

Datenbank herzustellen.<br />

Die Routine open_cursor baut zuerst die SELECT-Anweisung auf:<br />

SELECT * FROM Tabellenname<br />

Wobei Tabellenname der Parameter ist, der an die Routine übergeben wird.<br />

Dann bereitet sie eine dynamische SQL-Anweisung mit Hilfe dieser<br />

Zeichenfolge vor.<br />

Der Embedded SQL-Befehl DESCRIBE wird benutzt, um die Ergebnisse der<br />

SELECT-Anweisung in die SQLDA-Struktur zu schreiben.<br />

Größe der SQLDA<br />

Zu Beginn wird die Größe der SQLDA geschätzt (3). Ist das nicht groß<br />

genug, wird die tatsächliche Größe der Auswahlliste, die vom<br />

Datenbankserver zurückgegeben wurde, benutzt, um eine SQLDA der<br />

richtigen Größe zuzuweisen.<br />

Die SQLDA-Struktur wird dann mit Puffern gefüllt, die Zeichenfolgen<br />

enthalten, die wiederum <strong>für</strong> das Ergebnis der Abfrage stehen. Die Routine<br />

fill_s_sqlda konvertiert alle Datentypen in der SQLDA in DT_STRING<br />

und weist Puffer der passenden Größe zu.<br />

Dann wird <strong>für</strong> diese Anweisung ein Cursor deklariert und geöffnet. Die<br />

übrigen Routinen zum Bewegen und Schließen des Cursors sind die gleichen<br />

wie beim vorhergehenden Beispiel.


Beispiele <strong>für</strong> Dienste<br />

Kapitel 6 Programmieren mit Embedded SQL<br />

Die fetch-Routine differiert leicht, sie schreibt die Ergebnisse in die<br />

SQLDA-Struktur statt in eine Liste von Hostvariablen. Die print-Routine ist<br />

leicht verändert, um Ergebnisse aus der SQLDA-Struktur bis zur vollen<br />

Bildschirmbreite auszugeben. Die print-Routine benutzt auch die<br />

Namenfelder des SQLDA-Bereichs, um Überschriften <strong>für</strong> die Spalten<br />

auszugeben.<br />

Die Beispielprogramme cur.sqc und dcur.sqc werden optional als Dienste<br />

ausgeführt, wenn sie <strong>für</strong> eine Windows-Version kompiliert werden, auf<br />

denen Dienste laufen können.<br />

Die beiden Dateien, die den Beispielcode <strong>für</strong> Windows-Dienste enthalten,<br />

sind die Quelldatei ntsvc.c und die Header-Datei ntsvc.h. Der Code<br />

ermöglicht es, das damit gelinkte ausführbare Programm entweder als<br />

normales Programm oder als Windows-Dienst auszuführen.<br />

v Um eines der kompilierten Beispiele als Windows-Dienst<br />

auszuführen, gehen Sie wie folgt vor:<br />

1 Starten Sie <strong>Sybase</strong> Central und öffnen Sie das Verzeichnis "Dienste".<br />

2 Wählen Sie einen Diensttyp aus der Beispielanwendung aus und klicken<br />

Sie auf "OK".<br />

3 Geben Sie einen Dienstnamen in das entsprechende Feld ein.<br />

4 Wählen Sie das Beispielprogramm (curwnt.exe oder dcurwnt.exe) aus<br />

dem Unterverzeichnis Samples\ASA|C im SQL <strong>Anywhere</strong>-<br />

Installationsverzeichnis.<br />

5 Klicken Sie auf "OK", um den Dienst zu installieren.<br />

6 Klicken Sie auf "Start" im Hauptfenster, um den Dienst zu starten.<br />

Wird das Programm als Dienst ausgeführt, zeigt es, falls möglich, die<br />

normale Benutzeroberfläche. Die Ausgabe wird in das Ereignisprotokoll der<br />

Anwendung geschrieben. Falls die Benutzeroberfläche nicht gestartet werden<br />

kann, schreiben die Programme eine Seite in das Ereignisprotokoll der<br />

Anwendung und halten an.<br />

Diese Beispiele wurden mit dem Watcom C/C++ 10.5-Compiler und dem<br />

Microsoft Visual C++-Compiler getestet.<br />

195


Datentypen in Embedded SQL<br />

Datentypen in Embedded SQL<br />

196<br />

Um Informationen zwischen einem Programm und dem Datenbankserver<br />

austauschen zu können, müssen alle Datenelemente einen Datentyp haben.<br />

Die Konstanten <strong>für</strong> Embedded SQL haben alle das Präfix DT_ und befinden<br />

sich in der Header-Datei sqldef.h. Eine Hostvariable kann jeden der<br />

unterstützten Datentypen haben. Sie können diese Datentypen auch in einer<br />

SQLDA-Struktur benutzen, um Daten mit der Datenbank auszutauschen.<br />

Sie können mit den DECL_-Makros in sqlca.h Variablen dieser Datentypen<br />

definieren. Beispielsweise kann mit DECL_BIGINT eine Variable mit einem<br />

BIGINT-Wert deklariert werden.<br />

Folgende Datentypen werden von der Embedded SQL-<br />

Programmierschnittstelle unterstützt:<br />

♦ DT_BIT 8-Bit Ganzzahl mit Vorzeichen<br />

♦ DT_SMALLINT 16-Bit-Ganzzahl mit Vorzeichen<br />

♦ DT_UNSSMALLINT 16-Bit Ganzzahl ohne Vorzeichen<br />

♦ DT_TINYINT 8-Bit Ganzzahl mit Vorzeichen<br />

♦ DT_BIGINT 64-Bit Ganzzahl mit Vorzeichen<br />

♦ DT_INT 32-Bit Ganzzahl mit Vorzeichen<br />

♦ DT_UNSINT 16-Bit Ganzzahl ohne Vorzeichen<br />

♦ DT_FLOAT 4-Byte-Gleitkommazahl<br />

♦ DT_DOUBLE 8-Byte-Gleitkommazahl.<br />

♦ DT_DECIMAL gepackte Dezimalzahl<br />

typedef struct DECIMAL {<br />

char array[1];<br />

} DECIMAL;<br />

♦ DT_STRING Mit Nullwert endende Zeichenfolge. Die Zeichenfolge<br />

wird mit Leerzeichen aufgefüllt, wenn bei der Initialisierung der<br />

Datenbank mit Leerzeichen aufgefüllte Zeichenfolgen verwendet<br />

werden.<br />

♦ DT_DATE Mit Nullwert endende Zeichenfolge, die ein gültiges Datum<br />

repräsentiert<br />

♦ DT_TIME Mit Nullwert endende Zeichenfolge, die eine gültige<br />

Zeitangabe repräsentiert<br />

♦ DT_TIMESTAMP Mit Nullwert endende Zeichenfolge, die einen<br />

gültigen Zeitstempel repräsentiert


Kapitel 6 Programmieren mit Embedded SQL<br />

♦ DT_FIXCHAR Zeichenfolge mit fester Länge, mit Leerzeichen aufgefüllt<br />

♦ DT_VARCHAR Zeichenfolge variabler Länge, mit einem 2-Byte-<br />

Längenfeld. Wenn Sie dem Datenbankserver Informationen liefern,<br />

müssen Sie das Längenfeld setzen. Wenn Sie Informationen vom<br />

Datenbankserver abholen, setzt der Datenbankserver das Längenfeld<br />

(nicht aufgefüllt).<br />

typedef struct VARCHAR {<br />

unsigned short int len;<br />

char array[1];<br />

} VARCHAR;<br />

♦ DT_LONGVARCHAR Lange Zeichendaten mit unterschiedlicher Länge.<br />

Das Makro definiert eine Struktur folgendermaßen:<br />

#define DECL_LONGVARCHAR( size ) \<br />

struct { a_sql_uint32 array_len; \<br />

a_sql_uint32 stored_len; \<br />

a_sql_uint32 untrunc_len; \<br />

char array[size+1];\<br />

}<br />

Die DECL_LONGVARCHAR-Struktur kann mit Daten über 32 Kbyte<br />

verwendet werden. Umfangreiche Daten können auf einmal,<br />

beziehungsweise in Abschnitten abgerufen werden, und zwar mit der<br />

GET DATA-Anweisung. Sie können an den Server auf einmal,<br />

beziehungsweise in Abschnitten übermittelt werden, indem sie an eine<br />

Datenbankvariable mit der SET-Anweisung angehängt werden. Die<br />

Daten werden nicht mit Nullwert abgeschlossen.<br />

$ Weitere Hinweise finden Sie unter "Lange Werte senden und<br />

abfragen" auf Seite 237.<br />

♦ DT_BINARY Binärdaten variabler Länge mit einem 2-Byte-Längenfeld.<br />

Wenn Sie dem Datenbankserver Informationen liefern, müssen Sie das<br />

Längenfeld setzen. Wenn Sie Informationen vom Datenbankserver<br />

abholen, setzt der Datenbankserver das Längenfeld.<br />

typedef struct BINARY {<br />

unsigned short int len;<br />

char array[1];<br />

} BINARY;<br />

♦ DT_LONGBINARY Lange Binärdaten. Das Makro definiert eine Struktur<br />

folgendermaßen:<br />

#define DECL_LONGBINARY( size ) \<br />

struct { a_sql_uint32 array_len; \<br />

a_sql_uint32 stored_len; \<br />

a_sql_uint32 untrunc_len; \<br />

char array[size]; \<br />

}<br />

197


Datentypen in Embedded SQL<br />

198<br />

Die DECL_ LONGBINARY -Struktur kann mit Daten über 32 Kbyte<br />

verwendet werden. Umfangreiche Daten können auf einmal<br />

beziehungsweise in Abschnitten abgerufen werden, und zwar mit der<br />

GET DATA-Anweisung. Sie können an den Server auf einmal,<br />

beziehungsweise in Abschnitten übermittelt werden, indem sie an eine<br />

Datenbankvariable mit der SET-Anweisung angehängt werden.<br />

$ Weitere Hinweise finden Sie unter "Lange Werte senden und<br />

abfragen" auf Seite 237.<br />

♦ DT_TIMESTAMP_STRUCT SQLDATETIME-Struktur mit Feldern <strong>für</strong><br />

jeden Teil des Zeitstempels.<br />

typedef struct sqldatetime {<br />

unsigned short year; /* z. B. 1999 */<br />

unsigned char month; /* 0-11 */<br />

unsigned char day_of_week; /* 0-6 0=Sonntag */<br />

unsigned short day_of_year; /* 0-365 */<br />

unsigned char day; /* 1-31 */<br />

unsigned char hour; /* 0-23 */<br />

unsigned char minute; /* 0-59 */<br />

unsigned char second; /* 0-59 */<br />

unsigned long microsecond; /* 0-999999 */<br />

} SQLDATETIME;<br />

Die SQLDATETIME-Struktur kann benutzt werden, um Felder vom<br />

Typ DATE, TIME und TIMESTAMP abzurufen (oder alles, was in<br />

einen dieser Datentypen konvertiert werden kann). Anwendungen haben<br />

häufig eigene Formate und einen eigenen Programmcode <strong>für</strong> Zeit und<br />

Datum. Der Abruf von Daten in dieser Struktur, erleichtert dem<br />

<strong>Programmierer</strong> den Umgang damit. Beachten Sie, dass Felder vom Typ<br />

DATE, TIME und TIMESTAMP auch mit einem beliebigen<br />

Zeichendatentyp abgerufen und aktualisiert werden können.<br />

Wenn Sie eine SQLDATETIME-Struktur verwenden, um ein Datum,<br />

eine Zeit oder einen Zeitstempel in die Datenbank einzugeben, werden<br />

die Untersätze day_of_year und day_of_week ignoriert.<br />

$ Näheres finden Sie unter den Datenbankoptionen<br />

DATE_FORMAT, TIME_FORMAT, TIMESTAMP_FORMAT und<br />

DATE_ORDER in "Datenbankoptionen" auf Seite 597 der<br />

Dokumentation ASA Datenbankadministration.<br />

♦ DT_VARIABLE mit Nullwert abgeschlossene Zeichenfolge. Die<br />

Zeichenfolge muss der Name einer SQL-Variablen sein, deren Wert<br />

vom Datenbankserver benutzt wird. Dieser Datentyp wird ausschließlich<br />

benutzt, um Daten an den Datenbankserver zu liefern. Er kann nicht<br />

benutzt werden, um Daten vom Datenbankserver abzurufen.


Datenbank-<br />

Datentypen DATE<br />

und TIME<br />

Kapitel 6 Programmieren mit Embedded SQL<br />

Die Strukturen sind in der Datei sqlca.h festgelegt. Die Datentypen<br />

VARCHAR, BINARY und DECIMAL enthalten ein Array, das aus einem<br />

einzigen Zeichen besteht und sind daher nicht geeignet, um Hostvariable zu<br />

deklarieren. Sie sind dagegen nützlich, um Variable dynamisch zuzuweisen<br />

oder Variable zu konvertieren (typecasting).<br />

Die Embedded SQL-Schnittstelle bietet keine Datentypen, die den<br />

verschiedenen Datenbank-Datentypen von DATE und TIME entsprechen.<br />

Diese Datenbank-Datentypen werden alle entweder mit der Struktur<br />

SQLDATETIME oder mit Zeichenfolgen abgerufen und aktualisiert.<br />

$ Weitere Hinweise finden Sie unter "GET DATA-Anweisung [ESQL]"<br />

auf Seite 471 der Dokumentation ASA SQL-Referenzhandbuch und "SET-<br />

Anweisung" auf Seite 572 der Dokumentation ASA SQL-Referenzhandbuch.<br />

199


Hostvariable benutzen<br />

Hostvariable benutzen<br />

Hostvariable deklarieren<br />

Beispiel<br />

200<br />

Hostvariable sind C-Variable, die dem SQL-Präprozessor bekannt gemacht<br />

werden. Hostvariable können benutzt werden, um Werte an den<br />

Datenbankserver zu übergeben oder um Werte vom Datenbankserver<br />

abzurufen.<br />

Hostvariable sind recht einfach zu benutzen, aber sie unterliegen einigen<br />

Einschränkungen. Dynamische SQL ist eine allgemeinere Art, um<br />

Informationen mit dem Datenbankserver auszutauschen, mit Hilfe einer<br />

Struktur namens SQL-Deskriptor-Bereich (SQL Descriptor Area - SQLDA).<br />

Der SQL-Präprozessor erzeugt <strong>für</strong> jede einzelne Anweisung, in der<br />

Hostvariablen verwendet werden, automatisch ein SQLDA.<br />

$ Weitere Hinweise zu dynamischem SQL finden Sie unter "Statische<br />

und dynamische SQL" auf Seite 223.<br />

Hostvariable werden definiert, indem sie in einen Deklarationsabschnitt<br />

eingefügt werden (declaration section). Wie in den Standards <strong>für</strong> IBM SAA<br />

und ANSI Embedded SQL beschrieben, werden Hostvariable definiert,<br />

indem eine normale C-Variable mit folgenden Zeilen eingeschlossen wird:<br />

EXEC SQL BEGIN DECLARE SECTION;<br />

/* Deklarationen der C-Variablen */<br />

EXEC SQL END DECLARE SECTION;<br />

Diese Hostvariable können dann an Stelle von konstanten Werten in jeder<br />

SQL-Anweisung verwendet werden. Wenn der Datenbankserver den Befehl<br />

ausführt, wird der Wert der Hostvariable benutzt. Beachten Sie, dass<br />

Hostvariable nicht an Stelle von Tabellen- oder Spaltennamen verwendet<br />

werden können: Da<strong>für</strong> ist dynamisches SQL erforderlich. Der<br />

Variablenname hat in einer SQL-Anweisung einen Doppelpunkt (:) als<br />

Präfix, um ihn von anderen Namen zu unterscheiden, die in der Anweisung<br />

erlaubt sind.<br />

Ein standardmäßiger SQL-Präprozessor durchsucht nur den C-<br />

Programmcode, der innerhalb des Deklarationsabschnitts steht. TYPEDEF-<br />

Typen und –Strukturen sind also nicht zulässig. Variable können innerhalb<br />

des DECLARE-Abschnitts initialisiert werden.<br />

♦ Das folgende Beispiel zeigt den Gebrauch von Hostvariablen <strong>für</strong> einen<br />

INSERT-Befehl. Die Variablen werden von dem Programm belegt und<br />

dann in die Datenbank eingefügt:


C-Hostvariablentypen<br />

Kapitel 6 Programmieren mit Embedded SQL<br />

EXEC SQL BEGIN DECLARE SECTION;<br />

long employee_number;<br />

char employee_name[50];<br />

char employee_initials[8];<br />

char employee_phone[15];<br />

EXEC SQL END DECLARE SECTION;<br />

/* Das Programm belegt die Variablen mit passenden<br />

Werten*/<br />

*/<br />

EXEC SQL INSERT INTO Employee<br />

VALUES (:employee_number, :employee_name,<br />

:employee_initials, :employee_phone );<br />

$ Ein größeres Beispiel finden Sie unter "Beispiel <strong>für</strong> statischen<br />

Cursor" auf Seite 193.<br />

Nur eine begrenzte Anzahl von C-Datentypen werden als Hostvariable<br />

unterstützt. Andererseits haben bestimmte Hostvariable keinen<br />

entsprechenden Datentyp in C.<br />

In der Header-Datei sqlca.h festgelegte Makros können dazu verwendet<br />

werden, Hostvariable folgenden Typs zu definieren: VARCHAR,<br />

FIXCHAR, BINARY, PACKED DECIMAL, LONG VARCHAR, LONG<br />

BINARY oder SQLDATETIME. Sie werden wie folgt benutzt:<br />

EXEC SQL BEGIN DECLARE SECTION;<br />

DECL_VARCHAR( 10 ) v_varchar;<br />

DECL_FIXCHAR( 10 ) v_fixchar;<br />

DECL_LONGVARCHAR( 32678 ) v_longvarchar;<br />

DECL_BINARY( 4000 ) v_binary;<br />

DECL_LONGBINARY( 128000 ) v_longbinary;<br />

DECL_DECIMAL( 10, 2 ) v_packed_decimal;<br />

DECL_DATETIME v_datetime;<br />

EXEC SQL END DECLARE SECTION;<br />

Der Präprozessor erkennt diese Makros innerhalb eines<br />

Deklarationsabschnitts und behandelt Variable ihrem Typ entsprechend.<br />

Die folgende Tabelle zeigt die C-Variablentypen, die als Hostvariable erlaubt<br />

sind und die entsprechenden Datentypen der Embedded SQL-Schnittstelle.<br />

201


Hostvariable benutzen<br />

202<br />

C-Datentyp Datentyp der Embedded<br />

SQL-Schnittstelle<br />

short i;<br />

short int i;<br />

unsigned short int i;<br />

long l;<br />

long int l;<br />

unsigned long int l;<br />

Beschreibung<br />

DT_SMALLINT 16-Bit-Ganzzahl mit<br />

Vorzeichen<br />

DT_INT 32-Bit-Ganzzahl mit<br />

Vorzeichen<br />

float f; DT_FLOAT 4-Byte-Gleitkomma<br />

double d; DT_DOUBLE 8-Byte-Gleitkomma<br />

DECL_DECIMAL(p,s) DT_DECIMAL(p,s) Gepackte Dezimalzahl<br />

char a; /*n=1*/<br />

DECL_FIXCHAR(n) a;<br />

DECL_FIXCHAR a[n];<br />

DT_FIXCHAR(n) Mit Leerzeichen aufgefüllte<br />

Zeichenfolge fester Länge.<br />

char a[n]; /*n>=1*/ DT_STRING(n) Mit Nullwert abgeschlossene<br />

Zeichenfolge. Die<br />

Zeichenfolge wird mit<br />

Leerzeichen aufgefüllt, wenn<br />

bei der Initialisierung der<br />

Datenbank mit Leerzeichen<br />

aufgefüllte Zeichenfolgen<br />

verwendet werden.<br />

char *a; DT_STRING(32767) Mit Nullwert abgeschlossene<br />

Zeichenfolge<br />

DECL_VARCHAR(n) a; DT_VARCHAR(n) Zeichenfolge mit variabler<br />

Länge mit 2-Byte-<br />

Längenfeld, nicht mit<br />

Leerzeichen aufgefüllt<br />

DECL_BINARY(n) a; DT_BINARY(n) Zeichenfolge mit variabler<br />

Länge mit 2-Byte-<br />

Längenfeld<br />

DECL_DATETIME a; DT_TIMESTAMP_STRUCT SQLDATETIME-Struktur<br />

DECL_LONGVARCHAR( n )<br />

a;<br />

DT_LONGVARCHAR Lange Zeichenfolgen von<br />

variabler Länge mit drei 4-<br />

Byte-Längenfeldern. Nicht<br />

mit Leerzeichen aufgefüllt<br />

oder mit Nullwert endend.<br />

DECL_LONGBINARY( n ) a; DT_LONGBINARY Lange Binärdaten von<br />

variabler Länge mit drei 4-<br />

Byte-Längenfeldern. Nicht<br />

mit Leerzeichen aufgefüllt.


Zeiger auf ein<br />

Zeichen (pointer to<br />

char)<br />

Gültigkeitsbereich<br />

von Hostvariablen<br />

Hostvariable benutzen<br />

Kapitel 6 Programmieren mit Embedded SQL<br />

Von einer Hostvariable, die als pointer to char (char *a) deklariert ist,<br />

nimmt die Datenbankschnittstelle an, dass sie 32.767 Bytes lang ist. Jede<br />

Hostvariable vom Typ pointer to char, die benutzt wird, um Informationen<br />

von der Datenbank abzurufen, muss auf einen Puffer zeigen, der groß genug<br />

ist, um jeden Wert enthalten zu können, der möglicherweise von der<br />

Datenbank zurückkommen könnte.<br />

Dies kann recht gefährlich sein, denn jemand könnte die Definition der<br />

Spalte in der Datenbank ändern, sodass sie größer wird als zu dem Zeitpunkt,<br />

als das Programm geschrieben wurde. Dies wiederum könnte zu<br />

unvorhersehbaren Speicherbelegungen und daraus resultierenden Problemen<br />

führen. Falls Sie einen 16-Bit-Compiler benutzen, könnten die erforderlichen<br />

32.767 Bytes einen Programm-Stack-Überlauf verursachen. Es ist daher<br />

vorzuziehen, ein deklariertes Array zu benutzen, auch als Parameter <strong>für</strong> eine<br />

Funktion, die einen pointer to char erwartet. So erkennt die PREPARE-<br />

Anweisung die Größe des Arrays.<br />

Die Deklaration einer Hostvariablen kann im Allgemeinen überall dort<br />

stehen, wo auch eine C-Variablendeklaration stehen könnte. Das gilt auch <strong>für</strong><br />

den Parameterdeklarationsbereich einer C-Funktion. Die dort deklarierten C-<br />

Variablen haben ihre normalen Aufgaben (sie stehen innerhalb des Blocks<br />

zur Verfügung, in dem sie definiert sind). Da aber der SQL-Präprozessor den<br />

C-Code nicht durchsucht, erkennt er keine C-Blöcke.<br />

Für den SQL-Präprozessor sind Hostvariable globale Variable: zwei<br />

Hostvariable können niemals den gleichen Namen haben.<br />

Hostvariable können unter folgenden Umständen benutzt werden:<br />

♦ In SELECT-, INSERT-, UPDATE- und DELETE-Anweisungen sind sie<br />

überall dort erlaubt, wo eine Zahlen- oder Zeichenfolgenkonstante<br />

erlaubt sind.<br />

♦ In der INTO-Klausel einer SELECT oder FETCH-Anweisung<br />

♦ Hostvariable können auch in Embedded SQL-Befehlen benutzt werden<br />

an Stelle eines Anweisungsnamens, eines Cursornamens oder eines<br />

Optionsnamens.<br />

♦ Im Fall von CONNECT, DISCONNECT und SET CONNECT kann<br />

eine Hostvariable benutzt werden an Stelle einer Benutzer-ID, eines<br />

Kennworts, eines Verbindungsnamens, einer Verbindungszeichenfolge<br />

oder eines Datenbank-Umgebungsnamens.<br />

203


Hostvariable benutzen<br />

Beispiele<br />

Indikatorvariable<br />

204<br />

♦ Im Fall von SET OPTION und GET OPTION kann eine Hostvariable<br />

benutzt werden an Stelle einer Benutzer-ID, eines Optionsnamens oder<br />

eines Optionswerts.<br />

♦ Hostvariable können nicht an Stelle eines Tabellennamens oder eines<br />

Spaltennamens in einer Anweisung benutzt werden.<br />

♦ Folgendes ist gültiges Embedded SQL:<br />

INCLUDE SQLCA;<br />

long SQLCODE;<br />

sub1() {<br />

char SQLSTATE[6];<br />

exec SQL CREATE TABLE ...<br />

}<br />

♦ Folgendes ist nicht gültiges Embedded SQL:<br />

INCLUDE SQLCA;<br />

sub1() {<br />

char SQLSTATE[6];<br />

exec SQL CREATE TABLE ...<br />

}<br />

sub2() {<br />

exec SQL DROP TABLE...<br />

// Kein SQLSTATE im Gültigkeitsbereich dieser<br />

Anweisung<br />

}<br />

♦ SQLSTATE und SQLCODE sind besonders wichtig. Der ISO/ANSI-<br />

Standard verlangt, dass sie exakt wie folgt definiert werden:<br />

long SQLCODE;<br />

char SQLSTATE[6];<br />

Indikatorvariable sind C-Variable, die zusätzliche Informationen liefern,<br />

wenn Sie Daten abrufen oder speichern. Indikatorvariable werden in<br />

folgenden Fällen benutzt:<br />

♦ NULL-Werte Damit eine Anwendung mit NULL-Werten umgehen kann.<br />

♦ Gekürzte Zeichenfolgen Damit eine Anwendung Fälle behandeln kann,<br />

in denen ein abgerufener Wert gekürzt werden muss, um in eine<br />

Hostvariable zu passen.<br />

♦ Konvertierungsfehler Für Fehlerinformationen


Kapitel 6 Programmieren mit Embedded SQL<br />

Eine Indikatorvariable ist eine Hostvariable vom Typ short int, die in einer<br />

SQL-Anweisung unmittelbar auf eine normale Hostvariable folgt. In der<br />

folgenden INSERT-Anweisung zum Beispiel ist :ind_phone eine<br />

Indikatorvariable:<br />

EXEC SQL INSERT INTO Employee<br />

VALUES (:employee_number, :employee_name,<br />

:employee_initials, :employee_phone:ind_phone );<br />

Indikatorvariable <strong>für</strong> die Behandlung von Nullwerten verwenden<br />

Indikatorvariable<br />

verwenden, um<br />

NULL einzufügen<br />

In SQL-Daten repräsentiert NULL entweder ein unbekanntes Attribut oder<br />

eine nicht anwendbare Information. NULL in SQL darf nicht verwechselt<br />

werden mit der C-Konstante gleichen Namens (NULL). Die C-Konstante<br />

NULL wird benutzt, um nicht initialisierte oder ungültige Zeiger zu<br />

repräsentieren.<br />

In der Dokumentation zum <strong>Adaptive</strong> Server <strong>Anywhere</strong> bezieht sich eine<br />

Erwähnung von NULL immer auf die Bedeutung, die es in einer SQL-<br />

Datenbank hat (wie oben definiert). Die gleichnamige C-Konstante wird<br />

dagegen als Null-Zeiger bezeichnet (Groß-/Kleinschreibung).<br />

NULL kann nicht <strong>für</strong> einen Wert stehen, der dem <strong>für</strong> die Spalte definierten<br />

Typ entspricht. Um einen NULL-Wert an die Datenbank zu übergeben oder<br />

NULL als Ergebnis von der Datenbank erhalten zu können, ist daher mehr<br />

als eine normale Hostvariable erforderlich. Indikatorvariable werden <strong>für</strong><br />

diesen Zweck eingesetzt.<br />

Eine INSERT-Anweisung könnte wie folgt eine Indikatorvariable einfügen:<br />

EXEC SQL BEGIN DECLARE SECTION;<br />

short int employee_number;<br />

char employee_name[50];<br />

char employee_initials[6];<br />

char employee_phone[15];<br />

short int ind_phone;<br />

EXEC SQL END DECLARE SECTION;<br />

/*<br />

Das Programm belegt empnum, empname,<br />

initials und homephone<br />

*/<br />

if( /* falls die Telefonnummer unbekannt ist */ ) {<br />

ind_phone = -1;<br />

} else {<br />

ind_phone = 0;<br />

}<br />

EXEC SQL INSERT INTO Employee<br />

VALUES (:employee_number, :employee_name,<br />

:employee_initials, :employee_phone:ind_phone );<br />

205


Hostvariable benutzen<br />

Indikatorvariable<br />

verwenden, um<br />

NULL abzurufen<br />

206<br />

Hat die Indikatorvariable den Wert –1, wird NULL eingefügt. Hat sie den<br />

Wert 0, wird der tatsächliche Wert von employee_phone eingefügt.<br />

Indikatorvariable werden auch benutzt, um Daten von der Datenbank<br />

abzurufen. Sie werden verwendet, um anzuzeigen, dass ein NULL-Wert<br />

abgerufen wurde (der Indikator ist negativ). Falls ein NULL-Wert von der<br />

Datenbank abgerufen wird und keine Indikatorvariable zur Verfügung steht,<br />

wird ein Fehler erzeugt (SQLE_NO_INDICATOR). Fehler werden im<br />

nächsten Abschnitt erklärt.<br />

Indikatorvariable <strong>für</strong> gekürzte Werte verwenden<br />

Indikatorvariable zeigen an, ob irgendwelche abgerufenen Werte gekürzt<br />

wurden, um in eine Hostvariable zu passen. So können Anwendungen mit<br />

dem Kürzen von Werten angemessen umgehen.<br />

Falls ein Wert beim Abrufen gekürzt wurde, wird die Indikatorvariable mit<br />

einem positiven Wert belegt. Dieser Wert gibt die Länge an, den der aus der<br />

Datenbank abgerufene Wert vor dem Kürzen hatte. Ist die Länge des<br />

gekürzten Werts größer als 32.767, hat die Indikatorvariable den Wert<br />

32.767.<br />

Indikatorwerte <strong>für</strong> Konvertierungsfehler verwenden<br />

Als Voreinstellung ist die Datenbankoption CONVERSION_ERROR auf<br />

ON gesetzt, jede fehlgeschlagene Datentypkonvertierung führt zu einem<br />

Fehler und es wird keine Zeile zurückgegeben.<br />

Sie können Indikatorvariable verwenden, um festzustellen, in welcher Spalte<br />

eine fehlgeschlagene Datentypkonvertierung auftrat. Wenn Sie die<br />

Datenbankoption CONVERSION_ERROR auf OFF setzen, erzeugt jede<br />

fehlgeschlagene Datentypkonvertierung (statt eines Fehlers) die Warnung<br />

CANNOT_CONVERT. Hat die Spalte, in der der Konvertierungsfehler<br />

auftrat, eine Indikatorvariable, wird diese Variable mit –2 belegt.<br />

Wenn Sie beim Einfügen von Daten in die Datenbank die Datenbankoption<br />

CONVERSION_ERROR auf OFF setzen, wird der Wert NULL eingefügt,<br />

falls eine fehlgeschlagene Konvertierung auftritt.<br />

Zusammenfassung: Werte <strong>für</strong> Indikatorvariable<br />

Folgende Tabelle bietet eine Zusammenfassung zum Gebrauch von<br />

Indikatorvariablen.


Indikatorwert<br />

Wert, an die<br />

Datenbank<br />

übergeben<br />

Kapitel 6 Programmieren mit Embedded SQL<br />

Wert von der Datenbank erhalten<br />

> 0 Wert der Hostvariable Der abgerufene Wert wurde gekürzt -<br />

tatsächliche Länge in der<br />

Indikatorvariable<br />

0 Wert der Hostvariable Entweder das Abrufen war erfolgreich<br />

oder CONVERSION_ERROR ist auf<br />

ON gesetzt.<br />

–1 Nullwert Ergebnis NULL<br />

–2 Nullwert Konvertierungsfehler (nur wenn<br />

CONVERSION_ERROR auf OFF<br />

gesetzt ist). SQLCODE gibt die<br />

Warnung CANNOT_CONVERT aus.<br />

< –2 Nullwert Ergebnis NULL<br />

$ Weitere Informationen über das Abrufen von long-Werten finden Sie<br />

unter "GET DATA-Anweisung [ESQL]" auf Seite 471 der Dokumentation<br />

ASA SQL-Referenzhandbuch.<br />

207


SQL-Kommunikationsbereich (SQLCA)<br />

SQL-Kommunikationsbereich (SQLCA)<br />

SQLCA-Bereich<br />

bietet Fehlercodes<br />

SQLCA-Felder<br />

208<br />

Der SQL-Kommunikationsbereich (SQL Communication Area - SQLCA)<br />

ist ein Speicherbereich, der bei jeder Datenbankanforderung benutzt wird,<br />

um Statistiken und Fehlermeldungen von der Anwendung zum<br />

Datenbankserver zu übermitteln und umgekehrt. Der SQLCA-Bereich wird<br />

als Handle <strong>für</strong> die Kommunikationsverbindung zwischen Anwendung und<br />

Datenbank benutzt. Er wird allen Datenbank-Bibliotheksfunktionen<br />

übergeben, die mit dem Datenbankserver kommunizieren müssen. Er wird<br />

implizit allen Embedded SQL-Anweisungen übergeben.<br />

Eine globale SQLCA-Variable ist in der Schnittstellenbibliothek definiert.<br />

Der Präprozessor erzeugt eine externe Referenz auf die globale SQLCA-<br />

Variable und eine externe Referenz auf einen Zeiger auf die Variable. Die<br />

externe Referenz heißt sqlca und ist vom Typ SQLCA. Der Zeiger heißt<br />

sqlcaptr. Die globale Variable selbst wird in der Importbibliothek deklariert.<br />

Der SQLCA-Bereich ist in der Header-Datei sqlca.h definiert, die im<br />

Unterverzeichnis h Ihres Installationsverzeichnisses enthalten ist.<br />

Sie benutzen den SQLCA-Bereich, um auf einen bestimmten Fehlercode zu<br />

testen. Die Felder sqlcode und sqlstate enthalten Fehlercodes, falls eine<br />

Anforderung an die Datenbank einen Fehler hervorrief (siehe unten). Einige<br />

C-Makros sind definiert, um die Felder sqlcode, sqlstate und einige weitere<br />

anzusprechen.<br />

Die SQLCA-Felder haben folgende Bedeutung:<br />

♦ sqlcaid 8-Byte Zeichenfeld, das die Zeichenfolge SQLCA enthält (zur<br />

Identifizierung der SQLCA-Struktur). Dieses Feld unterstützt die<br />

Fehlersuche, wenn Sie Speicherinhalte untersuchen.<br />

♦ sqlcabc Ganzzahl (long integer), die die Länge der SQLCA-Struktur<br />

enthält (136 Bytes)<br />

♦ sqlcode Eine Ganzzahl ("long integer"), die den Fehlercode angibt,<br />

wenn die Datenbank einen Fehler bei einer Anforderung feststellt.<br />

Definitionen <strong>für</strong> die Fehlercodes befinden sich in der Header-Datei<br />

sqlerr.h. Bei einer erfolgreichen Operation ist der Fehlercode 0 (Null),<br />

bei einer Warnung ist er positiv und bei einem Fehler ist er negativ.<br />

$ Eine vollständige Auflistung der Fehlercodes finden Sie unter<br />

"Datenbank-Fehlermeldungen" auf Seite 1 der Dokumentation ASA<br />

Fehlermeldungen.


sqlerror-Array<br />

Kapitel 6 Programmieren mit Embedded SQL<br />

♦ sqlerrml Die Länge der Daten im Feld sqlerrmc<br />

♦ sqlerrmc Kann eine oder mehrere Zeichenfolgen enthalten, die in eine<br />

Fehlermeldung einzufügen sind. Einige Fehlermeldungen enthalten eine<br />

oder mehr Platzhalter-Zeichenfolgen (%1, %2, …), die durch die<br />

Zeichenfolge in diesem Feld ersetzt werden.<br />

Wenn zum Beispiel ein Fehler Table Not Found erzeugt wird, enthält<br />

sqlerrmc den Tabellennamen, der dann an passender Stelle in die<br />

Fehlermeldung eingefügt wird.<br />

$ Eine vollständige Auflistung der Fehlermeldungen finden Sie unter<br />

"Datenbank-Fehlermeldungen" auf Seite 1 der Dokumentation ASA<br />

Fehlermeldungen.<br />

♦ sqlerrp Reserviert<br />

♦ sqlerrd Array von Ganzzahlen ("long integer")<br />

♦ sqlwarn Reserviert<br />

♦ sqlstate SQLSTATE-Statuswert. Der ANSI SQL-Standard (SQL-92)<br />

definiert einen neuen Rückgabewerttyp <strong>für</strong> SQL-Anweisungen,<br />

zusätzlich zu dem in früheren Standards definierten SQLCODE. Der<br />

Wert von SQLSTATE ist immer eine fünf Zeichen lange mit 0 (Null)<br />

abgeschlossene Zeichenfolge, aufgeteilt in eine zwei Zeichen lange<br />

Klasse (die ersten zwei Zeichen) und eine drei Zeichen lange<br />

Unterklasse. Jedes Zeichen kann eine Ziffer von 0 bis 9 sein oder ein<br />

Großbuchstabe von A bis Z.<br />

Jede Klasse oder Unterklasse, die mit 0 bis 4 oder A bis H beginnt, ist<br />

durch den SQL-Standard definiert. Andere Klassen und Unterklassen<br />

sind durch die Implementierung definiert. Hat SQLSTATE den Wert<br />

'00000', ist kein Fehler und keine Warnung aufgetreten.<br />

$ Weitere SQLSTATE-Werte finden Sie unter "Datenbank-<br />

Fehlermeldungen" auf Seite 1 der Dokumentation ASA<br />

Fehlermeldungen.<br />

Das Array sqlerror besteht aus folgenden Elementen:<br />

♦ sqlerrd[1] (SQLIOCOUNT) Die Anzahl der Eingabe/Ausgabe-Vorgänge,<br />

die erforderlich waren, um einen Befehl auszuführen.<br />

Die Datenbank beginnt diese Zählung nicht mit 0 (Null) <strong>für</strong> jeden<br />

Befehl. Ihr Programm kann diese Variable vor der Ausführung einer<br />

Befehlssequenz auf 0 (Null) setzen. Nach dem letzten Befehl zeigt der<br />

Wert der Variablen die Gesamtzahl der Eingabe/Ausgabe-Vorgänge <strong>für</strong><br />

die gesamte Befehlssequenz an.<br />

♦ sqlerrd[2] (SQLCOUNT) Der Wert dieses Felds hängt davon ab, welche<br />

Anweisung ausgeführt wurde.<br />

209


SQL-Kommunikationsbereich (SQLCA)<br />

210<br />

♦ INSERT-, UPDATE-, PUT und DELETE-Anweisungen Anzahl der<br />

Zeilen, die von der Anweisung betroffen waren<br />

Bei Cursor OPEN wird das Feld belegt entweder mit der<br />

tatsächlichen Anzahl der Zeilen im Cursor (ein Wert größer als oder<br />

gleich 0) oder mit einer Schätzung der Anzahl (ein negative Zahl,<br />

deren absoluter Wert die Schätzung ist). Es wird sich um die<br />

tatsächliche Anzahl der Zeilen handeln, wenn der Datenbankserver<br />

sie errechnen kann, ohne die Zeilen zu zählen. Die Datenbank kann<br />

auch so konfiguriert werden, dass sie immer die tatsächliche Anzahl<br />

der Zeilen liefert (mit der Option ROW_COUNT).<br />

♦ FETCH Cursor-Anweisung Das Feld SQLCOUNT wird belegt,<br />

falls eine SQLE_NOTFOUND-Warnung zurückgegeben wird. Es<br />

enthält die Anzahl der Zeilen, um die eine FETCH RELATIVEoder<br />

eine FETCH ABSOLUTE-Anweisung den Bereich der<br />

möglichen Cursorpositionen überschritten hat. (Ein Cursor kann<br />

sich auf einer Zeile, vor der ersten Zeile oder nach der letzten Zeile<br />

befinden.) Bei weiten Abrufen entspricht SQLCOUNT der Anzahl<br />

der tatsächlich abgerufenen Zeilen und ist kleiner oder gleich der<br />

Anzahl der angeforderten Zeilen. Während eines weiten Abrufs<br />

wird SQLE_NOTFOUND nicht festgelegt.<br />

$ Weitere Hinweise zu weiten Abrufen finden Sie unter "Mehr<br />

als eine Zeile auf einmal abrufen" auf Seite 218.<br />

Der Wert ist 0 (Null), falls die Zeile nicht gefunden wurde, die<br />

Position aber gültig ist, zum Beispiel wenn FETCH RELATIVE 1<br />

ausgeführt wird, und die Position ist auf der letzten Zeile eines<br />

Cursors. Der Wert ist positiv, falls das Abrufen jenseits des Cursors<br />

versucht wurde, und negativ, falls das Abrufen vor dem Anfang des<br />

Cursors versucht wurde.<br />

♦ GET DATA-Anweisung Das Feld SQLCOUNT enthält die<br />

tatsächliche Länge des Werts.<br />

♦ DESCRIBE-Anweisung In der Klausel WITH VARIABLE<br />

RESULT, die benutzt wird, um Prozeduren zu beschreiben, die<br />

mehr als ein Ergebnis haben können, wird SQLCOUNT auf einen<br />

der folgenden Werte gesetzt:<br />

♦ 0 Die Ergebnismenge kann sich ändern: der Prozeduraufruf<br />

sollte nach jeder OPEN-Anweisung neu beschrieben werden.<br />

♦ 1 Die Ergebnismenge ist unveränderlich. Eine erneute<br />

Beschreibung ist nicht erforderlich.<br />

Im Fall eines Syntaxfehlers, SQLE_SYNTAX_ERROR, enthält<br />

dieses Feld die ungefähre Position des Zeichens innerhalb der<br />

Befehlszeichenfolge, wo der Fehler erkannt wurde.


Kapitel 6 Programmieren mit Embedded SQL<br />

♦ sqlerrd[3] (SQLIOESTIMATE) Die geschätzte Anzahl der<br />

Eingabe/Ausgabe-Vorgänge <strong>für</strong> den Abschluss des Befehls. Dieses Feld<br />

wird bei einem OPEN- oder EXPLAIN-Befehl belegt.<br />

SQLCA-Verwaltung <strong>für</strong> Code mit mehreren Threads oder<br />

"reentrant"-Code<br />

Sie können Embedded SQL-Anweisungen in Code mit mehreren Threads<br />

oder reentrant-Code benutzen. Wenn Sie allerdings eine einfache<br />

Verbindung benutzen, sind Sie auf eine aktive Anforderung pro Verbindung<br />

beschränkt. In einer Applikation mit mehreren Threads sollten Sie es<br />

vermeiden, <strong>für</strong> alle Threads dieselbe Verbindung zur Datenbank benutzen,<br />

außer wenn Sie Semaphore <strong>für</strong> die Zugriffssteuerung benutzen.<br />

Sie können ohne Einschränkung <strong>für</strong> jeden Thread, der die Datenbank<br />

benutzen will, eine separate Verbindung öffnen. Der SQLCA-Bereich wird<br />

von der Laufzeitbibliothek benutzt, um zwischen den verschiedenen Thread-<br />

Kontexten zu unterscheiden. Daher braucht jeder Thread, der eine<br />

Verbindung zur Datenbank benötigt, seinen eigenen SQCLA-Bereich.<br />

Jede einzelne Datenbankverbindung ist nur von einem einzelnen SQLCA-<br />

Bereich aus zugänglich, außer bei der Abbruchanweisung, die von einem<br />

separaten Thread aus ausgegeben werden muss.<br />

$ Hinweise zur Abbruchanforderung finden Sie unter "Anforderungs-<br />

Management implementieren" auf Seite 247.<br />

Mehrere SQLCA-Bereiche benutzen<br />

v Um mehrere SQLCA-Bereiche in Ihrer Anwendung zu benutzen,<br />

gehen Sie wie folgt vor:<br />

1 Sie müssen <strong>für</strong> den SQL-Präprozessor den Befehlszeilenschalter<br />

benutzen, der reentrant-Code erzeugt (-r). Der reentrant-Code ist etwas<br />

umfangreicher und etwas langsamer, weil keine statisch initialisierten<br />

globalen Variablen benutzt werden können. Diese Auswirkungen sind<br />

allerdings minimal.<br />

2 Jeder SQLCA-Bereich, der in Ihrem Programm benutzt wird, muss mit<br />

einem Aufruf von db_init initialisiert und am Ende mit einem Aufruf<br />

von db_fini wieder freigegeben werden.<br />

211


SQL-Kommunikationsbereich (SQLCA)<br />

212<br />

Vorsicht<br />

Wird unter NetWare nicht db_fini <strong>für</strong> jedes db_init aufgerufen,<br />

kann das den Datenbankserver und den NetWare-Dateiserver zum<br />

Absturz bringen.<br />

3 Die Embedded SQL-Anweisung SET SQLCA ("SET SQLCA-<br />

Anweisung [ESQL]" auf Seite 588 der Dokumentation ASA SQL-<br />

Referenzhandbuch) wird verwendet, um den SQL-Präprozessor<br />

anzuweisen, einen anderen SQLCA-Bereich <strong>für</strong><br />

Datenbankanforderungen zu benutzen. Ein Beispiel ist die folgende<br />

Anweisung: EXEC SQL SET SQLCA 'task_data->sqlca' wird zu Beginn<br />

eines Programms oder in einer Header-Datei benutzt, um SQLCA-<br />

Referenzen so einzustellen, dass sie auf Task-spezifische Daten zeigen.<br />

Diese Anweisung erzeugt keinen Code und hat daher keinen Einfluss auf<br />

die Performance. Sie ändert den Status innerhalb des Präprozessors,<br />

sodass jede Referenz auf den SQLCA-Bereich die angegebene<br />

Zeichenfolge benutzt.<br />

$ Weitere Hinweise zum Erstellen von SQLCA-Bereichen finden Sie<br />

unter "SET SQLCA-Anweisung [ESQL]" auf Seite 588 der Dokumentation<br />

ASA SQL-Referenzhandbuch.<br />

In welchen Fällen Sie mehrere SQLCA-Bereiche benutzen<br />

Sie können die Unterstützung mehrfacher SQLCAs in jeder der unterstützten<br />

Embedded SQL-Umgebungen benutzen, sie ist jedoch nur <strong>für</strong> reentrant-Code<br />

erforderlich.<br />

Die folgende Aufstellung gibt einen Überblick über die Umgebungen, in<br />

denen mehrfache SQLCAs benutzt werden müssen:<br />

♦ Anwendungen mit mehreren Threads Falls mehr als ein Thread<br />

denselben SQLCA-Bereich benutzt, kann ein Kontextwechsel<br />

verursachen, dass zum gleichen Zeitpunkt mehr als ein Thread auf den<br />

SQLCA-Bereich zugreift. Jeder Thread braucht seinen eigenen SQLCA-<br />

Bereich. Das kann auch geschehen, wenn Sie eine DLL haben, die<br />

Embedded SQL benutzt und die von mehr als einem Thread in Ihrer<br />

Anwendung aufgerufen wird.


Kapitel 6 Programmieren mit Embedded SQL<br />

♦ Dynamische Verknüpfungsbibliotheken (DLL) und gemeinsam<br />

genutzte Bibliotheken Eine DLL hat nur ein Datensegment. Während<br />

der Datenbankserver eine Anforderung von einer Anwendung bearbeitet,<br />

könnte er die Kontrolle an eine andere Anwendung übergeben, die<br />

ebenfalls eine Anforderung an den Datenbankserver richtet. Falls Ihre<br />

DLL den globalen SQLCA-Bereich benutzt, greifen beide<br />

Anwendungen gleichzeitig darauf zu. Jede Windows-Anwendung<br />

braucht ihren eigenen SQLCA-Bereich.<br />

♦ Eine DLL mit einem Datensegment Eine DLL kann mit nur einem<br />

Datensegment erstellt werden oder mit einem Datensegment <strong>für</strong> jede<br />

Anwendung. Falls Ihre DLL nur ein Datensegment hat, dürfen Sie aus<br />

dem gleichen Grund nicht den globalen SQLCA-Bereich benutzen, aus<br />

dem eine DLL den globalen SQLCA-Bereich nicht benutzen kann. Jede<br />

Anwendung braucht ihren eigenen SQLCA-Bereich.<br />

Verbindungsverwaltung mit mehreren SQLCA-Bereichen<br />

Sie müssen nicht mehrere SQLCA-Bereiche benutzen, um Verbindungen zu<br />

mehr als einer Datenbank herzustellen oder um mehr als eine Verbindung zu<br />

einer einzelnen Datenbank zu halten.<br />

Jeder SQLCA-Bereich kann eine namenlose Verbindung haben. Jeder<br />

SQLCA-Bereich hat eine aktive oder aktuelle Verbindung (siehe "SET<br />

CONNECTION-Anweisung [Interactive SQL]" auf Seite 578 der<br />

Dokumentation ASA SQL-Referenzhandbuch). Alle Vorgänge, die sich auf<br />

eine angegebene Datenbankverbindung beziehen, müssen denselben<br />

SQLCA-Bereich benutzen, der verwendet wurde, als die Verbindung<br />

geöffnet wurde.<br />

Datensatz sperren<br />

Vorgänge, die sich auf verschiedene Verbindungen beziehen, sind den<br />

normalen Datensatz-Sperrmechanismen unterworfen und können sich<br />

gegenseitig blockieren oder möglicherweise zu einer Deadlock-Situation<br />

führen. Information über Sperrmechanismen finden Sie im Kapitel<br />

"Transaktionen und Isolationsstufen verwenden" auf Seite 99 der<br />

Dokumentation ASA SQL-Benutzerhandbuch.<br />

213


Daten abrufen<br />

Daten abrufen<br />

214<br />

In Embedded SQL werden Daten mit der Anweisung SELECT abgerufen.<br />

Dabei werden zwei Fälle unterschieden:<br />

♦ Die SELECT-Anweisung gibt mehr als eine Zeile zurück Verwenden<br />

Sie eine INTO-Klausel, damit die zurückgegebenen Werte direkt<br />

Hostvariablen zugeordnet werden.<br />

$ Hinweise dazu finden Sie unter "SELECT-Anweisungen, die<br />

höchstens eine Zeile zurückgeben" auf Seite 214.<br />

♦ Die SELECT-Anweisung kann mehrere Zeilen zurückgeben<br />

Verwenden Sie Cursor zur Verwaltung der Zeilen in der Ergebnismenge.<br />

$ Weitere Hinweise finden Sie unter "Cursor in Embedded SQL<br />

verwenden" auf Seite 215.<br />

$ LONG VARCHAR- und LONG BINARY-Datentypen werden<br />

unterschiedlich zu anderen Datentypen behandelt. Weitere Hinweise finden<br />

Sie unter "LONG-Daten abrufen" auf Seite 238.<br />

SELECT-Anweisungen, die höchstens eine Zeile zurückgeben<br />

Beispiel<br />

Eine einzeilige Abfrage fragt höchstens eine Zeile von der Datenbank ab. In<br />

einer SELECT-Anweisung <strong>für</strong> eine einzeilige Abfrage befindet sich eine<br />

INTO-Klausel nach der Auswahlliste und vor der FROM-Klausel. Die<br />

INTO-Klausel enthält eine Liste der Hostvariablen, die die Werte der<br />

Auswahllisten-Elemente übernehmen sollen. Die Anzahl der Hostvariablen<br />

muss mit der Anzahl der Auswahllisten-Elemente übereinstimmen. Die<br />

Hostvariable können von Indikatorvariablen gefolgt sein, um NULL-<br />

Ergebnisse anzuzeigen.<br />

Sobald die SELECT-Anweisung ausgeführt wird, ruft der Datenbankserver<br />

die Ergebnisse ab und schreibt sie in die Hostvariable. Falls die<br />

Abfrageergebnisse mehr als eine Zeile enthalten, gibt der Datenbankserver<br />

einen Fehler zurück.<br />

Falls das Abfrageergebnis ist, dass keine Zeile ausgewählt ist, wird eine Row<br />

Not Found-Warnung zurückgeben. Fehler und Warnungen werden in der<br />

SQLCA-Struktur zurückgegeben, wie beschrieben in "SQL-<br />

Kommunikationsbereich (SQLCA)" auf Seite 208.<br />

Folgendes Code-Fragment gibt zum Beispiel 1 zurück, falls eine Zeile der<br />

Tabelle "employee" erfolgreich abgerufen wird, 0, falls die Zeile nicht<br />

existiert, und –1, falls ein Fehler auftritt.<br />

EXEC SQL BEGIN DECLARE SECTION;


Cursor in Embedded SQL verwenden<br />

Kapitel 6 Programmieren mit Embedded SQL<br />

long emp_id;<br />

char name[41];<br />

char sex;<br />

char birthdate[15];<br />

short int ind_birthdate;<br />

EXEC SQL END DECLARE SECTION;<br />

. . .<br />

int find_employee( long employee )<br />

{<br />

emp_id = employee;<br />

EXEC SQL SELECT emp_fname ||<br />

’ ’ || emp_lname, sex, birth_date<br />

INTO :name, :sex,<br />

:birthdate:ind_birthdate<br />

FROM "DBA".employee<br />

WHERE emp_id = :emp_id;<br />

if( SQLCODE == SQLE_NOTFOUND ) {<br />

return( 0 ); /* ’employee’ wurde nicht gefunden<br />

*/<br />

} else if( SQLCODE < 0 ) {<br />

return( -1 ); /* Fehler */<br />

} else {<br />

return( 1 ); /* gefunden */<br />

}<br />

}<br />

Ein Cursor wird benutzt, um Zeilen aus einer Abfrage abzurufen, die<br />

mehrere Zeilen in Ihrer Ergebnismenge hat. Ein Cursor ist ein Handle oder<br />

ein Name (identifier) <strong>für</strong> die SQL-Abfrage und eine Position innerhalb der<br />

Ergebnismenge.<br />

$ Eine Einführung zu Cursorn finden Sie unter "Mit Cursorn arbeiten"<br />

auf Seite 20.<br />

v So verwalten Sie einen Cursor in Embedded SQL:<br />

1 Deklarieren Sie einen Cursor <strong>für</strong> eine bestimmte SELECT-Anweisung<br />

mit der DECLARE-Anweisung.<br />

2 Öffnen Sie den Cursor mit der Anweisung OPEN.<br />

3 Rufen Sie die Ergebnisse Zeile <strong>für</strong> Zeile aus dem Cursor ab mit der<br />

FETCH-Anweisung.<br />

4 Wiederholen Sie das Abrufen der Zeilen, bis die Warnung Row Not<br />

Found zurückgegeben wird.<br />

215


Daten abrufen<br />

Cursor<br />

positionieren<br />

216<br />

Fehler und Warnungen werden in der SQLCA-Struktur zurückgegeben,<br />

wie in "SQL-Kommunikationsbereich (SQLCA)" auf Seite 208<br />

beschrieben.<br />

5 Schließen Sie den Cursor mit der CLOSE-Anweisung.<br />

Als Voreinstellung werden Cursor automatisch am Ende der Transaktion<br />

geschlossen (bei COMMIT oder ROLLBACK). Cursor, die mit einer WITH<br />

HOLD-Klausel geöffnet werden, bleiben <strong>für</strong> folgende Transaktionen<br />

geöffnet, bis sie explizit geschlossen werden.<br />

Das folgende einfache Beispiel zeigt den Gebrauch von Cursorn:<br />

void print_employees( void )<br />

{<br />

EXEC SQL BEGIN DECLARE SECTION;<br />

char name[50];<br />

char sex;<br />

char birthdate[15];<br />

short int ind_birthdate;<br />

EXEC SQL END DECLARE SECTION;<br />

EXEC SQL DECLARE C1 CURSOR FOR<br />

SELECT emp_fname || ’ ’ || emp_lname,<br />

sex, birth_date<br />

FROM "DBA".employee;<br />

EXEC SQL OPEN C1;<br />

for( ;; ) {<br />

EXEC SQL FETCH C1 INTO :name, :sex,<br />

:birthdate:ind_birthdate;<br />

if( SQLCODE == SQLE_NOTFOUND ) {<br />

break;<br />

} else if( SQLCODE < 0 ) {<br />

break;<br />

}<br />

if( ind_birthdate < 0 ) {<br />

strcpy( birthdate, "UNKNOWN" );<br />

}<br />

printf( "Name: %s Sex: %c Birthdate:<br />

%s.n",name, sex, birthdate );<br />

}<br />

EXEC SQL CLOSE C1;<br />

}<br />

$ Vollständige Beispiele <strong>für</strong> Cursor finden Sie unter "Beispiel <strong>für</strong><br />

statischen Cursor" auf Seite 193 und "Beispiel <strong>für</strong> dynamischen Cursor" auf<br />

Seite 193.<br />

Ein Cursor wird an einer von drei Stellen positioniert:<br />

♦ Auf einer Zeile<br />

♦ Vor der ersten Zeile


Cursorpositionierungsprobleme<br />

♦ Nach der letzten Zeile<br />

Kapitel 6 Programmieren mit Embedded SQL<br />

Wird ein Cursor geöffnet, ist er vor der ersten Zeile positioniert. Die<br />

Cursorposition kann mit dem FETCH-Befehl verschoben werden (siehe<br />

"FETCH-Anweisung [ESQL] [GP]" auf Seite 458 der Dokumentation ASA<br />

SQL-Referenzhandbuch ). Er kann absolut positioniert werden, entweder<br />

bezogen auf den Anfang oder auf das Ende des Abfrageergebnisses. Er kann<br />

auch relativ zur aktuellen Cursorposition verschoben werden.<br />

Mit speziellen positioned-Versionen der Anweisungen UPDATE und<br />

DELETE können Sie die Zeile an der aktuellen Cursor-Position aktualisieren<br />

oder löschen. Ist der Cursor vor der ersten Zeile oder nach der letzten Zeile<br />

positioniert, wird der Fehler No Current Row of Cursor zurückgeben.<br />

Die Anweisung PUT kann verwendet werden, um eine Zeile in einen Cursor<br />

einzufügen.<br />

Einfügungen und einige Aktualisierungen zu DYNAMIC SCROLL-Cursorn<br />

können Probleme bei der Cursorpositionierung verursachen. Der<br />

Datenbankserver platziert eingefügte Zeilen an unvorhersehbaren Positionen<br />

innerhalb eines Cursors, falls die SELECT-Anweisung keine ORDER BY-<br />

Klausel hat. In einigen Fällen erscheint die eingefügte Zeile überhaupt nicht,<br />

bis der Cursor geschlossen und wieder geöffnet wurde.<br />

217


Daten abrufen<br />

218<br />

Bei <strong>Adaptive</strong> Server <strong>Anywhere</strong> tritt dies auf, wenn zum Öffnen eines<br />

Cursors eine temporäre Tabelle erstellt werden musste.<br />

$ Eine Beschreibung finden Sie unter "Arbeitstabellen in der<br />

Abfrageverarbeitung verwenden" auf Seite 178 der Dokumentation ASA<br />

SQL-Benutzerhandbuch.<br />

Die UPDATE-Anweisung kann bewirken, dass sich eine Zeile im Cursor<br />

verschiebt. Das passiert, wenn der Cursor eine ORDER BY-Klausel hat, die<br />

einen vorhandenen Index benutzt (es wird keine temporäre Tabelle erstellt).<br />

Mehr als eine Zeile auf einmal abrufen<br />

Beispiel<br />

Die FETCH-Anweisung kann so modifiziert werden, dass sie mehr als eine<br />

Zeile auf einmal abruft. Das kann die Performance verbessern. Man nennt<br />

diese Methode mehrzeiliges Abrufen (wide fetch) oder auch Array-<br />

Abrufen (array fetch).<br />

$ Der <strong>Adaptive</strong> Server <strong>Anywhere</strong> unterstützt auch mehrzeiliges Speichern<br />

(wide puts) und mehrzeiliges Einfügen (wide inserts). Hinweise dazu finden<br />

Sie unter "PUT-Anweisung [ESQL]" auf Seite 538 der Dokumentation ASA<br />

SQL-Referenzhandbuch und "EXECUTE-Anweisung [ESQL]" auf Seite 449<br />

der Dokumentation ASA SQL-Referenzhandbuch.<br />

Um mehrzeiliges Abrufen (wide fetches) in Embedded SQL zu verwenden,<br />

fügen Sie die Abrufanweisung wie folgt in Ihren Code ein:<br />

EXEC SQL FETCH . . . ARRAY nnn<br />

Dabei ist ARRAY nnn das letzte Element der FETCH-Anweisung. Die<br />

Abrufanzahl nnn kann eine Hostvariable sein. Die Anzahl der Variablen im<br />

SQLDA-Bereich muss das Produkt aus nnn multipliziert mit der Anzahl der<br />

Spalten pro Zeile sein. Die erste Zeile wird in die SQLDA-Variablen von 0<br />

bis (Anzahl der Spalten pro Zeile)-1 geschrieben, und so fort.<br />

Jede Spalte muss in jeder Zeile des SQLDA-Bereichs vom selben Typ sein,<br />

sonst wird der Fehler SQLDA_INCONSISTENT ausgegeben.<br />

Der Server gibt in SQLCOUNT die Anzahl der Datensätze zurück, die<br />

abgerufen wurden. Diese Anzahl ist immer größer als 0 (Null), außer wenn<br />

ein Fehler oder eine Warnung ausgegeben wird. Bei einem mehrzeiligen<br />

Abruf gibt ein SQLCOUNT von 1 ohne Fehlerzustand an, dass eine gültige<br />

Zeile abgerufen wurde.<br />

Der folgende Beispielcode zeigt den Gebrauch von mehrzeiligen Abrufen<br />

(wide fetches). Sie können diesen Code auch in<br />

samples\ASA\esqlwidefetch\widefetch.sqc in Ihrem SQL <strong>Anywhere</strong>-<br />

Verzeichnis finden.


#include <br />

#include <br />

#include <br />

#include "sqldef.h"<br />

EXEC SQL INCLUDE SQLCA;<br />

Kapitel 6 Programmieren mit Embedded SQL<br />

EXEC SQL WHENEVER SQLERROR { PrintSQLError();<br />

goto err; };<br />

static void PrintSQLError()<br />

/*************************/<br />

{<br />

char buffer[200];<br />

}<br />

printf( "SQL error %d -- %s\n",<br />

SQLCODE,<br />

sqlerror_message( &sqlca,<br />

buffer,<br />

sizeof( buffer ) ) );<br />

static SQLDA * PrepareSQLDA(<br />

a_sql_statement_number stat0,<br />

unsigned width,<br />

unsigned *cols_per_row )<br />

/*********************************************/<br />

/* Einen SQLDA-Bereich <strong>für</strong> Abrufe von der von<br />

"stat0" definierten Anweisung zuordnen. "width"-<br />

Zeilen werden bei jeder FETCH-Anforderung abgerufen.<br />

Die Anzahl der Spalten wird "cols_per_row"<br />

zugeordnet. */<br />

{<br />

int num_cols;<br />

unsigned row, col, offset;<br />

SQLDA * sqlda;<br />

EXEC SQL BEGIN DECLARE SECTION;<br />

a_sql_statement_number stat;<br />

EXEC SQL END DECLARE SECTION;<br />

stat = stat0;<br />

sqlda = alloc_sqlda( 100 );<br />

if( sqlda == NULL ) return( NULL );<br />

EXEC SQL DESCRIBE :stat INTO sqlda;<br />

*cols_per_row = num_cols = sqlda->sqld;<br />

if( num_cols * width > sqlda->sqln ) {<br />

free_sqlda( sqlda );<br />

sqlda = alloc_sqlda( num_cols * width );<br />

if( sqlda == NULL ) return( NULL );<br />

EXEC SQL DESCRIBE :stat INTO sqlda;<br />

}<br />

// Erste Zeile in SQLDA mit describe in<br />

// folgende (weite) Zeilen kopieren<br />

219


Daten abrufen<br />

220<br />

);<br />

sqlda->sqld = num_cols * width;<br />

offset = num_cols;<br />

for( row = 1; row < width; row++ ) {<br />

for( col = 0;<br />

col < num_cols;<br />

col++, offset++ ) {<br />

sqlda->sqlvar[offset].sqltype =<br />

sqlda->sqlvar[col].sqltype;<br />

sqlda->sqlvar[offset].sqllen =<br />

sqlda->sqlvar[col].sqllen;<br />

// optional: beschriebenen Spaltennamen kopieren<br />

memcpy( &sqlda->sqlvar[offset].sqlname,<br />

&sqlda->sqlvar[col].sqlname,<br />

sizeof( sqlda->sqlvar[0].sqlname )<br />

}<br />

}<br />

fill_s_sqlda( sqlda, 40 );<br />

return( sqlda );<br />

err:<br />

return( NULL );<br />

}<br />

static void PrintFetchedRows( SQLDA * sqlda,<br />

unsigned cols_per_row )<br />

/******************************************/<br />

/* Bereits durch weite Abrufe erhaltene Zeilen in SQLDA<br />

ausgeben */<br />

{<br />

long rows_fetched;<br />

int row, col, offset;<br />

}<br />

if( SQLCOUNT == 0 ) {<br />

rows_fetched = 1;<br />

} else {<br />

rows_fetched = SQLCOUNT;<br />

}<br />

printf( "Abgerufene %d Zeilen:\n", rows_fetched );<br />

for( row = 0; row < rows_fetched; row++ ) {<br />

for( col = 0; col < cols_per_row; col++ ) {<br />

offset = row * cols_per_row + col;<br />

printf( " \"%s\"",<br />

(char *)sqlda->sqlvar[offset]<br />

.sqldata );<br />

}<br />

printf( "\n" );<br />

}<br />

static int DoQuery( char * query_str0,<br />

unsigned fetch_width0 )


Kapitel 6 Programmieren mit Embedded SQL<br />

/*****************************************/<br />

/* Wide Fetch "query_str0"-Auswahlanweisung<br />

* mit der Weite von "fetch_width0" Zeilen" */<br />

{<br />

SQLDA * sqlda;<br />

unsigned cols_per_row;<br />

EXEC SQL BEGIN DECLARE SECTION;<br />

a_sql_statement_number stat;<br />

char * query_str;<br />

unsigned fetch_width;<br />

EXEC SQL END DECLARE SECTION;<br />

}<br />

query_str = query_str0;<br />

fetch_width = fetch_width0;<br />

EXEC SQL PREPARE :stat FROM :query_str;<br />

EXEC SQL DECLARE QCURSOR CURSOR FOR :stat<br />

FOR READ ONLY;<br />

EXEC SQL OPEN QCURSOR;<br />

sqlda = PrepareSQLDA( stat,<br />

fetch_width,<br />

&cols_per_row );<br />

if( sqlda == NULL ) {<br />

printf( "Fehler beim Zuweisen von SQLDA\n" );<br />

return( SQLE_NO_MEMORY );<br />

for( ;; ) {<br />

EXEC SQL FETCH QCURSOR INTO DESCRIPTOR sqlda<br />

ARRAY :fetch_width;<br />

if( SQLCODE != SQLE_NOERROR ) break;<br />

PrintFetchedRows( sqlda, cols_per_row );<br />

}<br />

EXEC SQL CLOSE QCURSOR;<br />

EXEC SQL DROP STATEMENT :stat;<br />

free_filled_sqlda( sqlda );<br />

err:<br />

return( SQLCODE );<br />

}<br />

void main( int argc, char *argv[] )<br />

/*********************************/<br />

/* Optionales erstes Argument ist ’select’-Anweisung<br />

* optionales zweites Argument ist ’Fetch’-Weite */<br />

{<br />

char *query_str =<br />

"select emp_fname, emp_lname from employee";<br />

unsigned fetch_width = 10;<br />

if( argc > 1 ) {<br />

query_str = argv[1];<br />

if( argc > 2 ) {<br />

fetch_width = atoi( argv[2] );<br />

221


Daten abrufen<br />

Hinweise zur<br />

Verwendung von<br />

mehrzeiligen<br />

Abrufen (wide<br />

fetches)<br />

222<br />

if( fetch_width < 2 ) {<br />

fetch_width = 2;<br />

}<br />

}<br />

}<br />

db_init( &sqlca );<br />

EXEC SQL CONNECT "dba" IDENTIFIED BY "sql";<br />

DoQuery( query_str, fetch_width );<br />

EXEC SQL DISCONNECT;<br />

err:<br />

db_fini( &sqlca );<br />

}<br />

♦ Die Funktion PrepareSQLDA weist den SQLDA-Bereich mit Hilfe der<br />

Funktion alloc_sqlda einem Speicherbereich zu. So wird Platz <strong>für</strong><br />

Indikatorvariable ermöglicht, anstatt die Funktion alloc_sqlda_noind zu<br />

verwenden.<br />

♦ Falls weniger als die angeforderte Anzahl von Zeilen, jedoch nicht Null,<br />

abgerufen wurden (zum Beispiel am Ende des Cursors), wird <strong>für</strong> die<br />

nicht abgerufenen SQLDA-Elemente jeweils NULL zurückgegeben,<br />

indem der entsprechende Indikatorwert gesetzt wird. Falls keine<br />

Indikatorvariable vorhanden ist, wird ein Fehler erzeugt<br />

(SQLE_NO_INDICATOR: keine Indikatorvariable <strong>für</strong> ein NULL-<br />

Ergebnis).<br />

♦ Falls eine Zeile zurückgegeben wird, die aktualisiert wurde, und die eine<br />

Warnung SQLE_ROW_UPDATED_WARNING hervorgerufen hat,<br />

wird der Abruf in der Zeile angehalten, die die Warnung verursacht hat.<br />

Die Werte aller bis zu diesem Zeitpunkt abgearbeiteten Zeilen werden<br />

zurückgegeben (einschließlich der Zeile, die die Warnung verursacht<br />

hat). SQLCOUNT enthält die Anzahl der Zeilen, die abgerufen wurden,<br />

einschließlich der Zeile, die die Warnung verursacht hat. Alle<br />

verbleibenden SQLDA-Elemente werden mit NULL gekennzeichnet.<br />

♦ Falls eine Zeile, die abgerufen werden soll, gelöscht oder gesperrt wurde<br />

und so einen Fehler hervorruft (SQLE_NO_CURRENT_ROW oder<br />

SQLE_LOCKED), enthält SQLCOUNT die Anzahl der Zeilen, die vor<br />

dem Fehler gelesen wurden. Dies schließt nicht die Zeile ein, die den<br />

Fehler verursachte. Der SQLDA-Bereich enthält keine Werte <strong>für</strong> die<br />

Zeilen, denn bei Fehlern werden keine SQLDA-Werte zurückgegeben.<br />

Der Wert von SQLCOUNT kann verwendet werden, um den Cursor neu<br />

zu positionieren und, falls nötig, um die Zeilen zu lesen.


Statische und dynamische SQL<br />

Statische SQL-Anweisungen<br />

Dynamische SQL-Anweisungen<br />

Kapitel 6 Programmieren mit Embedded SQL<br />

Es gibt zwei Möglichkeiten, SQL-Anweisungen in ein C-Programm<br />

einzubetten:<br />

♦ Statische Anweisungen<br />

♦ Dynamische Anweisungen<br />

Bis hier haben wir statische SQL erklärt. Dieser Abschnitt vergleicht<br />

statische und dynamische SQL.<br />

Alle Standard-SQL-Anweisungen zur Datenmanipulation und<br />

Datendefinition können in ein C-Programm eingebettet werden, indem man<br />

sie mit dem Präfix EXEC SQL versieht und das Kommando mit einem<br />

Semikolon (;) abschliesst. Diese Anweisungen werden als statische<br />

Anweisungen bezeichnet.<br />

Statische Anweisungen können Referenzen auf Hostvariable enthalten, wie<br />

in "Hostvariable benutzen" auf Seite 200 beschrieben. Alle Beispiele bis hier<br />

haben statische Embedded SQL-Anweisungen benutzt.<br />

Hostvariable können nur an Stelle von Zeichenfolgen- und numerischen<br />

Konstanten benutzt werden. Sie können nicht verwendet werden, um<br />

Spalten- oder Tabellennamen zu ersetzen; <strong>für</strong> diese Vorgänge sind<br />

dynamische Anweisungen erforderlich.<br />

In C werden Zeichenfolgen in Zeichen-Arrays gespeichert. Dynamische<br />

Anweisungen werden in C-Zeichenfolgen konstruiert. Diese dynamischen<br />

Anweisungen können dann mit der PREPARE-Anweisung und der<br />

EXECUTE-Anweisung ausgeführt werden. Solche SQL-Anweisungen<br />

können Hostvariable nicht in der gleichen Weise ansprechen wie statische<br />

Anweisungen, denn auf C-Variable kann nicht über den Namen zugegriffen<br />

werden, solange das C-Programm ausgeführt wird.<br />

223


Statische und dynamische SQL<br />

Beispiel<br />

224<br />

Um Informationen zwischen dynamischen SQL-Anweisungen und C-<br />

Variablen auszutauschen, wird eine Datenstruktur namens SQL-<br />

Deskriptorbereich (SQL Descriptor Area - SQLDA) verwendet. Diese<br />

Struktur wird vom SQL-Präprozessor erzeugt, wenn Sie beim EXECUTE-<br />

Befehl in der USING-Klausel eine Liste von Hostvariablen spezifizieren.<br />

Jeder Variablen entspricht jeweils ein Platzhalter in der vorbereiteten<br />

Anweisung, zugeordnet über die Position.<br />

$ Informationen zum SQLDA-Bereich finden Sie unter "Der SQL-<br />

Deskriptor-Bereich (SQLDA)" auf Seite 228.<br />

Ein Platzhalter wird in die Anweisung eingefügt, um anzuzeigen, wo auf<br />

Hostvariable zugegriffen wird. Ein Platzhalter ist entweder ein Fragezeichen<br />

(?) oder eine Referenz auf eine Hostvariable wie in statischen Anweisungen<br />

(ein Hostvariablen-Name mit einem vorangestellten Doppelpunkt). Im<br />

letzteren Fall dient der Name der Hostvariable, der im Text der Anweisung<br />

benutzt wird, nur als Platzhalter <strong>für</strong> eine Referenz auf den SQL-<br />

Deskriptorbereich.<br />

Eine Hostvariable, mit der Informationen an die Datenbank übergeben<br />

werden, wird eine Bindevariable genannt.<br />

Zum Beispiel:<br />

EXEC SQL BEGIN DECLARE SECTION;<br />

char comm[200];<br />

char address[30];<br />

char city[20];<br />

short int cityind;<br />

long empnum;<br />

EXEC SQL END DECLARE SECTION;<br />

. . .<br />

sprintf( comm, "update %s set address = :?,<br />

city = :?"<br />

" where employee_number = :?",<br />

tablename );<br />

EXEC SQL PREPARE S1 FROM :comm;<br />

EXEC SQL EXECUTE S1 USING :address, :city:cityind,<br />

:empnum;<br />

Um diese Methode zu benutzen, muss der <strong>Programmierer</strong> wissen, wie viele<br />

Hostvariable in der Anweisung vorkommen. Normalerweise ist das nicht der<br />

Fall. Daher können Sie Ihre eigene SQLDA-Struktur aufsetzen und diesen<br />

SQLDA-Bereich in der USING-Klausel des EXECUTE-Befehls angeben.<br />

Die Anweisung DESCRIBE BIND VARIABLES gibt die Namen der<br />

Hostvariablen zu den Bindevariablen zurück, die in einem Prepared-<br />

Statement gefunden wurden. Dies erleichtert es dem C-Programm, die<br />

Hostvariablen zu verwalten. Im Folgenden finden Sie die allgemeine<br />

Methode:


SQLDA-Inhalt<br />

Indikatorvariable<br />

und NULL<br />

Kapitel 6 Programmieren mit Embedded SQL<br />

EXEC SQL BEGIN DECLARE SECTION;<br />

char comm[200];<br />

EXEC SQL END DECLARE SECTION;<br />

. . .<br />

sprintf( comm, "update %s set address = :address,<br />

city = :city"<br />

" where employee_number = :empnum",<br />

tablename );<br />

EXEC SQL PREPARE S1 FROM :comm;<br />

/* Nehmen Sie an, dass es nicht mehr als 10 Hostvariable<br />

gibt. Siehe nächstes Beispiel, falls Sie<br />

keine Grenze festlegen können */<br />

sqlda = alloc_sqlda( 10 );<br />

EXEC SQL DESCRIBE BIND VARIABLES FOR S1 USING DESCRIPTOR<br />

sqlda;<br />

/* sqlda->sqld sagt Ihnen, wie viele Hostvariable<br />

gefunden wurden. */<br />

/* SQLDA_VARIABLE-Felder mit Werten belegen,<br />

die auf den name-Feldern in sqlda basieren.<br />

. . .<br />

EXEC SQL EXECUTE S1 USING DESCRIPTOR sqlda;<br />

free_sqlda( sqlda );<br />

Der SQLDA-Bereich besteht aus einem Array von Variablendeskriptoren.<br />

Jeder Deskriptor beschreibt die Attribute der entsprechenden Variablen des<br />

C-Programms, oder die Stelle, an der die Datenbank Daten speichert oder<br />

von der sie Daten abruft:<br />

♦ den Datentyp<br />

♦ die Länge, falls type eine Zeichenfolge ist<br />

♦ Gesamtstellen und Dezimalstellen, falls type ein nummerischer<br />

Datentyp ist<br />

♦ Speicheradresse<br />

♦ Indikatorvariable<br />

$ Eine vollständige Beschreibung der SQLDA-Struktur finden Sie unter<br />

"Der SQL-Deskriptor-Bereich (SQLDA)" auf Seite 228<br />

Die Indikatorvariable wird verwendet, um einen NULL-Wert an die<br />

Datenbank zu übergeben, oder um einen NULL-Wert von der Datenbank<br />

abzurufen. Die Indikatorvariable wird auch vom Datenbankserver verwendet,<br />

um anzuzeigen, unter welchen Bedingungen Werte während einer<br />

Datenbankoperation gekürzt wurden. Die Indikatorvariable wird mit einem<br />

positiven Wert besetzt, wenn nicht genug Platz zur Verfügung stand, um<br />

einen Wert von der Datenbank zu erhalten.<br />

$ Weitere Hinweise finden Sie unter "Indikatorvariable" auf Seite 204.<br />

225


Statische und dynamische SQL<br />

Die dynamische SELECT-Anweisung<br />

226<br />

Eine SELECT-Anweisung, die nur eine einzige Zeile zurückgibt, kann<br />

dynamisch vorbereitet werden, gefolgt von einer EXECUTE-Anweisung mit<br />

einer INTO-Klausel, um das einzeilige Ergebnis abzurufen. SELECT-<br />

Anweisungen, die mehrere Zeilen zurückgeben, werden dagegen mit Hilfe<br />

von dynamischen Cursorn verwaltet.<br />

Mit dynamischen Cursorn werden Ergebnisse in eine Hostvariablen-Liste<br />

geschrieben, oder in einen SQLDA-Bereich, der mit der FETCH-Anweisung<br />

angegeben wird (FETCH INTO und FETCH USING DESCRIPTOR). Da<br />

die Anzahl der Elemente in der Auswahlliste dem C-<strong>Programmierer</strong><br />

normalerweise unbekannt ist, wird in der Regel der SQLDA-Bereich benutzt.<br />

Die Anweisung DESCRIBE SELECT LIST richtet einen SQLDA-Bereich<br />

ein mit Typen <strong>für</strong> die Elemente der Auswahlliste. Der Platzbedarf <strong>für</strong> die<br />

Werte wird dann mit der Funktion fill_sqlda() zugewiesen, die Information<br />

wird mit der Anweisung FETCH USING DESCRIPTOR abgerufen.<br />

Ein typisches Szenario sieht wie folgt aus:<br />

EXEC SQL BEGIN DECLARE SECTION;<br />

char comm[200];<br />

EXEC SQL END DECLARE SECTION;<br />

int actual_size;<br />

SQLDA * sqlda;<br />

. . .<br />

sprintf( comm, "select * from %s", table_name );<br />

EXEC SQL PREPARE S1 FROM :comm;<br />

/* Anfaengliche Schaetzung von 10 Spalten im Ergebnis.<br />

Falls es<br />

falsch ist, wird es gleich nach dem ersten<br />

DESCRIBE korrigiert, indem sqlda neu zugewiesen und<br />

DESCRIBE erneut ausgeführt wird. */<br />

sqlda = alloc_sqlda( 10 );<br />

EXEC SQL DESCRIBE SELECT LIST FOR S1 USING DESCRIPTOR<br />

sqlda;<br />

if( sqlda->sqld > sqlda->sqln ){<br />

actual_size = sqlda->sqld;<br />

free_sqlda( sqlda );<br />

sqlda = alloc_sqlda( actual_size );<br />

EXEC SQL DESCRIBE SELECT LIST FOR S1<br />

USING DESCRIPTOR sqlda;<br />

}<br />

fill_sqlda( sqlda );<br />

EXEC SQL DECLARE C1 CURSOR FOR S1;<br />

EXEC SQL OPEN C1;<br />

EXEC SQL WHENEVER NOTFOUND {break};<br />

for( ;; ){<br />

EXEC SQL FETCH C1 USING DESCRIPTOR sqlda;<br />

/* Daten verarbeiten */


}<br />

EXEC SQL CLOSE C1;<br />

EXEC SQL DROP STATEMENT S1;<br />

Kapitel 6 Programmieren mit Embedded SQL<br />

Beenden Sie Anweisungen (drop), wenn sie nicht mehr gebraucht werden.<br />

So stellen Sie sicher, dass Anweisungen beendet werden, damit nicht<br />

unnötigerweise Ressourcen gebunden bleiben.<br />

$ Ein vollständiges Beispiel <strong>für</strong> den Gebrauch von Cursorn <strong>für</strong> eine<br />

dynamische Anweisung finden Sie unter "Beispiel <strong>für</strong> dynamischen Cursor"<br />

auf Seite 193.<br />

$ Detaillierte Informationen zu den oben erwähnten Funktionen finden<br />

Sie unter "Referenz der Bibliotheksfunktion" auf Seite 253.<br />

227


Der SQL-Deskriptor-Bereich (SQLDA)<br />

Der SQL-Deskriptor-Bereich (SQLDA)<br />

Die SQLDA-Header-Datei<br />

228<br />

Der SQLDA-Bereich (SQL Descriptor Area) ist eine Schnittstellenstruktur,<br />

die <strong>für</strong> dynamische SQL-Anweisungen verwendet wird. Die Struktur tauscht<br />

Informationen über Hostvariable und Ergebnisse der SELECT-Anweisung<br />

mit der Datenbank aus. Der SQLDA-Bereich ist in der Header-Datei sqlda.h<br />

definiert.<br />

$ In der Datenbank-Schnittstellenbibliothek oder DLL gibt es<br />

Funktionen, die Sie zur Verwaltung der SQLDA-Bereiche verwenden<br />

können. Die Beschreibung dieser Funktionen finden Sie unter "Referenz der<br />

Bibliotheksfunktion" auf Seite 253.<br />

Wenn Hostvariable mit statischen SQL-Anweisungen verwendet werden,<br />

erzeugt der Präprozessor einen SQDLA-Bereich <strong>für</strong> diese Hostvariable. Was<br />

dann mit der Datenbank ausgetauscht wird, ist tatsächlich dieser SQLDA-<br />

Bereich.<br />

Der Inhalt von sqlda.h ist der folgende:<br />

#ifndef _SQLDA_H_INCLUDED<br />

#define _SQLDA_H_INCLUDED<br />

#define II_SQLDA<br />

#include "sqlca.h"<br />

#if defined( _SQL_PACK_STRUCTURES )<br />

#include "pshpk1.h"<br />

#endif<br />

#define SQL_MAX_NAME_LEN 30<br />

#define _sqldafar _sqlfar<br />

typedef short int a_SQL_type;<br />

struct sqlname {<br />

short int length; /* Länge der Char-Daten */<br />

char data[ SQL_MAX_NAME_LEN ]; /* Daten */<br />

};<br />

struct sqlvar { /* Array der Deskriptoren der Variablen */<br />

short int sqltype; /* Typ der Hostvariablen */<br />

short int sqllen; /* Länge der Hostvariablen */<br />

void _sqldafar *sqldata; /* Adresse der Variablen */<br />

short int _sqldafar *sqlind; /* Indikatorvariablen-Zeiger */<br />

struct sqlname sqlname;<br />

};


SQLDA-Felder<br />

Kapitel 6 Programmieren mit Embedded SQL<br />

struct sqlda{<br />

unsigned char sqldaid[8]; /* Eye-catcher "SQLDA"*/<br />

a_SQL_int32 sqldabc; /* Länge der sqlda-Struktur*/<br />

short int sqln; /* Deskriptorgröße in Anzahl der Einträge */<br />

short int sqld; /* Anzahl der von DESCRIBE gefundenen Variablen*/<br />

struct sqlvar sqlvar[1]; /* Array der Variablendeskriptoren */<br />

};<br />

#define SCALE(sqllen) ((sqllen)/256)<br />

#define PRECISION(sqllen) ((sqllen)&0xff)<br />

#define SET_PRECISION_SCALE(sqllen,precision,scale) \<br />

sqllen = (scale)*256 + (precision)<br />

#define DECIMALSTORAGE(sqllen) (PRECISION(sqllen)/2 + 1)<br />

typedef struct sqlda SQLDA;<br />

typedef struct sqlvar SQLVAR, SQLDA_VARIABLE;<br />

typedef struct sqlname SQLNAME, SQLDA_NAME;<br />

#ifndef SQLDASIZE<br />

#define SQLDASIZE(n) ( sizeof( struct sqlda ) + \<br />

(n-1) * sizeof( struct sqlvar) )<br />

#endif<br />

#if defined( _SQL_PACK_STRUCTURES )<br />

#include "poppk.h"<br />

#endif<br />

#endif<br />

Die SQLDA-Felder haben folgende Bedeutung:<br />

Feld Beschreibung<br />

sqldaid Ein 8-Byte-Zeichenfeld, das die Zeichenfolge SQLDA zur<br />

Identifizierung der SQLDA-Struktur enthält. Dieses Feld<br />

unterstützt die Fehlersuche, wenn Sie Speicherinhalte untersuchen.<br />

sqldabc Eine Ganzzahl (long integer), die die Länge der SQLDA-Struktur<br />

enthält<br />

sqln Die Anzahl der Variablendeskriptoren im Array sqlvar<br />

sqld Die Anzahl der gültigen Variablendeskriptoren (die eine<br />

Hostvariable beschreiben). Dieses Feld wird in der Regel von der<br />

DESCRIBE-Anweisung gesetzt, manchmal auch vom<br />

<strong>Programmierer</strong>, wenn Daten an den Datenbankserver geliefert<br />

werden.<br />

sqlvar Ein Array, bestehend aus Deskriptoren vom Typ struct sqlvar,<br />

von denen jeder eine Hostvariable beschreibt<br />

229


Der SQL-Deskriptor-Bereich (SQLDA)<br />

SQLDA-Hostvariablen-Beschreibungen<br />

230<br />

Jede sqlvar-Struktur im SQLDA-Bereich beschreibt eine Hostvariable. Die<br />

Felder der sqlvar-Struktur haben folgende Bedeutung:<br />

♦ sqltype Der Typ der Variable, die von diesem Deskriptor beschrieben<br />

wird (siehe "Datentypen in Embedded SQL" auf Seite 196)<br />

Das "low order Bit" zeigt an, ob NULL-Werte erlaubt sind. Gültige<br />

Typen- und Konstantendefinitionen befinden sich in der Header-Datei<br />

sqldef.h.<br />

Dieses Feld wird von der DESCRIBE-Anweisung belegt. Sie können<br />

dieses Feld mit jedem Typ belegen, wenn Sie Daten an den<br />

Datenbankserver liefern oder Daten vom Datenbankserver abrufen.<br />

Erforderliche Typkonvertierungen erfolgen automatisch.<br />

♦ sqllen Länge der Variable. Was der Wert dieser Variable tatsächlich<br />

bedeutet, hängt von den Informationen zum Typ ab und davon, wie der<br />

SQLDA-Bereich verwendet wird.<br />

Für DECIMAL-Typen wird dieses Feld in zwei je 1 Byte lange Felder<br />

aufgeteilt. Das "high byte" repräsentiert die Anzahl der Gesamtstellen<br />

und das "low byte" die Anzahl der Dezimalstellen. Die Gesamtstellen<br />

sind die Gesamtzahl der Ziffern. Die Dezimalstellen sind die Anzahl der<br />

Ziffern nach dem Dezimalzeichen.<br />

Bei LONG VARCHAR- und LONG BINARY-Datentypen wird das<br />

array_len-Feld der DT_LONGBINARY- und DT_LONGVARCHAR-<br />

Datentypstruktur anstelle des sqllen-Felds verwendet.<br />

$ Weitere Informationen über das Längenfeld finden Sie unter<br />

"SQLDA sqllen-Feldwerte" auf Seite 232.<br />

♦ sqldata Ein 4-Byte-Zeiger auf den Speicher, der von der Variable belegt<br />

wird. Dieser Speicherinhalt muss den Feldern sqltype und sqllen<br />

entsprechen.<br />

$ Informationen über Speicherformate finden Sie unter "Datentypen<br />

in Embedded SQL" auf Seite 196.<br />

Beim UPDATE- und INSERT-Befehl spielt diese Variable keine Rolle<br />

<strong>für</strong> den Vorgang, falls der sqldata-Zeiger ein Null-Zeiger ist. Bei<br />

FETCH werden keine Daten zurückgegeben, falls der sqldata-Zeiger<br />

ein Null-Zeiger ist. In anderen Worten, die vom Zeiger sqldata<br />

zurückgegebene Spalte ist eine entbundene Spalte.


Kapitel 6 Programmieren mit Embedded SQL<br />

Falls die DESCRIBE-Anweisung LONG NAMES benutzt, enthält<br />

dieses Feld den Langnamen der Ergebnismengen-Spalte. Falls die<br />

DESCRIBE-Anweisung darüber hinaus eine DESCRIBE USER<br />

TYPES-Anweisung ist, dann enthält dieses Feld den Langnamen des<br />

benutzerdefinierten Datentyps statt der Spalte. Ist der Typ ein ein<br />

vordefinierter Datentyp, ist das Feld leer.<br />

♦ sqlind Ein Zeiger auf den Indikatorwert. Ein Indikatorwert ist eine<br />

Ganzzahl (short int). Ein negativer Indikatorwert zeigt einen NULL-<br />

Wert an. Ein positiver Indikatorwert bedeutet, dass diese Variable von<br />

einer FETCH-Anweisung gekürzt wurde. Der Indikatorwert enthält die<br />

Länge der Daten, bevor sie gekürzt wurden. Ein Wert von –2 zeigt<br />

einen Konvertierungsfehler an, wenn die Datenbankoption<br />

CONVERSION_ERROR auf OFF gesetzt ist.<br />

$ Weitere Hinweise finden Sie unter "Indikatorvariable" auf<br />

Seite 204.<br />

Ist der sqlind-Zeiger ein Null-Zeiger, gehört keine Indikatorvariable zu<br />

dieser Hostvariable.<br />

Das sqlind-Feld wird auch in der DESCRIBE-Anweisung verwendet,<br />

um Parametertypen anzuzeigen. Ist der Datentyp benutzerdefiniert, wird<br />

das Feld auf DT_HAS_USERTYPE_INFO gesetzt. In diesem Fall<br />

sollten Sie DESCRIBE USER TYPES ausführen, um Informationen<br />

über den benutzerdefinierten Datentyp zu erhalten.<br />

♦ sqlname Eine VARCHAR-Struktur, die einen Längen- und einen<br />

Zeichenpuffer enthält. Sie ist mit einer DESCRIBE-Anweisung belegt<br />

und wird nur da<strong>für</strong> benutzt. Dieses Feld hat verschiedene Bedeutungen<br />

<strong>für</strong> zwei Formate der DESCRIBE-Anweisung:<br />

♦ Auswahlliste (SELECT LIST) Der Namenpuffer ist belegt mit dem<br />

Spaltentitel des entsprechenden Elements in der ausgewählten Liste.<br />

♦ Bindevariable Der Namenpuffer ist belegt mit dem Namen der<br />

Hostvariable, die als Bindevariable benutzt wurde, oder mit "?" falls<br />

eine namenlose Parametermarkierung verwendet wurde.<br />

Handelt es sich um einen DESCRIBE SELECT LIST-Befehl, sind alle<br />

vorhandenen Indikatorvariablen mit einer Markierung (flag) belegt, die<br />

anzeigt, ob das Listenelement aktualisierbar ist. Weitere Informationen<br />

über diese Markierung finden Sie in der Header-Datei sqldef.h.<br />

Handelt es sich um eine DESCRIBE USER TYPES-Anweisung, dann<br />

enthält dieses Feld den Langnamen des benutzerdefinierten Datentyps an<br />

Stelle der Spalte. Ist der Typ ein ein vordefinierter Datentyp, ist das Feld<br />

leer.<br />

231


Der SQL-Deskriptor-Bereich (SQLDA)<br />

SQLDA sqllen-Feldwerte<br />

Werte beschreiben<br />

232<br />

Die Feldlänge sqllen der sqlvar-Struktur in einem SQLDA-Bereich wird in<br />

drei verschiedenen Arten von Interaktionen mit dem Datenbankserver<br />

verwendet.<br />

♦ Werte beschreiben Mit der DESCRIBE-Anweisung erhalten Sie<br />

Informationen über die Hostvariablen, die zum Speichern von Daten<br />

erforderlich sind, die von der Datenbank abgerufen wurden, oder über<br />

Hostvariable, die zum Übergeben von Daten an die Datenbank<br />

erforderlich sind.<br />

$ Siehe "Werte beschreiben" auf Seite 232.<br />

♦ Werte abrufen Werte von der Datenbank abrufen.<br />

$ Siehe "Werte abrufen" auf Seite 235.<br />

♦ Werte senden Informationen an die Datenbank senden.<br />

$ Siehe "Werte senden" auf Seite 234.<br />

Diese Interaktionen werden in diesem Abschnitt behandelt.<br />

Die folgenden Tabellen beschreiben detailliert jede dieser Interaktionen.<br />

Diese Tabellen enthalten die Schnittstellen-Konstantentypen (DT_-Typen),<br />

die in der Header-Datei sqldef.h zu finden sind. Es sind die Konstanten, die<br />

das SQLDA-Feld sqltype belegen können.<br />

$ Hinweise über sqltype-Feldwerte finden Sie unter "Datentypen in<br />

Embedded SQL" auf Seite 196.<br />

Auch in statischem SQL wird ein SQLDA-Bereich verwendet, er wird<br />

allerdings vom SQL-Präprozessor erzeugt und vollständig belegt. In diesem<br />

Fall zeigen die Tabellen die Entsprechungen zwischen den statischen C-<br />

Hostvariablentypen und den Schnittstellenkonstanten.<br />

Die folgende Tabelle zeigt die Werte der Strukturelemente sqllen und<br />

sqltype, die der DESCRIBE-Befehl <strong>für</strong> verschiedene Datenbanktypen<br />

zurückgibt (sowohl SELECT LIST als auch BIND VARIABLE DESCRIBE-<br />

Anweisungen). Im Fall eines benutzerdefinierten Datenbank-Datentyps wird<br />

der zu Grunde liegende Datentyp beschrieben.<br />

Ihr Programm kann entweder die Typen und Längen benutzen, die<br />

DESCRIBE zurückgibt, oder es kann andere Typen benutzen. Der<br />

Datenbankserver wird jede erforderliche Typkonvertierung durchführen. Der<br />

Speicherbereich, auf den das Feld sqldata zeigt, muss den Feldern sqltype<br />

und sqllen entsprechen.


Kapitel 6 Programmieren mit Embedded SQL<br />

$ Weitere Hinweise zu Embedded SQL-Datentypen finden Sie unter<br />

"Datentypen in Embedded SQL" auf Seite 196.<br />

Datenbank-Feldtyp zurückgegebener<br />

Embedded SQL-Typ<br />

BIGINT DT_BIGINT 8<br />

BINARY(n) DT_BINARY n<br />

BIT DT_BIT 1<br />

CHAR(n) DT_FIXCHAR n<br />

von describe<br />

zurückgegebene<br />

Länge<br />

DATE DT_DATE die Länge der<br />

längsten formatierten<br />

Zeichenfolge<br />

DECIMAL(p,s) DT_DECIMAL das high byte des<br />

Längenfelds im<br />

SQLDA-Bereich auf<br />

p setzen, das low<br />

byte auf s<br />

DOUBLE DT_DOUBLE 8<br />

FLOAT DT_FLOAT 4<br />

INT DT_INT 4<br />

LONG BINARY DT_LONGBINARY 32767<br />

LONG VARCHAR DT_LONGVARCHAR 32767<br />

REAL DT_FLOAT 4<br />

SMALLINT DT_SMALLINT 2<br />

TIME DT_TIME die Länge der<br />

längsten formatierten<br />

Zeichenfolge<br />

TIMESTAMP DT_TIMESTAMP die Länge der<br />

längsten formatierten<br />

Zeichenfolge<br />

TINYINT DT_TINYINT 1<br />

UNSIGNED BIGINT DT_UNSBIGINT 8<br />

UNSIGNED INT DT_UNSINT 4<br />

UNSIGNED SMALLINT DT_UNSSMALLINT 2<br />

VARCHAR(n) DT_VARCHAR n<br />

233


Der SQL-Deskriptor-Bereich (SQLDA)<br />

Werte senden<br />

234<br />

Die folgende Tabelle zeigt, wie Sie die Länge eines Werts spezifizieren,<br />

wenn Sie im SQLDA-Bereich Daten an den Datenbankserver liefern.<br />

In diesem Fall sind nur die in der Tabelle gezeigten Datentypen erlaubt. Die<br />

Datentypen DT_DATE, DT_TIME und DT_TIMESTAMP werden genau so<br />

behandelt wie DT_STRING, wenn Informationen an die Datenbank geliefert<br />

werden. Der Wert muss eine mit Nullwert abgeschlossene Zeichenfolge in<br />

einem passenden Datumsformat sein.<br />

Embedded SQL-Datentyp Programmaktion zur Einstellung der<br />

Länge<br />

DT_BIGINT keine Aktion erforderlich<br />

DT_BINARY(n) die Länge wird einem Feld in der Struktur<br />

BINARY entnommen<br />

DT_BIT keine Aktion erforderlich<br />

DT_DATE Länge durch das abschließende \0 bestimmt<br />

DT_DECIMAL(p,s) das high byte des Längenfelds im SQLDA-<br />

Bereich auf p setzen, das low byte auf s<br />

DT_DOUBLE keine Aktion erforderlich<br />

DT_FIXCHAR(n) das Längenfeld im SQLDA-Bereich<br />

bestimmt die Länge der Zeichenfolge<br />

DT_FLOAT keine Aktion erforderlich<br />

DT_INT keine Aktion erforderlich<br />

DT_LONGBINARY Längenfeld ignoriert. Siehe "LONG-Daten<br />

senden" auf Seite 240<br />

DT_LONGVARCHAR Längenfeld ignoriert. Siehe "LONG-Daten<br />

senden" auf Seite 240<br />

DT_SMALLINT keine Aktion erforderlich<br />

DT_STRING Länge durch das abschließende \0 bestimmt<br />

DT_TIME Länge durch das abschließende \0 bestimmt<br />

DT_TIMESTAMP Länge durch das abschließende \0 bestimmt<br />

DT_TIMESTAMP_STRUCT keine Aktion erforderlich


Werte abrufen<br />

Kapitel 6 Programmieren mit Embedded SQL<br />

Embedded SQL-Datentyp Programmaktion zur Einstellung der<br />

Länge<br />

DT_UNSBIGINT keine Aktion erforderlich<br />

DT_UNSINT keine Aktion erforderlich<br />

DT_UNSSMALLINT keine Aktion erforderlich<br />

DT_VARCHAR(n) die Länge wird einem Feld in der Struktur<br />

VARCHAR entnommen<br />

DT_VARIABLE Länge durch das abschließende \0 bestimmt<br />

Die folgende Tabelle zeigt die Werte des Längenfelds, wenn Sie Daten von<br />

der Datenbank abrufen und den SQLDA-Bereich verwenden. Das Feld<br />

sqllen wird beim Abrufen von Daten nie geändert.<br />

In diesem Fall sind nur die in der Tabelle gezeigten Datentypen erlaubt. Die<br />

Datentypen DT_DATE, DT_TIME und DT_TIMESTAMP werden genau so<br />

behandelt wie DT_STRING, wenn Informationen von der Datenbank<br />

abgerufen werden. Der Wert wird als Zeichenfolge im aktuellen<br />

Datumsformat formatiert.<br />

Embedded SQL-<br />

Datentyp<br />

Auf welchen Wert<br />

muss das Programm<br />

das Längenfeld setzen,<br />

wenn es Daten von der<br />

Datenbank abruft?<br />

Wie gibt die Datenbank<br />

Längeninformationen<br />

zurück, nachdem ein<br />

Wert abgerufen<br />

wurde?<br />

DT_BIGINT keine Aktion erforderlich keine Aktion erforderlich<br />

DT_BINARY(n) Maximale Länge der<br />

Struktur BINARY (n+2)<br />

das Feld len der Struktur<br />

BINARY ist auf die<br />

tatsächliche Länge gesetzt<br />

DT_BIT keine Aktion erforderlich keine Aktion erforderlich<br />

DT_DATE Länge des Puffers \0 am Ende der<br />

Zeichenfolge<br />

DT_DECIMAL(p,s) Das "high byte" auf p<br />

setzen und das "low byte"<br />

auf s<br />

keine Aktion erforderlich<br />

DT_DOUBLE keine Aktion erforderlich keine Aktion erforderlich<br />

DT_FIXCHAR(n) Länge des Puffers bis zur Länge des Puffers<br />

aufgefüllt mit Leerzeichen<br />

DT_FLOAT keine Aktion erforderlich keine Aktion erforderlich<br />

235


Der SQL-Deskriptor-Bereich (SQLDA)<br />

236<br />

Embedded SQL-<br />

Datentyp<br />

Auf welchen Wert<br />

muss das Programm<br />

das Längenfeld setzen,<br />

wenn es Daten von der<br />

Datenbank abruft?<br />

Wie gibt die Datenbank<br />

Längeninformationen<br />

zurück, nachdem ein<br />

Wert abgerufen<br />

wurde?<br />

DT_INT keine Aktion erforderlich keine Aktion erforderlich<br />

DT_LONGBINARY Länge-Feld ignoriert. Siehe<br />

"LONG-Daten abrufen"<br />

auf Seite 238<br />

DT_LONGVARCHAR Länge-Feld ignoriert. Siehe<br />

"LONG-Daten abrufen"<br />

auf Seite 238<br />

Länge-Feld ignoriert. Siehe<br />

"LONG-Daten abrufen"<br />

auf Seite 238<br />

Länge-Feld ignoriert. Siehe<br />

"LONG-Daten abrufen"<br />

auf Seite 238<br />

DT_SMALLINT keine Aktion erforderlich keine Aktion erforderlich<br />

DT_STRING Länge des Puffers \0 am Ende der<br />

Zeichenfolge<br />

DT_TIME Länge des Puffers \0 am Ende der<br />

Zeichenfolge<br />

DT_TIMESTAMP Länge des Puffers \0 am Ende der<br />

Zeichenfolge<br />

DT_TIMESTAMP_<br />

STRUCT<br />

keine Aktion erforderlich keine Aktion erforderlich<br />

DT_UNSBIGINT keine Aktion erforderlich keine Aktion erforderlich<br />

DT_UNSINT keine Aktion erforderlich keine Aktion erforderlich<br />

DT_UNSSMALLINT keine Aktion erforderlich keine Aktion erforderlich<br />

DT_VARCHAR(n) Maximale Länge der<br />

Struktur VARCHAR (n+2)<br />

das Feld len der Struktur<br />

VARCHAR ist auf die<br />

tatsächliche Länge gesetzt


Lange Werte senden und abfragen<br />

Verwendung von<br />

statischem SQL<br />

Verwendung von<br />

dynamischem SQL<br />

Kapitel 6 Programmieren mit Embedded SQL<br />

Die Methode zum Senden und Abrufen von LONG VARCHAR- und LONG<br />

BINARY-Werten in Embedded SQL-Anwendungen ist anders als bei den<br />

übrigen Datentypen. Sie können auch die Standard-SQLDA-Felder<br />

verwenden, allerdings sind diese auf 32-Kbyte-Daten beschränkt, da die<br />

Felder, die die Informationen enthalten (sqldata, sqllen, sqlind), 16-Bit-<br />

Werte sind. Eine Änderung dieser Werte auf 32-Bit-Werte würde<br />

vorhandene Anwendungen zerstören.<br />

Die Methode zur Beschreibung von LONG VARCHAR- und LONG<br />

BINARY-Werten ist dieselbe wie bei anderen Datentypen.<br />

$ Hinweise über das Abrufen und Senden von Werten finden Sie unter<br />

"LONG-Daten abrufen" auf Seite 238 und "LONG-Daten senden" auf<br />

Seite 240.<br />

Es werden separate Struktuten verwendet, um die zugeordneten,<br />

gespeicherten und ungekürzten Längen von LONG BINARY- und LONG<br />

VARCHAR-Datentypen aufzunehmen. Die statischen SQL-Datentypen<br />

werden in sqlca.h folgendermaßen definiert:<br />

#define DECL_LONGVARCHAR( size ) \<br />

struct { a_sql_uint32 array_len; \<br />

a_sql_uint32 stored_len; \<br />

a_sql_uint32 untrunc_len; \<br />

char array[size+1];\<br />

}<br />

#define DECL_LONGBINARY( size ) \<br />

struct { a_sql_uint32 array_len; \<br />

a_sql_uint32 stored_len; \<br />

a_sql_uint32 untrunc_len; \<br />

char array[size]; \<br />

}<br />

Bei dynamischem SQL ist das Einstellen des sqltype-Felds auf<br />

DT_LONGVARCHAR oder DT_LONGBINARY ausreichend. Die<br />

zugeordneten LONGBINARY- und LONGVARCHAR-Sturkturen sehen<br />

folgendermaßen aus:<br />

237


Lange Werte senden und abfragen<br />

LONG-Daten abrufen<br />

238<br />

typedef struct LONGVARCHAR {<br />

a_sql_uint32 array_len;<br />

/* Anzahl der zugeordneten Byte im Array */<br />

a_sql_uint32 stored_len;<br />

/* Anzahl der im Array gespeicherten Byte<br />

* (nie höher als array_len)<br />

*/<br />

a_sql_uint32 untrunc_len;<br />

/* Anzahl der Byte in nicht-gekürztem<br />

* Ausdruck(kann höher sein als array_len)<br />

*/<br />

char array[1]; /* die Daten */<br />

} LONGVARCHAR, LONGBINARY;<br />

$ Hinweise darüber, wie Sie diese Funktion in Ihren Anwendungen<br />

implementieren, finden Sie unter "LONG-Daten abrufen" auf Seite 238 und<br />

"LONG-Daten senden" auf Seite 240.<br />

Dieser Abschnitt beschreibt, wie Sie LONG-Werte aus der Datenbank<br />

abrufen. Hintergrundinformationen finden Sie unter "Lange Werte senden<br />

und abfragen" auf Seite 237.<br />

Die Prozeduren unterscheiden sich abhängig davon, ob Sie statisches oder<br />

dynamisches SQL verwenden.<br />

v So rufen Sie einen LONG VARCHAR- oder LONG BINARY-Wert ab<br />

(statisches SQL):<br />

1 Deklarieren Sie eine Hostvariable vom Typ DECL_LONGVARCHAR<br />

oder DECL_LONGBINARY, wie erforderlich.<br />

2 Rufen Sie die Daten mit FETCH, GET DATA oder EXECUTE INTO<br />

ab. <strong>Adaptive</strong> Server <strong>Anywhere</strong> stellt die folgenden Informationen ein:<br />

♦ Indikatorvariable Die Indikatorvariable ist negativ, wenn der Wert<br />

NULL ist, oder 0, wenn es keine Kürzung gibt; beziehungsweise die<br />

positive ungekürzte Länge in Byte bis zu einem Höchstwert von<br />

32767.<br />

$ Weitere Hinweise finden Sie unter "Indikatorvariable" auf<br />

Seite 204.<br />

♦ stored_len Dieses DECL_LONGVARCHAR- oder<br />

DECL_LONGBINARY-Feld enthält die Anzahl von Byte, die in<br />

das Array abgerufen werden. Der Wert ist niemals größer als<br />

array_len.


Kapitel 6 Programmieren mit Embedded SQL<br />

♦ untrunc_len Dieses DECL_LONGVARCHAR- oder<br />

DECL_LONGBINARY-Feld enthält die Anzahl von Byte, die vom<br />

Datenbankserver gehalten werden. Dieser Wert muss kleiner/gleich<br />

dem stored_len-Wert sein. Er wird auch gesetzt, wenn der<br />

Datenwert ungekürzt ist.<br />

v So nehmen Sie einen Wert in eine LONGVARCHAR- oder<br />

LONGBINARY-Struktur auf (dynamisches SQL):<br />

1 Stellen Sie das sqltype-Feld auf DT_LONGVARCHAR oder<br />

DT_LONGBINARY ein, wie erforderlich.<br />

2 Stellen Sie das sqldata-Feld so ein, dass es auf die LONGVARCHARoder<br />

LONGBINARY-Struktur zeigt.<br />

Sie können das LONGVARCHARSIZE( n )- oder LONGBINARYSIZE( n<br />

)-Makro verwenden, um die Gesamtanzahl der Bytes zu bestimmen, die<br />

zugeordnet werden müssen, um n-Byte von Daten im Array-Feld<br />

aufzunehmen.<br />

3 Stellen Sie das array_len-Feld der LONGVARCHAR- oder<br />

LONGBINARY-Struktur auf die Anzahl der Bytes ein, die dem Array-<br />

Feld zugeordnet sind.<br />

4 Rufen Sie die Daten mit FETCH, GET DATA oder EXECUTE INTO<br />

ab. <strong>Adaptive</strong> Server <strong>Anywhere</strong> stellt die folgenden Informationen ein:<br />

♦ * sqlind Dieses sqlda-Feld ist negativ, wenn der Wert NULL ist,<br />

oder 0, wenn es keine Kürzung gibt, beziehungsweise die positive<br />

ungekürzte Länge in Byte bis zu einem Höchstwert von 32767.<br />

♦ stored_len Dieses LONGVARCHAR- oder LONGBINARY-Feld<br />

enthält die Anzahl von Byte, die in das Array abgerufen werden.<br />

Der Wert ist niemals größer als array_len.<br />

♦ untrunc_len Dieses LONGVARCHAR- oder LONGBINARY-Feld<br />

enthält die Anzahl von Byte, die vom Datenbankserver gehalten<br />

werden. Dieser Wert muss kleiner/gleich dem stored_len-Wert<br />

sein. Er wird auch gesetzt, wenn der Datenwert ungekürzt ist.<br />

Der folgende Codeabschnitt illustriert den Mechanismus, der zum Abrufen<br />

von LONG VARCHAR-Daten mittels dynamischem Embedded SQL<br />

verwendet wird. Er dient nur zur Illustration und ist nicht <strong>für</strong> eine<br />

tatsächliche Verwendung bestimmt.<br />

239


Lange Werte senden und abfragen<br />

LONG-Daten senden<br />

240<br />

#define DATA_LEN 128000<br />

void get_test_var()<br />

/*****************/<br />

{<br />

LONGVARCHAR *longptr;<br />

SQLDA *sqlda;<br />

SQLVAR *sqlvar;<br />

}<br />

sqlda = alloc_sqlda( 1 );<br />

longptr = (LONGVARCHAR *)malloc(<br />

LONGVARCHARSIZE( DATA_LEN ) );<br />

if( sqlda == NULL || longptr == NULL ) {<br />

fatal_error( "Allocation failed" );<br />

}<br />

// longptr <strong>für</strong> Datenaufnahme initialisieren<br />

longptr->array_len = DATA_LEN;<br />

// _<br />

// (sqllen wird nicht mit DT_LONG-Typen verwendet)<br />

sqlda->sqld = 1; // 1 sqlvar verwenden<br />

sqlvar = &sqlda->sqlvar[0];<br />

sqlvar->sqltype = DT_LONGVARCHAR;<br />

sqlvar->sqldata = longptr;<br />

printf( "fetching test_var\n" );<br />

EXEC SQL PREPARE select_stmt FROM 'SELECT test_var';<br />

EXEC SQL EXECUTE select_stmt INTO DESCRIPTOR sqlda;<br />

EXEC SQL DROP STATEMENT select_stmt;<br />

printf( "stored_len: %d, untrunc_len: %d,<br />

1st char: %c, last char: %c\n",<br />

longptr->stored_len,<br />

longptr->untrunc_len,<br />

longptr->array[0],<br />

longptr->array[DATA_LEN-1] );<br />

free_sqlda( sqlda );<br />

free( longptr );<br />

Dieser Abschnitt beschreibt, wie Sie LONG-Werte an die Datenbank von<br />

Embedded SQL-Anwendungen senden. Hintergrundinformationen finden Sie<br />

unter "Lange Werte senden und abfragen" auf Seite 237.<br />

Die Prozeduren unterscheiden sich abhängig davon, ob Sie statisches oder<br />

dynamisches SQL verwenden.


Kapitel 6 Programmieren mit Embedded SQL<br />

v So senden Sie einen LONG VARCHAR- oder LONG BINARY-Wert<br />

(statisches SQL):<br />

1 Deklarieren Sie eine Hostvariable vom Typ DECL_LONGVARCHAR<br />

oder DECL_LONGBINARY, wie erforderlich.<br />

2 Wenn Sie NULL senden und eine Indikatorvariable verwenden, stellen<br />

Sie die Indikatorvariable auf einen negativen Wert ein.<br />

$ Weitere Hinweise finden Sie unter "Indikatorvariable" auf<br />

Seite 204.<br />

3 Stellen Sie das stored_len-Feld der DECL_LONGVARCHAR- oder<br />

DECL_LONGBINARY-Struktur auf die Anzahl von Byte der Daten im<br />

Array-Feld ein.<br />

4 Senden Sie die Daten, indem Sie den Corsor öffnen oder die Anweisung<br />

ausführen.<br />

Der folgende Codeabschnitt illustriert den Mechanismus, der zum Senden<br />

von LONG VARCHAR-Daten mittels statischem Embedded SQL verwendet<br />

wird. Er dient nur zur Illustration und ist nicht <strong>für</strong> eine tatsächliche<br />

Verwendung bestimmt.<br />

#define DATA_LEN 12800<br />

EXEC SQL BEGIN DECLARE SECTION;<br />

// SQLPP initialisiert longdata.array_len<br />

DECL_LONGVARCHAR(128000) longdata;<br />

EXEC SQL END DECLARE SECTION;<br />

void set_test_var()<br />

/*****************/<br />

{<br />

// longdata <strong>für</strong> das Senden von Daten initialisieren<br />

memset( longdata.array, 'a', DATA_LEN );<br />

longdata.stored_len = DATA_LEN;<br />

}<br />

printf( "Setting test_var to %d a's\n", DATA_LEN );<br />

EXEC SQL SET test_var = :longdata;<br />

v So senden Sie einen Wert mittels einer LONGVARCHAR- oder<br />

LONGBINARY-Struktur (dynamisches SQL):<br />

1 Stellen Sie das sqltype-Feld auf DT_LONGVARCHAR oder<br />

DT_LONGBINARY ein, wie erforderlich.<br />

2 Wenn Sie NULL senden, stellen Sie * sqlind auf einen negativen Wert<br />

ein.<br />

3 Stellen Sie das sqldata-Feld so ein, dass es auf die LONGVARCHARoder<br />

LONGBINARY-Struktur zeigt.<br />

241


Lange Werte senden und abfragen<br />

242<br />

Sie können das LONGVARCHARSIZE( n )- oder LONGBINARYSIZE( n<br />

)-Makro verwenden, um die Gesamtanzahl an Byte zu bestimmen, die<br />

zugeordnet werden müssen, um n-Byte von Daten im Array-Feld<br />

aufzunehmen.<br />

4 Stellen Sie das array_len-Feld der LONGVARCHAR- oder<br />

LONGBINARY-Struktur auf die Anzahl an Byte ein, die dem Array-<br />

Feld zugeordnet sind.<br />

5 Stellen Sie das stored_len-Feld der LONGVARCHAR- oder<br />

LONGBINARY-Struktur auf die Anzahl an Byte der Daten im Array-<br />

Feld ein. Dieser Wert darf nicht größer als array_len sein.<br />

6 Senden Sie die Daten, indem Sie den Cursor öffnen oder die Anweisung<br />

ausführen.


Kapitel 6 Programmieren mit Embedded SQL<br />

Gespeicherte Prozeduren verwenden<br />

In diesem Abschnitt wird die Verwendung von SQL-Prozeduren in<br />

Embedded SQL beschrieben.<br />

Einfache gespeicherte Prozeduren verwenden<br />

Sie können gespeicherte Prozeduren in Embedded SQL erstellen und<br />

aufrufen.<br />

Eine CREATE PROCEDURE-Anweisung kann wie jede andere<br />

Datendefinitions-Anweisung, z.B. CREATE TABLE, eingebettet werden.<br />

Sie können auch eine CALL-Anweisung einbetten, um eine gespeicherte<br />

Prozedur auszuführen. Das folgende Code-Fragment veranschaulicht das<br />

Erstellen und Ausführen einer gespeicherten Prozedur in Embedded SQL<br />

EXEC SQL CREATE PROCEDURE pettycash( IN amount<br />

DECIMAL(10,2) )<br />

BEGIN<br />

UPDATE account<br />

SET balance = balance - amount<br />

WHERE name = ’bank’;<br />

UPDATE account<br />

SET balance = balance + amount<br />

WHERE name = ’pettycash expense’;<br />

END;<br />

EXEC SQL CALL pettycash( 10.72 );<br />

Wenn Sie Werte von Hostvariablen an eine gespeicherte Prozedur<br />

weitergeben oder die Ausgabevariable abrufen wollen, bereiten Sie eine<br />

CALL-Anweisung vor und führen Sie sie aus. Das folgende Code-Fragment<br />

veranschaulicht die Verwendung von Hostvariablen. Sowohl die USING als<br />

auch die INTO-Klausel werden in der EXECUTE-Anweisung benutzt.<br />

EXEC SQL BEGIN DECLARE SECTION;<br />

double hv_expense;<br />

double hv_balance;<br />

EXEC SQL END DECLARE SECTION;<br />

243


Gespeicherte Prozeduren verwenden<br />

244<br />

// hier Code schreiben<br />

EXEC SQL CREATE PROCEDURE pettycash(<br />

IN expense DECIMAL(10,2),<br />

OUT endbalance DECIMAL(10,2) )<br />

BEGIN<br />

UPDATE account<br />

SET balance = balance - expense<br />

WHERE name = ’bank’;<br />

UPDATE account<br />

SET balance = balance + expense<br />

WHERE name = ’pettycash expense’;<br />

SET endbalance = ( SELECT balance FROM account<br />

WHERE name = ’bank’ );<br />

END;<br />

EXEC SQL PREPARE S1 FROM ’CALL pettycash( ?, ? )’;<br />

EXEC SQL EXECUTE S1 USING :hv_expense INTO :hv_balance;<br />

$ Weitere Hinweise finden Sie unter "EXECUTE-Anweisung [ESQL]"<br />

auf Seite 449 der Dokumentation ASA SQL-Referenzhandbuch und<br />

"PREPARE-Anweisung [ESQL]" auf Seite 533 der Dokumentation ASA<br />

SQL-Referenzhandbuch.<br />

Gespeicherte Prozeduren mit Ergebnismengen<br />

Eine Datenbankprozedur kann auch eine SELECT-Anweisung enthalten. Die<br />

Prozedur wird mit einer RESULT-Klausel deklariert, um Anzahl, Name und<br />

Typen der Spalten in der Ergebnismenge zu spezifizieren. Die Spalten einer<br />

Ergebnismenge unterscheiden sich von den Ausgabeparametern. In einer<br />

Prozedur mit Ergebnismenge kann die CALL-Anweisung an Stelle der<br />

SELECT-Anweisung in der Cursordeklaration verwendet werden:<br />

EXEC SQL BEGIN DECLARE SECTION;<br />

char hv_name[100];<br />

EXEC SQL END DECLARE SECTION;<br />

EXEC SQL CREATE PROCEDURE female_employees()<br />

RESULT( name char(50) )<br />

BEGIN<br />

SELECT emp_fname || emp_lname FROM employee<br />

WHERE sex = ’f’;<br />

END;<br />

EXEC SQL PREPARE S1 FROM ’CALL female_employees()’;<br />

EXEC SQL DECLARE C1 CURSOR FOR S1;<br />

EXEC SQL OPEN C1;<br />

for(;;) {


Dynamische<br />

Cursor <strong>für</strong> CALL-<br />

Anweisungen<br />

Kapitel 6 Programmieren mit Embedded SQL<br />

EXEC SQL FETCH C1 INTO :hv_name;<br />

if( SQLCODE != SQLE_NOERROR ) break;<br />

printf( "%s\\n", hv_name );<br />

}<br />

EXEC SQL CLOSE C1;<br />

In diesem Beispiel wurde die Prozedur mit einer OPEN-Anweisung statt<br />

einer EXECUTE-Anweisung aufgerufen. Nach der OPEN-Anweisung wird<br />

die Prozedur ausgeführt, bis sie eine SELECT-Anweisung erreicht. Zu<br />

diesem Zeitpunkt ist C1 ein Cursor <strong>für</strong> die SELECT-Anweisung innerhalb<br />

der Datenbankprozedur. Sie können alle Arten des FETCH-Befehls<br />

verwenden (rückwärts und vorwärts scrollen) solange Sie sie benötigen. Die<br />

CLOSE-Anweisung beendet die Ausführung der Prozedur.<br />

Nach der SELECT-Anweisung wird in der Prozedur keine weitere<br />

Anweisung ausgeführt. Um Anweisungen nach dem SELECT auszuführen,<br />

benutzen Sie den Befehl RESUME Cursorname. Der RESUME-Befehl gibt<br />

entweder die Warnung SQLE_PROCEDURE_COMPLETE zurück oder<br />

SQLE_NOERROR, und zeigt damit an, dass es noch einen weiteren Cursor<br />

gibt. Das folgende Beispiel zeigt eine zweifache Auswahlprozedur:<br />

EXEC SQL CREATE PROCEDURE people()<br />

RESULT( name char(50) )<br />

BEGIN<br />

SELECT emp_fname || emp_lname<br />

FROM employee;<br />

SELECT fname || lname<br />

FROM customer;<br />

END;<br />

EXEC SQL PREPARE S1 FROM ’CALL people()’;<br />

EXEC SQL DECLARE C1 CURSOR FOR S1;<br />

EXEC SQL OPEN C1;<br />

while( SQLCODE == SQLE_NOERROR ) {<br />

for(;;) {<br />

EXEC SQL FETCH C1 INTO :hv_name;<br />

if( SQLCODE != SQLE_NOERROR ) break;<br />

printf( "%s\\n", hv_name );<br />

}<br />

EXEC SQL RESUME C1;<br />

}<br />

EXEC SQL CLOSE C1;<br />

Diese Beispiele haben statische Cursor verwendet. Dynamische Cursor<br />

können auch <strong>für</strong> die CALL-Anweisung verwendet werden.<br />

$ Eine Beschreibung von dynamischen Cursorn finden Sie unter "Die<br />

dynamische SELECT-Anweisung" auf Seite 226.<br />

245


Gespeicherte Prozeduren verwenden<br />

DESCRIBE ALL<br />

Mehrfache<br />

Ergebnismengen<br />

246<br />

Die DESCRIBE-Anweisung funktioniert ohne Einschränkung <strong>für</strong><br />

Prozeduraufrufe. DESCRIBE OUTPUT erzeugt einen SQLDA-Bereich mit<br />

einer Beschreibung <strong>für</strong> jede Spalte der Ergebnismenge.<br />

Hat die Prozedur keine Ergebnismenge, enthält der SQLDA-Bereich eine<br />

Beschreibung <strong>für</strong> jeden INOUT- oder OUT-Parameter der Prozedur. Eine<br />

DESCRIBE INPUT-Anweisung erzeugt einen SQLDA-Bereich mit einer<br />

Beschreibung <strong>für</strong> jeden IN- oder INOUT-Parameter der Prozedur.<br />

DESCRIBE ALL beschreibt IN-, INOUT-, OUT- und RESULT-Parameter.<br />

DESCRIBE ALL benutzt die Indikatorvariablen im SQLDA-Bereich, um<br />

zusätzliche Information zu liefern.<br />

Die Bits <strong>für</strong> DT_PROCEDURE_IN und DT_PROCEDURE_OUT werden in<br />

den Indikatorvariablen gesetzt, wenn eine CALL-Anweisung beschrieben<br />

wird. DT_PROCEDURE_IN gibt einen IN- oder INOUT-Parameter an, und<br />

DT_PROCEDURE_OUT gibt einen INOUT- oder OUT-Parameter an. In<br />

RESULT-Spalten von Prozeduren sind beide Bits bereinigt.<br />

Nach einem Beschreibungs-OUTPUT können diese Bits benutzt werden, um<br />

zwischen Anweisungen zu unterscheiden, die Ergebnismengen haben<br />

(müssen OPEN, FETCH, RESUME, CLOSE benutzen), und Anweisungen,<br />

die keine Ergebnismengen haben (müssen EXECUTE benutzen).<br />

$ Eine vollständige Beschreibung finden Sie unter "DESCRIBE-<br />

Anweisung [ESQL]" auf Seite 426 der Dokumentation ASA SQL-<br />

Referenzhandbuch.<br />

Haben Sie eine Prozedur, die mehrere Ergebnismengen zurückgibt, müssen<br />

Sie sie nach jeder RESUME-Anweisung neu beschreiben, falls sich die Form<br />

der Ergebnismengen ändert.<br />

Sie müssen den Cursor beschreiben, nicht die Anweisung, um die aktuelle<br />

Position des Cursors neu zu beschreiben.


Kapitel 6 Programmieren mit Embedded SQL<br />

Programmiertechniken <strong>für</strong> Embedded SQL<br />

´Dieser Abschnitt enthält eine Reihe von Tipps <strong>für</strong> Entwickler von<br />

Programmen mit Embedded SQL.<br />

Anforderungs-Management implementieren<br />

Sicherungsfunktionen<br />

Das voreingestellte Verhalten der Schnittstellen-DLL <strong>für</strong> Anwendungen<br />

beinhaltet es, zu warten, bis eine Anforderung an die Datenbank ausgeführt<br />

wurde und erst dann andere Funktionen auszuführen. Dieses Verhalten<br />

können Sie mit Hilfe der Funktionen <strong>für</strong> die Anforderungsverwaltung<br />

ändern. Zum Beispiel ist bei Interactive SQL das Betriebssystem weiterhin<br />

aktiv, während Interactive SQL auf eine Antwort der Datenbank wartet und<br />

inzwischen andere Aufgaben ausführt.<br />

Sie können eine Anwendung aktivieren, während eine Anforderung an die<br />

Datenbank abgearbeitet wird, indem Sie eine Callback-Funktion zur<br />

Verfügung stellen. In dieser Callback-Funktion setzen Sie eine weitere<br />

Datenbankanforderung - keine db_cancel_request - ab. Sie können die<br />

Funktion db_is_working in Ihren Message-Handlers verwenden, um<br />

festzustellen, ob gerade eine Anforderung an die Datenbank abgearbeitet<br />

wird.<br />

Die Funktion db_register_a_callback wird verwendet, um die Callback-<br />

Funktionen Ihrer Anwendung zu registrieren:<br />

$ Weitere Hinweise finden Sie im Folgenden.<br />

♦ "db_register_a_callback-Funktion" auf Seite 261<br />

♦ "db_cancel_request-Funktion" auf Seite 257<br />

♦ "db_is_working-Funktion" auf Seite 260<br />

Die Funktion db_backup unterstützt online-Sicherungen in Anwendungen<br />

mit Embedded SQL. Das Sicherungsdienstprogramm setzt diese Funktion<br />

ein. Sie brauchen nur dann ein Programm zu schreiben, das diese Funktion<br />

verwendet, falls Ihre Sicherungsanforderungen die Leistung des<br />

Sicherungsdienstprogramms von <strong>Adaptive</strong> Server <strong>Anywhere</strong> übersteigen.<br />

247


Programmiertechniken <strong>für</strong> Embedded SQL<br />

248<br />

BACKUP-Anweisung wird empfohlen<br />

Obwohl diese Funktion ein Möglichkeit bietet, einer Anwendung<br />

Sicherungsfunktionen hinzuzufügen, wird empfohlen, diese Aufgabe über<br />

die BACKUP-Anweisung zu auszuführen. Weitere Hinweise finden Sie<br />

unter "BACKUP-Anweisung" auf Seite 268 der Dokumentation ASA<br />

SQL-Referenzhandbuch.<br />

$ Sie können mit der Funktion DBBackup der Datenbank-Tools auch<br />

direkt auf das Sicherungsdienstprogramm zugreifen. Weitere Hinweise über<br />

diese Funktion finden Sie im Abschnitt "DBBackup-Funktion" auf Seite 323.<br />

$ Weitere Hinweise finden Sie unter "db_backup-Funktion" auf<br />

Seite 254.


SQL-Präprozessor<br />

Syntax<br />

Siehe auch:<br />

Kapitel 6 Programmieren mit Embedded SQL<br />

Der SQL-Präprozessor bearbeitet ein C- oder C++-Programm, das<br />

Embedded SQL-Code enthält, bevor der Compiler gestartet wird.<br />

sqlpp [ Parameter ] SQL-Dateiname [ Ausgabedateiname ]<br />

Parameter Beschreibung<br />

–c<br />

"Schlüsselwort=Wert;..."<br />

–d Bevorzugte Datengröße<br />

Referenzparameter <strong>für</strong> die Datenbankverbindung<br />

bereitstellen [UltraLite]<br />

–e Ebene Nicht-konforme SQL-Syntax als Fehler kennzeichnen<br />

–f Das Schlüsselwort "far" in erzeugte statische Daten<br />

schreiben<br />

-g UltraLite-Warnungen nicht anzeigen<br />

–h Zeilenbreite Maximale Zeilenlänge der Ausgabe begrenzen<br />

–k Benutzerdeklarationation von SQLCODE einfügen<br />

-m Version Versionsnamen <strong>für</strong> generierte Synchronisationsskripten<br />

angeben<br />

–n Zeilennummern<br />

–o Betriebssys Ziel-Betriebssystem.<br />

–p Projekt UltraLite-Projektname<br />

–q Stiller Modus: Keinen Vorspann ausgeben<br />

–r Wieder-eintretender Code<br />

–s Zeichenfolgenlänge Maximale Zeichenfolgenlänge <strong>für</strong> den Compiler<br />

–w Ebene Nicht-konforme SQL-Syntax als Warnung<br />

kennzeichnen<br />

–x Mehrbyte-SQL-Zeichenfolgen in Escapesequenzen<br />

umwandeln<br />

–z Sequenz Sortierfolge angeben<br />

"Überblick" auf Seite 182<br />

249


SQL-Präprozessor<br />

Beschreibung<br />

Optionen<br />

250<br />

Der SQL-Präprozessor bearbeitet ein C- oder C++-Programm, das<br />

Embedded SQL-Code enthält, bevor der Compiler gestartet wird. SQLPP<br />

übersetzt die SQL-Anweisungen in Eingabedatei in Quellcode der Sprache<br />

C, der in Ausgabedatei gelegt wird. Die normale Dateinamenerweiterung <strong>für</strong><br />

Quelldateien mit Embedded SQL ist .sqc. Der voreingestellte Name <strong>für</strong> die<br />

Ausgabedatei ist der Name der SQL-Datei mit der Erweiterung .c. Falls der<br />

Name der SQL-Datei bereits die Erweiterung .c hat, erhält die Ausgabedatei<br />

standardmäßig die Erweiterung .cc.<br />

–c Erforderlich, wenn Dateien, die Teil einer UltraLite-Anwendung sind, mit<br />

dem Präprozessor bearbeitet werden. Die Verbindungszeichenfolge muss<br />

dem SQL-Präprozessor Zugriff zum Lesen und Ändern Ihrer<br />

Referenzdatenbank geben.<br />

–d Code erzeugen, der die Größe des Datenbereichs reduziert.<br />

Datenstrukturen werden vor der Verwendung zur Ausführungszeit wieder<br />

benutzt und initialisiert. Dies erhöht die Code-Größe.<br />

–e Diese Option kennzeichnet Embedded SQL-Code, der nicht Teil eines<br />

bestimmten Sets von SQL/92 ist, als Fehler.<br />

Die zulässigen Werte von Ebene und ihre Bedeutung sind wie folgt:<br />

♦ e Kennzeichnet Syntax, die nicht Einstiegsebene-SQL/92-Syntax ist<br />

♦ i Kennzeichnet Syntax, die nicht Zwischenebene-SQL/92-Syntax ist<br />

♦ f Kennzeichnet Syntax, die nicht vollständige SQL/92-Syntax ist<br />

♦ t Nicht-Standard-Hostvariablentypen markieren<br />

♦ u Kennzeichnet Syntax, die nicht von UltraLite unterstützt wird<br />

♦ w Lässt die gesamte unterstützte Syntax zu<br />

-g Keine Warnungen im Hinblick auf die Erzeugung von UltraLite-Code<br />

–h Begrenzt die maximale Länge von Ausgabezeilen durch sqlpp auf<br />

Zeilenbreite. Das Fortsetzungszeichen ist ein Rückstrich (\) und der<br />

Mindestwert von Zeilenbreite ist zehn.<br />

–k Teilt dem Präprozessor mit, dass das zu kompilierende Programm eine<br />

Benutzerdeklaration von SQLCODE enthält<br />

-m Geben Sie den Versionsnamen <strong>für</strong> die erzeugten Synchronisationsskripts<br />

an. Die erzeugten Synchronisationsskripts können in einer MobiLinkkonsolidierten<br />

Datenbank <strong>für</strong> einfache Synchronisation verwendet werden.


Kapitel 6 Programmieren mit Embedded SQL<br />

–n Erzeugt Zeilennummerinformationen in der C-Datei. Diese umfassen<br />

#line-Direktiven an den betreffenden Stellen im erzeugten C-Code. Wenn<br />

der von Ihnen verwendete Compiler die Anweisung #line unterstützt, lässt<br />

diese Option den Compiler Fehler in Zeilennummern in der SQC-Datei<br />

protokollieren (der Datei mit Embedded SQL), und zwar im Gegensatz zum<br />

Protokollieren von Fehlern in Zeilennummern in der C-Datei, die vom SQL-<br />

Präprozessor erzeugt wird. Ebenso werden die #line-Anweisungen indirekt<br />

vom Source Level Debugger verwendet, sodass Sie bei der Fehlersuche<br />

gleichzeitig die SQC-Quelldatei sehen können.<br />

–o Geben Sie das Ziel-Betriebssystem an. Beachten Sie, dass diese Option<br />

mit dem Betriebssystem übereinstimmen muss, auf dem das Programm<br />

ausgeführt werden soll. In Ihrem Programm wird eine Referenz auf ein<br />

bestimmtes Symbol erzeugt. Dieses Symbol ist in der<br />

Schnittstellenbibliothek definiert. Wenn Sie die falsche Betriebssystem-<br />

Spezifikation oder die falsche Bibliothek verwenden, wird vom Linker ein<br />

Fehler erkannt. Folgende Betriebssysteme werden unterstützt:<br />

♦ WINDOWS Windows 95/98/Me, Windows CE<br />

♦ WINNT Microsoft Windows NT/2000/XP<br />

♦ NETWARE Novell NetWare<br />

♦ UNIX UNIX<br />

–p Kennzeichnet das UltraLite-Projekt, zu dem die Embedded SQL-Dateien<br />

gehören. Diese Option kann nur verwendet werden, wenn Dateien verarbeitet<br />

werden, die Teil einer UltraLite-Anwendung sind.<br />

–q Kein Banner drucken.<br />

–r Weitere Hinweise zum reentrant-Code finden Sie unter "SQLCA-<br />

Verwaltung <strong>für</strong> Code mit mehreren Threads oder "reentrant"-Code" auf<br />

Seite 211.<br />

–s Setzt die maximale Größe <strong>für</strong> Zeichenfolgen fest, die der Präprozessor in<br />

die C-Datei ausgibt. Zeichenfolgen, die länger als dieser Wert sind, werden<br />

mit Hilfe einer Liste von Zeichen initialisiert (’a’,’b’,’c’ usw.). Die meisten C-<br />

Compiler sind in der Größe der Zeichenfolgenliterale begrenzt, die Sie<br />

handhaben können. Mit dieser Option wird die obere Grenze festgesetzt. Der<br />

Standardwert ist 500.<br />

–w Diese Option kennzeichnet jeden Embedded SQL-Code als Warnung, der<br />

nicht Teil eines bestimmten Sets von SQL/92 ist.<br />

Die zulässigen Werte von Ebene und ihre Bedeutung sind wie folgt:<br />

♦ e Kennzeichnet Syntax, die nicht Einstiegsebene-SQL/92-Syntax ist<br />

251


SQL-Präprozessor<br />

252<br />

♦ i Kennzeichnet Syntax, die nicht Zwischenebene-SQL/92-Syntax ist<br />

♦ f Kennzeichnet Syntax, die nicht vollständige SQL/92-Syntax ist<br />

♦ t Nicht-Standard-Hostvariablentypen markieren<br />

♦ u Kennzeichnet Syntax, die nicht von UltraLite unterstützt wird<br />

♦ w Lässt die gesamte unterstützte Syntax zu<br />

–x Ändert Mehrbyte-Zeichenfolgen in Escape-Sequenzen, sodass sie vom<br />

Compiler verarbeitet werden können.<br />

–z Mit dieser Option wird die Kollatierungssequenz angegeben. Um eine<br />

Liste mit den empfohlenen Kollatierungssequenzen zu erhalten, geben Sie<br />

dbinit –l an der Eingabeaufforderung ein.<br />

Die Kollatierungssequenz hilft dem Präprozessor, die Zeichen zu verstehen,<br />

die im Quellcode oder Programm verwendet werden, z.B. bei der<br />

Identifizierung von alphabetischen Zeichen, die <strong>für</strong> die Verwendung in<br />

Bezeichnern geeignet sind. Wenn -z nicht angegeben wird, versucht der<br />

Präprozessor, auf Grund des Betriebssystems und der Umgebungsvariablen<br />

SQLLOCALE eine geeignete Kollatierung zu ermitteln.


Referenz der Bibliotheksfunktion<br />

DLL-Eintrittspunkte<br />

alloc_sqlda-Funktion<br />

Prototyp<br />

Beschreibung<br />

alloc_sqlda_noind-Funktion<br />

Prototyp<br />

Beschreibung<br />

Kapitel 6 Programmieren mit Embedded SQL<br />

Der SQL-Präprozessor erzeugt Funktionsaufrufe in der<br />

Schnittstellenbibliothek oder DLL. Zusätzlich zu den vom SQL-Präprozessor<br />

erzeugten Funktionsaufrufen wird dem Benutzer eine Gruppe von<br />

Bibliotheksfunktionen zur Verfügung gestellt, mit denen Datenbankvorgänge<br />

leichter ausgeführt werden können. Prototypen dieser Funktionen werden<br />

durch den Befehl EXEC SQL INCLUDE SQLCA eingefügt.<br />

Dieser Abschnitt enthält eine Referenzbeschreibung der verschiedenen<br />

Funktionen, geordnet nach Kategorien.<br />

Die DLL-Eintrittspunkte sind gleich, abgesehen davon, dass die Prototypen<br />

einen <strong>für</strong> DLLs passenden Zusatz haben.<br />

Sie können die Eintrittspunkte auf portierbare Weise unter Verwendung von<br />

_esqlentry_ deklarieren, was in sqlca.h definiert ist. Es wird in den Wert<br />

__stdcall aufgelöst:<br />

SQLDA *alloc_sqlda( unsigned numvar );<br />

Diese Funktion weist einen SQLDA-Bereich mit Deskriptoren <strong>für</strong> die<br />

numvar zu. Das Feld sqln des SQLDA-Bereichs wird mit der numvar<br />

initialisiert. Den Indikatorvariablen wird Speicherplatz zugewiesen, die<br />

Indikatorzeiger werden auf diesen Speicherplatz gesetzt und der<br />

Indikatorwert wird mit 0 (Null) initialisiert. Ein Null-Zeiger wird<br />

zurückgegeben, falls kein Speicher zugewiesen werden konnte. Es wird<br />

empfohlen, dass Sie diese Funktion an Stelle der Funktion<br />

alloc_sqlda_noind verwenden.<br />

SQLDA *alloc_sqlda_noind( unsigned numvar );<br />

Diese Funktion weist einen SQLDA-Bereich mit Deskriptoren <strong>für</strong> die<br />

numvar zu. Das Feld sqln des SQLDA-Bereichs wird mit der numvar<br />

initialisiert. Den Indikatorvariablen wird kein Speicherplatz zugewiesen; die<br />

Indikatorzeiger werden auf den Null-Zeiger gesetzt. Ein Null-Zeiger wird<br />

zurückgegeben, falls kein Speicher zugewiesen werden konnte.<br />

253


Referenz der Bibliotheksfunktion<br />

db_backup-Funktion<br />

Prototyp<br />

Zugriffs-<br />

Berechtigung<br />

Beschreibung<br />

254<br />

void db_backup(<br />

SQLCA * sqlca,<br />

int op,<br />

int file_num,<br />

unsigned long page_num,<br />

SQLDA * sqlda);<br />

Um die Sicherungsfunktionen benutzen zu können, müssen Sie mit einer<br />

Benutzer-ID mit DBA-Berechtigung oder mit REMOTE DBA-Berechtigung<br />

(SQL Remote) verbunden sein.<br />

BACKUP-Anweisung wird empfohlen<br />

Obwohl diese Funktion ein Möglichkeit bietet, einer Anwendung<br />

Sicherungsfunktionen hinzuzufügen, wird empfohlen, diese Aufgabe über<br />

die BACKUP-Anweisung zu auszuführen. Weitere Hinweise finden Sie<br />

unter "BACKUP-Anweisung" auf Seite 268 der Dokumentation ASA<br />

SQL-Referenzhandbuch.<br />

Welche Aktion ausgeführt wird, hängt vom Wert des Parameters op ab:<br />

♦ DB_BACKUP_START Muß aufgerufen werden, bevor eine Sicherung<br />

beginnen kann. Zu einem Zeitpunkt kann immer nur eine Sicherung auf<br />

einem gegebenen Datenbankserver laufen. Datenbank-Checkpoints sind<br />

deaktiviert, bis die Sicherung vollständig ist (db_backup wird mit dem<br />

Wert op <strong>für</strong> DB_BACKUP_END aufgerufen). Kann die Sicherung nicht<br />

starten, wird der SQLCODE mit SQLE_BACKUP_NOT_STARTED<br />

belegt. Andernfalls wird das Feld SQLCOUNT des sqlca mit der Größe<br />

der Datenbankseiten belegt. (Sicherungen werden Seite <strong>für</strong> Seite<br />

durchgeführt.)<br />

Die Parameter file_num, page_num und sqlda werden nicht beachtet.<br />

♦ DB_BACKUP_OPEN_FILE Öffnet die mit file_num angegebene<br />

Datenbankdatei, sodass Seiten der angegebenen Datei mit<br />

DB_BACKUP_READ_PAGE gesichert werden können. Gültige<br />

Dateinummern sind 0 (Null) bis DB_BACKUP_MAX_FILE <strong>für</strong> die<br />

Stamm-Datenbankdateien, DB_BACKUP_TRANS_LOG_FILE <strong>für</strong> die<br />

Transaktionslogdatei und DB_BACKUP_WRITE_FILE <strong>für</strong> die<br />

Datenbank-Write-Datei, falls sie existiert. Falls die angegebene Datei<br />

nicht existiert, wird SQLCODE mit SQLE_NOTFOUND belegt.<br />

Andernfalls enthält SQLCOUNT die Anzahl der Seiten in der Datei,<br />

SQLIOESTIMATE enthält einen 32-Bit-Wert (POSIX time_t), der die<br />

Zeit angibt, zu der die Datenbankdatei erstellt wurde, der Name der<br />

Betriebssystemdatei befindet sich im Feld sqlerrmc des SQLCA-<br />

Bereichs.


Kapitel 6 Programmieren mit Embedded SQL<br />

Die Parameter page_num und sqlda werden nicht beachtet.<br />

♦ DB_BACKUP_READ_PAGE Eine Seite der Datenbankdatei lesen, die<br />

mit file_num angegeben wird. page_num sollte einen Wert von 0 bis 1<br />

weniger als die Seitenanzahl haben, die von einem erfolgreichen Aufruf<br />

von db_backup mit dem Vorgang DB_BACKUP_OPEN_FILE in<br />

SQLCOUNT zurückgegeben wurde. Andernfalls wird SQLCODE mit<br />

SQLE_NOTFOUND belegt. Der sqlda-Deskriptor sollte mit einer<br />

Variablen vom Typ DT_BINARY eingerichtet werden, die auf einen<br />

Puffer zeigt. Der Puffer sollte groß genug sein, um Binärdaten in der<br />

Größe zu speichern, wie sie im Feld SQLCOUNT beim Aufruf von<br />

db_backup mit dem Vorgang DB_BACKUP_START zurückgegeben<br />

werden.<br />

Die Daten in DT_BINARY enthalten eine 2 Byte lange Längenangabe,<br />

gefolgt von den eigentlichen Binärdaten, sodass der Puffer mindestens 2<br />

Byte länger sein muss als die Seitengröße.<br />

Die Anwendung muss den Puffer speichern<br />

Dieser Aufruf erzeugt eine der angegebenen Datenbankseiten im<br />

Puffer, aber es bleibt der Anwendung überlassen, den Pufferinhalt auf<br />

einem Sicherungsdatenträger zu speichern.<br />

♦ DB_BACKUP_READ_RENAME_LOG Die gleiche Aktion wie bei<br />

DB_BACKUP_READ_PAGE, außer dass nach der letzten Seite das<br />

Transaktionslog zurückgegeben wurde; der Datenbankserver das<br />

bestehende Transaktionslog umbenennt und ein ein neues startet<br />

Falls der Datenbankserver nicht in der Lage ist, das Log zu diesem<br />

Zeitpunkt umzubenennen (z.B. können in Datenbanken der Version 7.x<br />

oder älter unvollständige Transaktionen auftreten) tritt der Fehler<br />

SQLE_BACKUP_CANNOT_RENAME_LOG_YET auf. In diesem Fall<br />

benutzen Sie nicht die zurückgegebene Seite, sondern erneuern Sie die<br />

Anforderung, bis Sie SQLE_NOERROR erhalten und schreiben Sie<br />

dann die Seite. Fahren Sie mit dem Lesen der Seiten fort, bis Sie den<br />

Zustand SQLE_NOTFOUND erhalten.<br />

Die Fehlermeldung<br />

SQLE_BACKUP_CANNOT_RENAME_LOG_YET kann mehrere<br />

Male und <strong>für</strong> mehrere Seiten auftreten. In Ihrer Wiederholungsschleife<br />

sollten Sie eine Verzögerung einbauen, um den Server nicht mit zu<br />

vielen Anforderungen zu verlangsamen.<br />

Erhalten Sie die Bedingung SQLE_NOTFOUND, wurde das<br />

Transaktionslog erfolgreich gesichert und die Datei umbenannt. Der<br />

Name der alten Transaktiondatei wird im Feld sqlerrmc des SQLCA-<br />

Bereichs zurückgegeben.<br />

255


Referenz der Bibliotheksfunktion<br />

256<br />

Den Wert von sqlda->sqlvar[0].sqlind sollten Sie überprüfen,<br />

nachdem Sie db_backup aufgerufen haben. Ist dieser Wert größer als 0<br />

(Null), wurde die letzte Logseite geschrieben und die Logdatei wurde<br />

umbenannt. Der neue Name befindet sich nach wie vor in<br />

sqlca.sqlerrmc, aber der Wert von SQLCODE ist SQLE_NOERROR.<br />

Danach sollten Sie db_backup nicht nochmals aufrufen, außer Sie<br />

möchten Dateien schließen und die Sicherung beenden. Falls Sie das<br />

tun, erhalten Sie eine zweite Kopie Ihrer gesicherten Logdatei und<br />

SQLE_NOTFOUND.<br />

♦ DB_BACKUP_CLOSE_FILE Muss aufgerufen werden, wenn die<br />

Bearbeitung einer Datei abgeschlossen ist, um die mit file_num<br />

angegebene Datenbankdatei zu schließen.<br />

Die Parameter page_num und sqlda werden nicht beachtet.<br />

♦ DB_BACKUP_END Muß beim Beenden der Sicherung aufgerufen<br />

werden. Keine andere Sicherung kann beginnen, bevor die letzte beendet<br />

wurde. Checkpoints werden wieder aktiviert.<br />

Die Parameter file_num, page_num und sqlda werden nicht beachtet.<br />

Das Programm dbbackup verwendet folgenden Algorithmus. Beachten Sie,<br />

dass es sich nicht um C-Code handelt, und dass keine Fehlerüberprüfung<br />

enthalten ist.<br />

db_backup( ... DB_BACKUP_START ... )<br />

allocate page buffer based on page size in SQLCODE<br />

sqlda = alloc_sqlda( 1 )<br />

sqlda->sqld = 1;<br />

sqlda->sqlvar[0].sqltype = DT_BINARY<br />

sqlda->sqlvar[0].sqldata = allocated buffer<br />

for file_num = 0 to DB_BACKUP_MAX_FILE<br />

db_backup( ... DB_BACKUP_OPEN_FILE, file_num ... )<br />

if SQLCODE == SQLE_NO_ERROR<br />

/* Datei vorhanden */<br />

num_pages = SQLCOUNT<br />

file_time = SQLE_IO_ESTIMATE<br />

open backup file with name from sqlca.sqlerrmc<br />

for page_num = 0 to num_pages - 1<br />

db_backup( ... DB_BACKUP_READ_PAGE,<br />

file_num, page_num, sqlda )<br />

write page buffer out to backup file<br />

next page_num<br />

close backup file<br />

db_backup( ... DB_BACKUP_CLOSE_FILE, file_num ... )<br />

end if<br />

next file_num<br />

backup up file DB_BACKUP_WRITE_FILE as above<br />

backup up file DB_BACKUP_TRANS_LOG_FILE as above<br />

free page buffer


db_cancel_request-Funktion<br />

Prototyp<br />

Beschreibung<br />

db_delete_file-Funktion<br />

Prototyp<br />

Zugriffs-<br />

Berechtigung<br />

Beschreibung<br />

Kapitel 6 Programmieren mit Embedded SQL<br />

db_backup( ... DB_BACKUP_END ... )<br />

int db_cancel_request( SQLCA *sqlca );<br />

Diese Funktion bricht die gerade aktive Anforderung an den<br />

Datenbankserver ab. Sie überprüft, ob die Anforderung an den<br />

Datenbankserver aktiv ist, bevor sie die Abbruchsanforderung sendet. Wenn<br />

die Funktion 1 zurückgibt, wurde die Abbruchsanforderung gesendet; wenn<br />

sie 0 zurückgibt, wurde keine Anforderung gesendet.<br />

Ein Rückgabewert ungleich 0 bedeutet nicht, dass die Anforderung<br />

abgebrochen wurde. Es gibt einige kritische zeitliche Überschneidungen,<br />

wenn sich die Abbruchsanforderung und die Antwort von der Datenbank<br />

oder vom Server überschneiden. In diesen Fällen findet einfach kein<br />

Abbruch statt, obwohl die Funktion weiterhin TRUE zurückgibt.<br />

Die Funktion db_cancel_request kann asynchron aufgerufen werden. Diese<br />

und die Funktion db_is_working sind die einzigen Funktionen in der<br />

Schnittstellenbibliothek der Datenbank, die asynchron aufgerufen werden<br />

können, weil sie einen SQLCA-Bereich benutzen, der schon von einer<br />

anderen Anforderung verwendet werden könnte.<br />

Wenn Sie eine Anforderung abbrechen, die eine Cursoroperation durchführt,<br />

ist die Position des Cursors unbestimmt. Sie müssen den Cursor entweder<br />

mit seiner absoluten Position festlegen oder ihn nach dem Abbrechen<br />

schließen.<br />

void db_delete_file(<br />

SQLCA * sqlca,<br />

char * filename );<br />

Um die Sicherungsfunktionen benutzen zu können, müssen Sie mit einer<br />

Benutzer-ID mit DBA-Berechtigung oder mit REMOTE DBA-Berechtigung<br />

(SQL Remote) verbunden sein.<br />

Die Funktion db_delete_file fordert vom Datenbankserver das Löschen der<br />

Datei namens filename an. Diese Funktion kann nach dem Sichern und<br />

Umbenennen des Transaktionslogs verwendet werden (siehe oben,<br />

DB_BACKUP_READ_RENAME_LOG in "db_backup-Funktion" auf<br />

Seite 254), um das alte Transaktionslog zu löschen. Sie müssen mit einer<br />

Benutzer-ID mit DBA-Berechtigung verbunden sein.<br />

257


Referenz der Bibliotheksfunktion<br />

db_find_engine-Funktion<br />

Prototyp<br />

Beschreibung<br />

db_fini-Funktion<br />

Prototyp<br />

Beschreibung<br />

Siehe auch:<br />

db_get_property-Funktion<br />

Prototyp<br />

258<br />

unsigned short db_find_engine(<br />

SQLCA *sqlca,<br />

char *name );<br />

Diese Funktion gibt eine kurze Ganzzahl ohne Vorzeichen zurück, die<br />

Statusinformationen über den Datenbankserver namens name anzeigt. Falls<br />

kein Server mit dem angegebenen Namen gefunden werden kann, ist der<br />

Rückgabewert 0 (Null). Ein Rückgabewert ungleich 0 bedeutet, dass der<br />

angegebene Server gerade läuft.<br />

Jedes Bit des Rückgabewert enthält eine spezifische Information. Die<br />

Header-Datei sqldef.h definiert Konstanten <strong>für</strong> diese Informationen. Falls ein<br />

Null-Zeiger <strong>für</strong> name angegeben wird, gibt die Funktion Information über<br />

die voreingestellte Datenbank zurück.<br />

unsigned short db_fini( *sqlca );<br />

Diese Funktion gibt Ressourcen frei, die von der Datenbankschnittstelle<br />

benutzt wurden. Nachdem Sie db_fini aufgerufen haben, sind keine weiteren<br />

Bibliotheksaufrufe und keine weiteren Embedded SQL-Befehle erlaubt.<br />

Wenn während der Verarbeitung ein Fehler auftritt, wird der Fehlercode in<br />

SQLCA eingestellt und die Funktion gibt 0 zurück. Wenn es keine Fehler<br />

gegeben hat, wird ein Nicht-Nullwert zurückgegeben.<br />

Sie müssen db_fini einmal <strong>für</strong> jeden benutzten SQLCA-Bereich aufrufen.<br />

Vorsicht<br />

Wird unter NetWare nicht db_fini <strong>für</strong> jedes db_init aufgerufen, kann das<br />

den Datenbankserver und den NetWare-Dateiserver zum Absturz bringen.<br />

Hinweise über die Verwendung von db_fini in UltraLite-Anwendungen<br />

finden Sie unter "db_fini-Funktion" auf Seite 247 der Dokumentation<br />

UltraLite Benutzerhandbuch.<br />

unsigned int db_get_property(<br />

SQLCA * sqlca,<br />

a_db_property property,<br />

char * value_buffer,<br />

int value_buffer_size );


Beschreibung<br />

Siehe auch:<br />

db_init-Funktion<br />

Prototyp<br />

Beschreibung<br />

Kapitel 6 Programmieren mit Embedded SQL<br />

Diese Funktion wird verwendet, um die Adressen der Server zu erhalten, zu<br />

denen derzeit eine Verbindung besteht. Sie wird vom Dienstprogramm<br />

dbping verwendet, um die Serveradresse auszudrucken.<br />

Die Funktion kann auch benutzt werden, um den Wert der<br />

Datenbankeigenschaften zu erhalten. Datenbankeigenschaften können auch<br />

auf eine schnittstellenunabhängige Weise abgerufen werden, nämlich durch<br />

Ausführen einer SELECT-Anweisung, siehe "Eigenschaften von<br />

Datenbanken" auf Seite 690 der Dokumentation ASA<br />

Datenbankadministration.<br />

Es gelten die folgenden Argumente:<br />

♦ a_db_property Ein enum mit dem Wert<br />

DB_PROP_SERVER_ADDRESS. DB_PROP_SERVER_ADDRESS<br />

ruft die Servernetzwerkadresse der derzeitigen Verbindung als<br />

ausdruckbare Zeichenfolge zurück. Gemeinsamer Speicher und<br />

NamedPipes-Protokolle geben immer die leere Zeichenfolge <strong>für</strong> die<br />

Adresse zurück. TCP/IP- und SPX-Protokolle geben nicht-leere<br />

Zeichenfolgeadressen zurück.<br />

♦ value_buffer Dieses Argument wird mit dem Eigenschaftswert als<br />

Zeichenfolge mit einer abschließenden Null gefüllt.<br />

♦ value_buffer_size Die maximale Länge der Zeichenfolge value_buffer,<br />

einschließlich des abschließenden Nullzeichens.<br />

"Eigenschaften von Datenbanken" auf Seite 690 der Dokumentation ASA<br />

Datenbankadministration<br />

unsigned short db_init( SQLCA *sqlca );<br />

Diese Funktion initialisiert die Schnittstellenbibliothek der Datenbank. Diese<br />

Funktion muss aufgerufen werden, bevor ein anderer Bibliotheksaufruf<br />

erfolgen kann und bevor ein Embedded SQL-Befehl ausgeführt wird. Die<br />

Ressourcen, die die Schnittstellenbibliothek <strong>für</strong> Ihr Programm braucht,<br />

werden bei diesem Aufruf zugewiesen und initialisiert.<br />

Geben Sie mit db_fini am Ende Ihres Programms die Ressourcen frei. Falls<br />

während der Prozessverarbeitung Fehler auftreten, werden sie im SQLCA-<br />

Bereich zurückgegeben und der Rückgabewert ist 0 (Null). Treten keine<br />

Fehler auf, ist der Rückgabewert ungleich 0 (Null) und Sie können beginnen,<br />

Embedded SQL-Befehle und -Funktionen zu benutzen.<br />

259


Referenz der Bibliotheksfunktion<br />

Siehe auch:<br />

db_is_working-Funktion<br />

Prototyp<br />

Beschreibung<br />

db_locate_servers-Funktion<br />

Prototyp<br />

Beschreibung<br />

260<br />

In den meisten Fällen sollte diese Funktion nur einmal aufgerufen werden,<br />

um die Adresse der globalen Variable sqlca weiterzugeben, die in der<br />

Header-Datei sqlca.h definiert ist. Falls Sie mit Embedded SQL eine DLL<br />

oder eine Anwendung schreiben, die mehrfache Threads hat, rufen Sie<br />

db_init einmal <strong>für</strong> jeden SQLCA-Bereich auf, der benutzt wird.<br />

$ Weitere Hinweise finden Sie unter "SQLCA-Verwaltung <strong>für</strong> Code mit<br />

mehreren Threads oder "reentrant"-Code" auf Seite 211.<br />

Vorsicht<br />

Wenn Sie unter NetWare db_fini nicht <strong>für</strong> jedes db_init aufrufen, kann<br />

dies einen Absturz des Datenbankservers und des NetWare-Dateiservers<br />

verursachen.<br />

Hinweise über die Verwendung von db_init in UltraLite-Anwendungen<br />

finden Sie unter "db_init-Funktion" auf Seite 247 der Dokumentation<br />

UltraLite Benutzerhandbuch.<br />

unsigned db_is_working( SQLCA *sqlca );<br />

Diese Funktion gibt 1 zurück, falls eine Datenbankanforderung Ihrer<br />

Anwendung läuft, die den angegebenen sqlca benutzt. Sie gibt 0 (Null)<br />

zurück, falls keine Anwendung läuft, die den angegebenen sqlca benutzt.<br />

Diese Funktion kann asynchron aufgerufen werden. Diese und die Funktion<br />

db_cancel_request sind die einzigen Funktionen in der<br />

Schnittstellenbibliothek der Datenbank, die asynchron aufgerufen werden<br />

können, weil sie einen SQLCA-Bereich benutzen, der schon von einer<br />

anderen Anforderung verwendet werden könnte.<br />

unsigned int db_locate_servers(<br />

SQLCA *sqlca,<br />

SQL_CALLBACK_PARM callback_address,<br />

void *callback_user_data );<br />

Bietet Zugriff auf die vom Befehlszeilen-Dienstprogramm dblocate<br />

angezeigten Daten und listet alle <strong>Adaptive</strong> Server <strong>Anywhere</strong>-<br />

Datenbankserver mit TCP/IP-Anschluss im lokalen Netzwerk auf.<br />

Die Callback-Funktion muss folgende Syntax haben:


int (*)( SQLCA *sqlca,<br />

a_server_address *server_addr,<br />

void *callback_user_data );<br />

db_register_a_callback-Funktion<br />

Prototyp<br />

Beschreibung<br />

Kapitel 6 Programmieren mit Embedded SQL<br />

Die Callback-Funktion wird <strong>für</strong> jeden gefundenen Server ausgeführt. Wenn<br />

die Callback-Funktion den Wert 0 zurückgibt, stoppt db_locate_servers die<br />

Suche nach Servern.<br />

Die an die Callback-Funktion übergebenen Parameter sqlca und<br />

callback_user_data sind dieselben Parameter, die an db_locate_servers<br />

übergeben werden. Der zweite Parameter ist ein Zeiger auf eine<br />

a_server_address-Struktur. a_server_address wird mit folgender<br />

Definition in sqlca.h festgelegt:<br />

typedef struct a_server_address {<br />

a_SQL_uint32 port_type;<br />

a_SQL_uint32 port_num;<br />

char *name;<br />

char *address;<br />

} a_server_address;<br />

♦ port_type Ist hier immer PORT_TYPE_TCP (laut Definition 6 in<br />

sqlca.h)<br />

♦ port_num Ist die TCP-Portnummer, die der Server abhört<br />

♦ name Zeigt auf einen Puffer, der den Servernamen enthält<br />

♦ address Zeigt auf einen Puffer, der die IP-Adresse des Servers enthält<br />

$ Weitere Hinweise finden Sie unter "Das Serverposition-<br />

Dienstprogramm" auf Seite 554 der Dokumentation ASA<br />

Datenbankadministration.<br />

void db_register_a_callback(<br />

SQLCA *sqlca,<br />

a_db_callback_index index,<br />

( SQL_CALLBACK_PARM ) callback );<br />

Diese Funktion registriert Callback-Funktionen:<br />

Falls Sie keine Callback-Funktion DB_CALLBACK_WAIT registrieren, ist<br />

die voreingestellte Reaktion, nichts zu tun. Ihre Anwendung ist blockiert,<br />

wartet auf die Antwort von der Datenbank und Windows zeigt den Cursor als<br />

Sanduhr an.<br />

Um einen Callback zu löschen, übergeben Sie einen Null-Zeiger als<br />

callback-Funktion.<br />

261


Referenz der Bibliotheksfunktion<br />

262<br />

Die folgenden Werte sind <strong>für</strong> den Parameter index erlaubt:<br />

♦ DB_CALLBACK_DEBUG_MESSAGE Die bereitgestellte Funktion wird<br />

<strong>für</strong> jede Fehlersuchmeldung einmal aufgerufen. Ihr wird eine auf Null<br />

endende Zeichenfolge übergeben, die den Text der Debug-Meldung<br />

enthält. Die Zeichenfolge enthält gewöhnlich eine Zeilenendmarke (\n)<br />

unmittelbar vor dem beendenden Nullwertzeichen. Der Prototyp der<br />

Callback-Funktion lautet folgendermaßen:<br />

void SQL_CALLBACK debug_message_callback(<br />

SQLCA *sqlca,<br />

char * message_string );<br />

♦ DB_CALLBACK_START Der Callback-Prototyp sieht wie folgt aus:<br />

void SQL_CALLBACK start_callback( SQLCA *sqlca );<br />

Diese Funktion wird unmittelbar vor dem Absenden einer<br />

Datenbankanforderung an den Server aufgerufen.<br />

DB_CALLBACK_START wird nur unter Windows verwendet.<br />

♦ DB_CALLBACK_FINISH Der Callback-Prototyp sieht wie folgt aus:<br />

void SQL_CALLBACK finish_callback( SQLCA * sqlca );<br />

Diese Funktion wird aufgerufen, nachdem die Antwort auf eine<br />

Datenbankanforderung von der Schnittstellen-DLL empfangen wurde.<br />

DB_CALLBACK_FINISH wird nur unter Windows-Betriebssystemen<br />

verwendet.<br />

♦ DB_CALLBACK_CONN_DROPPED Die Syntax sieht wie folgt aus:<br />

void SQL_CALLBACK conn_dropped_callback (<br />

SQLCA *sqlca,<br />

char *conn_name );<br />

Diese Funktion wird aufgerufen, wenn der Datenbankserver im Begriff<br />

ist, die Verbindung aufgrund einer Zeitüberschreitung zu verlieren, von<br />

einer DROP CONNECTION-Anweisung oder weil der Server<br />

heruntergefahren wird. Der Verbindungsname conn_name wird<br />

übergeben, sodass Sie zwischen den Verbindungen unterscheiden<br />

können. Wenn die Verbindung nicht benannt war, hat sie den Wert<br />

NULL.<br />

♦ DB_CALLBACK_WAIT Der Callback-Prototyp sieht wie folgt aus:<br />

void SQL_CALLBACK wait_callback( SQLCA *sqlca );<br />

Diese Funktion wird wiederholt von der Schnittstellenbibliothek<br />

aufgerufen, während der Datenbankserver oder die Clientbibliothek mit<br />

dem Abarbeiten Ihrer Datenbankanforderung beschäftigt sind.<br />

So würden Sie diesen Callback registrieren:


db_start_database-Funktion<br />

Prototyp<br />

Argumente<br />

Kapitel 6 Programmieren mit Embedded SQL<br />

db_register_a_callback( &sqlca,<br />

DBCALLBACK_WAIT,<br />

(SQL_CALLBACK_PARM)&db_wait_request );<br />

♦ DB_CALLBACK_MESSAGE Diese Funktion ermöglicht es der<br />

Anwendung, Nachrichten vom Server zu verarbeiten, während sie eine<br />

Anforderung abarbeitet.<br />

Der Callback-Prototyp sieht wie folgt aus:<br />

void SQL_CALLBACK message_callback(<br />

SQLCA* sqlca,<br />

unsigned short msg_type,<br />

an_SQL_code code,<br />

unsigned length,<br />

char* msg<br />

);<br />

Der msg_type-Parameter gibt an, wie wichtig die Nachricht ist und<br />

mehrere unterschiedliche Nachrichtentypen können unterschiedlich<br />

behandelt werden. Die möglichen Nachrichtentypen sind<br />

MESSAGE_TYPE_INFO, MESSAGE_TYPE_WARNING,<br />

MESSAGE_TYPE_ACTION und MESSAGE_TYPE_STATUS. Diese<br />

Konstanten sind in sqldef.h definiert. Das code-Feld ist ein<br />

Identifizierer. Das Längen-Feld gibt an, wie lang die Nachricht ist. Die<br />

Meldung ist nicht mit Nullwert abgeschlossen.<br />

Zum Beispiel zeigt die Interactive SQL Callback-Funktion STATUSund<br />

INFO-Nachrichten in einem Nachrichtenfenster an, während<br />

Nachrichten vom Typ ACTION und WARNING in einem Dialogfenster<br />

erscheinen. Wenn eine Anwendung diese Callback-Funktion nicht<br />

registriert, gibt es eine Standard-Callback-Funktion, die alle Nachrichten<br />

in die Serverlogdatei schreibt (wenn der Debug-Modus eingestellt und<br />

eine Logdatei angegeben ist). Zusätzlich werden Nachrichten vom Typ<br />

MESSAGE_TYPE_WARNING und MESSAGE_TYPE_ACTION<br />

betriebssystemabhängig auffälliger dargestellt.<br />

unsigned int db_start_database( SQLCA * sqlca, char * parms );<br />

sqlca Ein Zeiger auf eine SQLCA-Struktur. Hinweise dazu finden Sie unter<br />

"SQL-Kommunikationsbereich (SQLCA)" auf Seite 208.<br />

parms Eine auf NULL endende Zeichenfolge, die eine Semikolon-getrennte<br />

Liste mit Parametereinstellungen enhält, und zwar in der Form<br />

STICHWORT=Wert. Zum Beispiel:<br />

"UID=DBA;PWD=SQL;DBF=c:\\db\\MeineDatenbank.db"<br />

263


Referenz der Bibliotheksfunktion<br />

Beschreibung<br />

db_start_engine-Funktion<br />

Prototyp<br />

Argumente<br />

Beschreibung<br />

264<br />

$ Eine Liste der Verbindungsparameter finden Sie unter<br />

"Verbindungsparameter" auf Seite 182 der Dokumentation ASA<br />

Datenbankadministration.<br />

Diese Funktion startet eine Datenbank auf einem vorhandenen Server, falls<br />

die Datenbank nicht bereits läuft. Die Schritte, die zum Starten einer<br />

Datenbank ausgeführt werden, sind unter "Personal Server starten" auf<br />

Seite 88 der Dokumentation ASA Datenbankadministration beschrieben.<br />

Der Rückgabewert ist wahr, falls die Datenbank bereits lief oder erfolgreich<br />

gestartet werden konnte. Informationen über Fehler werden im SQLCA-<br />

Bereich zurückgegeben.<br />

Falls eine Benutzer-ID und ein Kennwort in den Parametern übergeben<br />

wurden, werden sie ignoriert.<br />

$ Die Berechtigung zum Starten und Stoppen einer Datenbank wird in der<br />

Serverbefehlszeile gesetzt. Weitere Hinweise finden Sie unter "Der<br />

Datenbankserver" auf Seite 134 der Dokumentation ASA<br />

Datenbankadministration.<br />

unsigned int db_start_engine( SQLCA * sqlca, char * parms );<br />

sqlca Ein Zeiger auf eine SQLCA-Struktur. Hinweise dazu finden Sie unter<br />

"SQL-Kommunikationsbereich (SQLCA)" auf Seite 208.<br />

parms Eine auf NULL endende Zeichenfolge, die eine durch Semikolons<br />

getrennte Liste mit Parametereinstellungen enhält, und zwar in der Form<br />

STICHWORT=Wert. Zum Beispiel:<br />

"UID=DBA;PWD=SQL;DBF=c:\\db\\MeineDatenbank.db"<br />

$ Eine Liste der Verbindungsparameter finden Sie unter<br />

"Verbindungsparameter" auf Seite 182 der Dokumentation ASA<br />

Datenbankadministration.<br />

Mit dieser Funktion wird der Datenbankserver gestartet, falls er nicht bereits<br />

läuft. Die Schritte, die diese Funktion ausführt, sind dieselben, wie sie unter<br />

"Personal Server starten" auf Seite 88 der Dokumentation ASA<br />

Datenbankadministration beschrieben sind.<br />

Der Rückgabewert ist gültig, falls der Datenbankserver gefunden wurde oder<br />

falls er erfolgreich gestartet werden konnte. Informationen über Fehler<br />

werden im SQLCA-Bereich zurückgegeben.


Kapitel 6 Programmieren mit Embedded SQL<br />

Der folgende Aufruf von db_start_engine startet den Datenbankserver und<br />

nennt ihn asademo, er lädt nicht die Datenbank, trotz des DBF-<br />

Verbindungsparameters:<br />

db_start_engine( &sqlca, "DBF=c:\\asa8\\asademo.db;<br />

Start=dbeng8" );<br />

Falls Sie nach dem Server auch eine Datenbank starten wollen, fügen Sie die<br />

Datenbankdatei in den Verbindungsparameter START ein:<br />

db_start_engine( &sqlca,"ENG=eng_name;START=dbeng8<br />

c:\\asa\\asademo.db" );<br />

Dieser Aufruf startet den Server, nennt ihn eng_name und startet die<br />

Datenbank asademo auf diesem Server.<br />

Die Funktion db_start_engine versucht, eine Verbindung zu einem Server<br />

herzustellen, bevor einer gestartet wird, um zu verhindern, dass ein Server<br />

gestartet wird, der bereits läuft.<br />

Der Verbindungsparameter FORCESTART wird nur von der Funktion<br />

db_start_engine verwendet. Wenn er auf YES gesetzt wird, wird nicht<br />

versucht, eine Verbindung zu einem Server herzustellen, bevor einer<br />

gestartet wird. Dadurch kann das folgende Befehlspaar wie erwartet arbeiten:<br />

1 Starten eines Datenbankservers mit dem Namen server_1:<br />

start dbeng8 -n server_1 asademo.db<br />

2 Der Start eines neuen Servers wird erzwungen und es wird eine<br />

Verbindung zu ihm hergestellt:<br />

db_start_engine( &sqlda, "START=dbeng8 -n server_2 asademo.db;ForceStart=YES" )<br />

db_stop_database-Funktion<br />

Prototyp<br />

Argumente<br />

Wenn FORCESTART nicht oder ohne ENG-Parameter verwendet wurde,<br />

hätte der zweite Befehl versucht, eine Verbindung zu server_1 herzustellen.<br />

Der Servername wird von der Funktion db_start_engine nicht vom<br />

Parameter des START-Parameters ermittelt.<br />

unsigned int db_stop_database( SQLCA * sqlca, char * parms );<br />

sqlca Ein Zeiger auf eine SQLCA-Struktur. Hinweise dazu finden Sie unter<br />

"SQL-Kommunikationsbereich (SQLCA)" auf Seite 208.<br />

parms Eine auf NULL endende Zeichenfolge, die eine durch Semikolons<br />

getrennte Liste mit Parametereinstellungen enhält, und zwar in der Form<br />

STICHWORT=Wert. Zum Beispiel:<br />

"UID=DBA;PWD=SQL;DBF=c:\\db\\MeineDatenbank.db"<br />

265


Referenz der Bibliotheksfunktion<br />

Beschreibung<br />

db_stop_engine-Funktion<br />

Prototyp<br />

Argumente<br />

Beschreibung<br />

266<br />

$ Eine Liste der Verbindungsparameter finden Sie unter<br />

"Verbindungsparameter" auf Seite 182 der Dokumentation ASA<br />

Datenbankadministration.<br />

Diese Funktion beendet die Datenbank namens DatabaseName auf dem<br />

Server namens EngineName. Falls der EngineName nicht angegeben ist,<br />

bezieht sich die Funktion auf den voreingestellten Server.<br />

Als Voreinstellung beendet diese Funktion eine Datenbank nicht, solange<br />

noch eine Verbindung zu dieser Datenbank offen ist. Falls Unconditional<br />

mit yes belegt ist, wird die Datenbank beendet, auch wenn noch<br />

Verbindungen offen sind.<br />

Ist der Rückgabewert TRUE, sind keine Fehler aufgetreten.<br />

$ Die Berechtigung zum Starten und Stoppen einer Datenbank wird in der<br />

Serverbefehlszeile gesetzt. Weitere Hinweise finden Sie unter "Der<br />

Datenbankserver" auf Seite 134 der Dokumentation ASA<br />

Datenbankadministration.<br />

unsigned int db_stop_engine( SQLCA * sqlca, char * parms );<br />

sqlca Ein Zeiger auf eine SQLCA-Struktur. Hinweise dazu finden Sie unter<br />

"SQL-Kommunikationsbereich (SQLCA)" auf Seite 208.<br />

parms Eine auf NULL endende Zeichenfolge, die eine durch Semikolons<br />

getrennte Liste mit Parametereinstellungen enhält, und zwar in der Form<br />

STICHWORT=Wert. Zum Beispiel:<br />

"UID=DBA;PWD=SQL;DBF=c:\\db\\MeineDatenbank.db"<br />

$ Eine Liste der Verbindungsparameter finden Sie unter<br />

"Verbindungsparameter" auf Seite 182 der Dokumentation ASA<br />

Datenbankadministration.<br />

Diese Funktion fährt den Datenbankserver herunter. Folgende Schritte<br />

werden von dieser Funktion ausgeführt:<br />

♦ Sie sucht den Datenbankserver, dessen Name dem Wert des Parameters<br />

EngineName entspricht. Falls EngineName nicht angegeben wurde,<br />

sucht sie nach dem voreingestellten lokalen Datenbankserver.<br />

♦ Falls kein passender Server gefunden wird, schlägt die Funktion fehl.<br />

♦ Die Funktion sendet eine Anforderung an den Server, alle Datenbanken<br />

zu finden und zu beenden.<br />

♦ Sie entlädt den Datenbankserver.


db_string_connect-Funktion<br />

Prototyp<br />

Argumente<br />

Beschreibung<br />

db_string_disconnect-Funktion<br />

Prototyp<br />

Kapitel 6 Programmieren mit Embedded SQL<br />

Als Voreinstellung beendet diese Funktion einen Datenbankserver nicht,<br />

solange noch eine Verbindung zu dieser Datenbank offen ist. Falls<br />

Unconditional mit yes belegt ist, wird der Datenbankserver beendet, auch<br />

wenn noch Verbindungen offen sind.<br />

Ein C-Programm kann diese Funktion nutzen anstatt DBSTOP aufzurufen.<br />

Ist der Rückgabewert TRUE, sind keine Fehler aufgetreten.<br />

Die Verwendung von db_stop_engine hängt von den Berechtigungen ab, die<br />

mit der Serveroption -gk festgelegt wurden.<br />

$ Weitere Hinweise finden Sie unter "–gk-Serveroption" auf Seite 157<br />

der Dokumentation ASA Datenbankadministration.<br />

unsigned int db_string_connect( SQLCA * sqlca, char * parms );<br />

sqlca Ein Zeiger auf eine SQLCA-Struktur. Hinweise dazu finden Sie unter<br />

"SQL-Kommunikationsbereich (SQLCA)" auf Seite 208.<br />

parms Eine auf NULL endende Zeichenfolge, die eine durch Semikolons<br />

getrennte Liste mit Parametereinstellungen enhält, und zwar in der Form<br />

STICHWORT=Wert. Zum Beispiel:<br />

"UID=DBA;PWD=SQL;DBF=c:\\db\\MeineDatenbank.db"<br />

$ Eine Liste der Verbindungsparameter finden Sie unter<br />

"Verbindungsparameter" auf Seite 182 der Dokumentation ASA<br />

Datenbankadministration.<br />

Liefert zusätzliche Funktionalität über den Embedded SQL-Befehl<br />

CONNECT hinaus. Diese Funktion führt eine Verbindung aus, wobei der<br />

Algorithmus verwendet wird, der in "Fehlerbehandlung bei Verbindungen"<br />

auf Seite 82 der Dokumentation ASA Datenbankadministration beschrieben<br />

wird.<br />

Der Rückgabewert ist wahr (ungleich Null), falls eine Verbindung<br />

zustandekam, andernfalls ist er falsch (Null). Informationen über Fehler beim<br />

Starten des Servers, beim Starten der Datenbank oder beim<br />

Verbindungsaufbau werden im SQLCA-Bereich zurückgegeben.<br />

unsigned int db_string_disconnect( SQLCA * sqlca, char * parms );<br />

267


Referenz der Bibliotheksfunktion<br />

Argumente<br />

Beschreibung<br />

db_string_ping_server-Funktion<br />

Prototyp<br />

Beschreibung<br />

268<br />

sqlca Ein Zeiger auf eine SQLCA-Struktur. Hinweise dazu finden Sie unter<br />

"SQL-Kommunikationsbereich (SQLCA)" auf Seite 208.<br />

parms Eine auf NULL endende Zeichenfolge, die eine durch Semikolons<br />

getrennte Liste mit Parametereinstellungen enhält, und zwar in der Form<br />

STICHWORT=Wert. Zum Beispiel:<br />

"UID=DBA;PWD=SQL;DBF=c:\\db\\MeineDatenbank.db"<br />

$ Eine Liste der Verbindungsparameter finden Sie unter<br />

"Verbindungsparameter" auf Seite 182 der Dokumentation ASA<br />

Datenbankadministration.<br />

Diese Funktion trennt die Verbindung, die mit dem Parameter<br />

ConnectionName angegeben wurde. Alle anderen Parameter werden<br />

ignoriert.<br />

Falls der Parameter ConnectionName in der Zeichenfolge fehlt, wird die<br />

unbenannte Verbindung getrennt. Dies entspricht dem Embedded SQL-<br />

Befehl DISCONNECT. Der Boolesche Rückgabewert ist wahr, falls eine<br />

Verbindung erfolgreich getrennt wurde. Informationen über Fehler werden<br />

im SQLCA-Bereich zurückgegeben.<br />

Diese Funktion fährt die Datenbank herunter, falls sie mit dem Parameter<br />

AutoStop=yes gestartet wurde, und falls keine anderen Verbindungen mit<br />

der Datenbank bestehen. Es beendet auch den Serverbetrieb, falls der Server<br />

mit dem Parameter AutoStop=yes gestartet wurde, und falls keine weitere<br />

Datenbank mehr auf dem Server läuft.<br />

unsigned int db_string_ping_server(<br />

SQLCA * sqlca,<br />

char * connect_string,<br />

unsigned int connect_to_db );<br />

connect_string ist eine normale Verbindungszeichenfolge, die eventuell<br />

Server- und Datenbankinformationen enthält.<br />

Wenn connect_to_db nicht gleich Null (d.h. wahr) ist, dann versucht die<br />

Funktion eine Verbindung zu einer Datenbank auf einem Server herzustellen.<br />

Es wird nur ein Wert ungleich Null (d.h. wahr) zurückgegeben, wenn die<br />

Verbindungszeichenfolge ausreicht, um eine Verbindung zu einer benannten<br />

Datenbank auf dem benannten Server herzustellen.


fill_s_sqlda-Funktion<br />

Prototyp<br />

Beschreibung<br />

fill_sqlda-Funktion<br />

Prototyp<br />

Beschreibung<br />

free_filled_sqlda-Funktion<br />

Prototyp<br />

Beschreibung<br />

Kapitel 6 Programmieren mit Embedded SQL<br />

Wenn connect_to_db gleich Null ist, versucht die Funktion lediglich, die<br />

Position eines Servers zu ermitteln. Es wird nur ein Wert ungleich Null<br />

zurückgegeben, wenn die Verbindungszeichenfolge ausreicht, um die<br />

Position eines Servers zu ermitteln. Es wird nicht versucht, eine Verbindung<br />

zur Datenbank herzustellen.<br />

struct sqlda * fill_s_sqlda(<br />

struct sqlda * sqlda,<br />

unsigned int maxlen );<br />

Diese Funktion entspricht fill_sqlda,, abgesehen davon, dass sie alle<br />

Datentypen in sqlda in den Datentyp DT_STRING umwandelt. Es wird<br />

genügend Speicherplatz zugewiesen, um die eine Repräsentation des<br />

Datentyps als Zeichenfolge zu speichern, der ursprünglich im SQLDA-<br />

Bereich angegeben wurde, und zwar bis zu maximal maxlen Byte. Die<br />

Längenfelder im SQLDA-Bereich (sqllen) werden dementsprechend<br />

geändert. Die Funktion gibt im Erfolgsfall sqlda zurück und den Null-Zeiger,<br />

falls nicht genügend Speicherplatz zur Verfügung stand.<br />

struct sqlda * fill_sqlda( struct sqlda * sqlda );<br />

Diese Funktion weist alle Variable, die in den Deskriptoren von sqlda<br />

beschrieben sind, Speicherplatz zu und ordnet die Speicheradressen dem<br />

Feld sqldata des entsprechenden Deskriptors zu. Es wird genügend<br />

Speicherplatz zugewiesen <strong>für</strong> den im Deskriptor angegebenen Datenbanktyp<br />

und die angegebene Länge. Die Funktion gibt im Erfolgsfall sqlda zurück<br />

und den Null-Zeiger, falls nicht genügend Speicherplatz zur Verfügung<br />

stand.<br />

void free_filled_sqlda( struct sqlda * sqlda );<br />

Diese Funktion gibt den Speicherplatz frei, der einem sqldata-Zeiger und<br />

dem SQLDA-Bereich selbst zugewiesen war. Null-Zeiger werden nicht<br />

freigegeben.<br />

Durch Aufrufen dieser Funktion wird automatisch auch free_sqlda<br />

aufgerufen und alle Deskriptoren, die durch alloc_sqlda zugewiesen waren,<br />

freigegeben.<br />

269


Referenz der Bibliotheksfunktion<br />

free_sqlda-Funktion<br />

Prototyp<br />

Beschreibung<br />

free_sqlda_noind-Funktion<br />

Prototyp<br />

Beschreibung<br />

sql_needs_quotes-Funktion<br />

Prototyp<br />

Beschreibung<br />

270<br />

void free_sqlda( struct sqlda *sqlda );<br />

Diese Funktion gibt Speicherplatz, der diesem sqlda zugewiesen wurde, und<br />

den Speicherplatz der Indikatorvariablen, der in fill_sqlda zugewiesen<br />

wurde, frei. Sie sollten den von den sqldata -Zeigern referenzierten<br />

Speicherplatz nicht freigeben.<br />

void free_sqlda_noind( struct sqlda * sqlda );<br />

Diese Funktion gibt den Speicherplatz frei, der dem sqlda zugewiesen war.<br />

Sie sollten den von den sqldata -Zeigern referenzierten Speicherplatz nicht<br />

freigeben. Die Indikatorvariablen-Zeiger werden nicht beachtet.<br />

"Eigenschaften von Datenbanken" auf Seite 690 der Dokumentation ASA<br />

Datenbankadministration<br />

"Das Ping-Dienstprogramm" auf Seite 550 der Dokumentation ASA<br />

Datenbankadministration<br />

unsigned int sql_needs_quotes( SQLCA *sqlca, char *str );<br />

Diese Funktion gibt einen Booleschen Wert zurück, der anzeigt, ob eine<br />

Zeichenfolge mit Anführungszeichen eingeschlossen werden muss, wenn sie<br />

als SQL-Name (identifier) benutzt wird. Sie formuliert eine Anforderung an<br />

den Datenbankserver, um festzustellen, ob Anführungszeichen nötig sind.<br />

Die relevante Information wird im Feld sqlcode gespeichert.<br />

Wir unterscheiden drei unterschiedliche Kombinationen von Rückgabewert<br />

und Code:<br />

♦ return = FALSE, sqlcode = 0 In diesem Fall braucht die Zeichenfolge<br />

mit Sicherheit keine Anführungszeichen.<br />

♦ return = TRUE In diesem Fall ist sqlcode immer mit SQLE_WARNING<br />

belegt und die Zeichenfolge braucht mit Sicherheit Anführungszeichen.<br />

♦ return = FALSE Falls sqlcode mit etwas anderem als<br />

SQLE_WARNING belegt ist, ist das Testergebnis unklar.


sqlda_storage-Funktion<br />

Prototyp<br />

Beschreibung<br />

sqlda_string_length-Funktion<br />

Prototyp<br />

Beschreibung<br />

sqlerror_message-Funktion<br />

Prototyp<br />

Beschreibung<br />

Kapitel 6 Programmieren mit Embedded SQL<br />

unsigned long sqlda_storage( struct sqlda *sqlda, int varno );<br />

Die Funktion gibt die Speichergröße zurück, die erforderlich wäre, um jeden<br />

möglichen Wert der in sqlda->sqlvar[varno] beschriebenen Variable zu<br />

speichern.<br />

unsigned long sqlda_string_length( SQLDA *sqlda, int varno );<br />

Diese Funktion gibt die Länge zurück, die eine C-Zeichenfolge (Typ<br />

DT_STRING) haben müsste, um die Variable sqlda->sqlvar[varno]<br />

aufzunehmen (unabhängig vom Datentyp).<br />

char *sqlerror_message( SQLCA *sqlca, char * buffer, int max );<br />

Diese Funktion gibt einen Zeiger auf eine Zeichenfolge zurück, die eine<br />

Fehlermeldung enthält. Die Fehlermeldung enthält den Text <strong>für</strong> den<br />

Fehlercode im SQLCA-Bereich. Wurde kein Fehler gemeldet, wird ein Null-<br />

Zeiger zurückgegeben. Die Fehlermeldung wird in dem gelieferten Puffer<br />

gespeichert, falls erforderlich, gekürzt auf die Länge max.<br />

271


Befehlszusammenfassung <strong>für</strong> Embedded SQL<br />

Befehlszusammenfassung <strong>für</strong> Embedded SQL<br />

272<br />

Alle Embedded SQL Anweisungen beginnen mit EXEC SQL und<br />

enden mit einem Semikolon (;).<br />

Es gibt zwei Gruppen von Embedded SQL-Befehlen: Standard-SQL-Befehle<br />

werden benutzt, indem sie einfach in ein C-Programm geschrieben werden,<br />

eingeschlossen von EXEC SQL und einem Semikolon (;). CONNECT,<br />

DELETE, SELECT, SET und UPDATE haben zusätzliche Formate, die nur<br />

in Embedded SQL zur Verfügung stehen. Die zusätzlichen Formate gehören<br />

zur zweiten Gruppe der Embedded SQL-spezifischen Befehle.<br />

$ Eine Beschreibung der Standard-SQL-Befehle finden Sie unter "SQL-<br />

Anweisungen" auf Seite 217 der Dokumentation ASA SQL-<br />

Referenzhandbuch.<br />

Mehrere SQL-Befehle sind spezifisch <strong>für</strong> Embedded SQL und können nur<br />

innerhalb eines C-Programms benutzt werden.<br />

$ Weitere Hinweise über die Embedded SQL-Befehle finden Sie unter<br />

"SQL-Sprachelemente" auf Seite 3 der Dokumentation ASA SQL-<br />

Referenzhandbuch.<br />

Standardmäßige Datenbearbeitung und Datendefinitions-Anweisungen<br />

können von Embedded SQL-Anwendungen verwendet werden. Darüber<br />

hinaus gelten die folgenden Anweisungen speziell <strong>für</strong> die Programmierung<br />

von Embedded SQL:<br />

♦ ALLOCATE DESCRIPTOR Speicher <strong>für</strong> einen Deskriptor zuweisen<br />

$ Siehe "ALLOCATE DESCRIPTOR-Anweisung [ESQL]" auf<br />

Seite 222 der Dokumentation ASA SQL-Referenzhandbuch<br />

♦ CLOSE Einen Cursor schließen<br />

$ Siehe "CLOSE-Anweisung [ESQL] [GP]" auf Seite 285 der<br />

Dokumentation ASA SQL-Referenzhandbuch<br />

♦ CONNECT Mit der Datenbank verbinden<br />

$ Siehe "CONNECT-Anweisung [ESQL] [Interactive SQL]" auf<br />

Seite 292 der Dokumentation ASA SQL-Referenzhandbuch<br />

♦ DEALLOCATE DESCRIPTOR Speicher freigeben, der <strong>für</strong> einen<br />

Deskriptor reserviert war<br />

$ Siehe "DEALLOCATE DESCRIPTOR-Anweisung [ESQL]" auf<br />

Seite 410 der Dokumentation ASA SQL-Referenzhandbuch


Kapitel 6 Programmieren mit Embedded SQL<br />

♦ Deklarationsabschnitt Hostvariable <strong>für</strong> die Kommunikation mit der<br />

Datenbank deklarieren<br />

$ Siehe "Deklarationsabschnitt [ESQL]" auf Seite 421 der<br />

Dokumentation ASA SQL-Referenzhandbuch<br />

♦ DECLARE CURSOR Einen Cursor deklarieren<br />

$ Siehe "DECLARE CURSOR-Anweisung [ESQL] [GP]" auf<br />

Seite 412 der Dokumentation ASA SQL-Referenzhandbuch<br />

♦ DELETE (positioniert) Die Zeilen an der aktuellen Cursorposition<br />

löschen<br />

$ Siehe "DELETE-Anweisung (positionsbasiert) [ESQL] [GP]" auf<br />

Seite 424 der Dokumentation ASA SQL-Referenzhandbuch<br />

♦ DESCRIBE Die Hostvariable <strong>für</strong> eine bestimmte SQL-Anweisung<br />

deklarieren<br />

$ Siehe "DESCRIBE-Anweisung [ESQL]" auf Seite 426 der<br />

Dokumentation ASA SQL-Referenzhandbuch<br />

♦ DISCONNECT Die Verbindung mit dem Datenbankserver lösen<br />

$ Siehe "DISCONNECT-Anweisung [ESQL] [Interactive SQL]" auf<br />

Seite 430 der Dokumentation ASA SQL-Referenzhandbuch<br />

♦ DROP STATEMENT Ressourcen freigeben, die von einem Prepared-<br />

Statement benutzt werden<br />

$ Siehe "DROP STATEMENT-Anweisung [ESQL]" auf Seite 439<br />

der Dokumentation ASA SQL-Referenzhandbuch<br />

♦ EXECUTE Eine bestimmte SQL-Anweisung ausführen<br />

$ Siehe "EXECUTE-Anweisung [ESQL]" auf Seite 449 der<br />

Dokumentation ASA SQL-Referenzhandbuch<br />

♦ EXPLAIN Die Strategie zur Optimierung eines bestimmten Cursors<br />

erklären<br />

$ Siehe "EXPLAIN-Anweisung [ESQL]" auf Seite 456 der<br />

Dokumentation ASA SQL-Referenzhandbuch<br />

♦ FETCH Eine Zeile aus einem Cursor abrufen<br />

$ Siehe "FETCH-Anweisung [ESQL] [GP]" auf Seite 458 der<br />

Dokumentation ASA SQL-Referenzhandbuch<br />

♦ GET DATA Lange Werte aus einem Cursor abrufen<br />

$ Siehe "GET DATA-Anweisung [ESQL]" auf Seite 471 der<br />

Dokumentation ASA SQL-Referenzhandbuch<br />

273


Befehlszusammenfassung <strong>für</strong> Embedded SQL<br />

274<br />

♦ GET DESCRIPTOR Angaben zu einer Variablen in einen SQLDA-<br />

Bereich abrufen.<br />

$ Siehe "GET DESCRIPTOR-Anweisung [ESQL]" auf Seite 473 der<br />

Dokumentation ASA SQL-Referenzhandbuch<br />

♦ GET OPTION Die Einstellung einer bestimmten Datenbankoption<br />

abholen<br />

$ Siehe "GET OPTION-Anweisung [ESQL]" auf Seite 475 der<br />

Dokumentation ASA SQL-Referenzhandbuch<br />

♦ INCLUDE Eine Datei ins SQL-Preprocessing einschließen<br />

$ Siehe "INCLUDE-Anweisung [ESQL]" auf Seite 495 der<br />

Dokumentation ASA SQL-Referenzhandbuch<br />

♦ OPEN Einen Cursor öffnen<br />

$ Siehe "OPEN-Anweisung [ESQL] [GP]" auf Seite 523 der<br />

Dokumentation ASA SQL-Referenzhandbuch<br />

♦ PREPARE Eine bestimmte SQL-Anweisung vorbereiten<br />

$ Siehe "PREPARE-Anweisung [ESQL]" auf Seite 533 der<br />

Dokumentation ASA SQL-Referenzhandbuch<br />

♦ PUT Eine Zeile in einen Cursor einfügen<br />

$ Siehe "PUT-Anweisung [ESQL]" auf Seite 538 der Dokumentation<br />

ASA SQL-Referenzhandbuch<br />

♦ SET CONNECTION Die aktive Verbindung ändern<br />

$ Siehe "SET CONNECTION-Anweisung [Interactive SQL]" auf<br />

Seite 578 der Dokumentation ASA SQL-Referenzhandbuch<br />

♦ SET DESCRIPTOR Die Variablen in einem SQLDA-Bereich<br />

beschreiben und Daten im SQLDA-Bereich ablegen<br />

$ Siehe "SET DESCRIPTOR-Anweisung [ESQL]" auf Seite 579 der<br />

Dokumentation ASA SQL-Referenzhandbuch<br />

♦ SET SQLCA Einen anderen als den global voreingestellten SQLCA-<br />

Bereich benutzen<br />

$ Siehe "SET SQLCA-Anweisung [ESQL]" auf Seite 588 der<br />

Dokumentation ASA SQL-Referenzhandbuch<br />

♦ UPDATE (positioniert) Die Zeile an der aktuellen Cursorposition<br />

aktualisieren<br />

$ Siehe "UPDATE-Anweisung (positionsbasiert) [ESQL] [GP]" auf<br />

Seite 626 der Dokumentation ASA SQL-Referenzhandbuch


Kapitel 6 Programmieren mit Embedded SQL<br />

♦ WHENEVER Angeben, welche Aktionen bei Fehlern in SQL-<br />

Anweisungen erfolgen sollen<br />

$ Siehe "WHENEVER-Anweisung [ESQL]" auf Seite 636 der<br />

Dokumentation ASA SQL-Referenzhandbuch<br />

275


Befehlszusammenfassung <strong>für</strong> Embedded SQL<br />

276


KAPITEL 7<br />

ODBC-Programmierung<br />

Über dieses<br />

Kapitel<br />

Inhalt<br />

In diesem Kapitel finden Sie Hinweise zum Entwickeln von Anwendungen,<br />

die die ODBC-Programmierschnittstelle direkt aufrufen.<br />

Die primäre Dokumentation <strong>für</strong> die Entwicklung von ODBC-Anwendungen<br />

ist die Microsoft ODBC SDK Documentation, die als Teil des Microsoft<br />

Data Access Components (MDAC) SDK verfügbar ist. Dieses Kapitel<br />

enthält einführende Unterlagen sowie eine Beschreibung der spezifischen<br />

Funktionen <strong>für</strong> <strong>Adaptive</strong> Server <strong>Anywhere</strong>. Sie ist jedoch keine umfassende<br />

Anleitung <strong>für</strong> die Entwicklung von ODBC-Anwendungen.<br />

Einige Tools zur Entwicklung von Anwendungen, die bereits ODBC<br />

unterstützen, haben eine eigene Programmierschnittstelle, die die ODBC-<br />

Schnittstelle verbirgt. Dieses Kapitel richtet sich nicht an die Benutzer dieser<br />

Tools.<br />

Thema Seite<br />

Einführung in ODBC 278<br />

ODBC-Anwendungen erstellen 280<br />

ODBC-Beispiele 285<br />

ODBC-Handles 287<br />

Verbindung mit einer Datenquelle herstellen 290<br />

SQL-Anweisungen ausführen 294<br />

Mit Ergebnismengen arbeiten 299<br />

Gespeicherte Prozeduren aufrufen 304<br />

Umgang mit Fehlern 306<br />

277


Einführung in ODBC<br />

Einführung in ODBC<br />

Unterstützte<br />

Plattformen<br />

ODBC-Übereinstimmung<br />

Stufen der ODBC-<br />

Unterstützung<br />

Von <strong>Adaptive</strong><br />

Server <strong>Anywhere</strong><br />

unterstützte<br />

Funktionen<br />

278<br />

Open Database Connectivity (ODBC) ist eine Programmierschnittstelle,<br />

die von der Microsoft Corporation als Standardschnittstelle <strong>für</strong> Datenbank-<br />

Managementsysteme in Windows-Betriebssystemen definiert wurde. ODBC<br />

ist eine aufrufbasierte Schnittstelle.<br />

Um ODBC-Anwendungen <strong>für</strong> <strong>Adaptive</strong> Server <strong>Anywhere</strong> zu entwickeln,<br />

brauchen Sie:<br />

♦ <strong>Adaptive</strong> Server <strong>Anywhere</strong>.<br />

♦ Einen C-Compiler, mit dem Sie Programme in Ihrer<br />

Betriebssystemumgebung erstellen können<br />

♦ Das Microsoft ODBC Software Development Kit. Sie finden es im<br />

Microsoft Developer Network. Es umfasst Dokumentation und Tools,<br />

um ODBC-Anwendungen zu testen.<br />

<strong>Adaptive</strong> Server <strong>Anywhere</strong> unterstützt die ODBC API außer unter Windows<br />

auch unter UNIX und Windows CE. Die plattformunabhängige ODBC-<br />

Unterstützung erleichtert die Entwicklung portabler<br />

Datenbankanwendungen.<br />

$ Weitere Informationen zur Auflistung von ODBC-Treibern in verteilten<br />

Transaktionen finden Sie unter "Dreischichtige Datenverarbeitung und<br />

verteilte Transaktionen" auf Seite 399.<br />

<strong>Adaptive</strong> Server <strong>Anywhere</strong> bietet Unterstützung <strong>für</strong> ODBC 3.52.<br />

ODBC-Funktionen werden nach Kompatibilitätsstufen eingeordnet. Eine<br />

Funktion ist entweder Kern, Stufe 1, oder Stufe 2, wobei Stufe 2 den<br />

Standard am besten unterstützt. Diese Funktionen sind aufgeführt in der<br />

Dokumentation ODBC Programmer’s Reference, die von der Microsoft<br />

Corporation als Teil des ODBC Software Development Kits bzw. von der<br />

Microsoft Website unter<br />

http://msdn.microsoft.com/library/default.asp?url=/library/enus/odbc/htm/odbcabout_this_manual.asp<br />

bezogen werden kann.<br />

Der <strong>Adaptive</strong> Server <strong>Anywhere</strong> unterstützt die ODBC 3,52 Spezifikation.<br />

♦ Kernübereinstimmung Der <strong>Adaptive</strong> Server <strong>Anywhere</strong> unterstützt alle<br />

Kernfunktionen.


ODBC-Rückwärts-<br />

Kompatibilität<br />

Der ODBC-Treiber-<br />

Manager<br />

Kapitel 7 ODBC-Programmierung<br />

♦ Übereinstimmung mit Stufe 1 <strong>Adaptive</strong> Server <strong>Anywhere</strong> unterstützt<br />

alle Funktionen der Stufe 1, abgesehen von der asynchronen Ausführung<br />

von ODBC-Funktionen.<br />

<strong>Adaptive</strong> Server <strong>Anywhere</strong> unterstützt die gemeinsame Nutzung einer<br />

Verbindung durch mehrfache Threads. Die Anforderungen von<br />

verschiedenen Threads werden von <strong>Adaptive</strong> Server <strong>Anywhere</strong><br />

serialisiert.<br />

♦ Übereinstimmung mit Stufe 2 <strong>Adaptive</strong> Server <strong>Anywhere</strong> unterstützt<br />

alle Funktionen der Stufe 2, mit Ausnahme der folgenden:<br />

♦ Dreiteilige Namen von Tabellen und Ansichten. Dies ist auf<br />

<strong>Adaptive</strong> Server <strong>Anywhere</strong> nicht anwendbar.<br />

♦ Asynchrone Ausführung von ODBC-Funktionen <strong>für</strong> bestimmte<br />

einzelne Anweisungen<br />

♦ Die Fähigkeit, Login-Anforderungen und SQL-Anforderungen nach<br />

einer gegebenen Zeit abzubrechen (time out)<br />

Anwendungen, die mit älteren Versionen von ODBC entwickelt wurden,<br />

sind weiter kompatibel mit <strong>Adaptive</strong> Server <strong>Anywhere</strong> und dem neueren<br />

ODBC-Treiber-Manager. Die neuen ODBC Funktionen stehen in den älteren<br />

Anwendungen nicht zur Verfügung.<br />

Der ODBC-Treiber-Manager gehört zu der mit <strong>Adaptive</strong> Server <strong>Anywhere</strong><br />

ausgelieferten ODBC-Software. ODBC-Treiber-Manager Version 3 hat eine<br />

neue Schnittstelle <strong>für</strong> die Konfiguration von ODBC-Datenquellen.<br />

279


ODBC-Anwendungen erstellen<br />

ODBC-Anwendungen erstellen<br />

ODBC-Header-Datei einbeziehen<br />

280<br />

In diesem Abschnitt wird beschrieben, wie einfache ODBC-Anwendungen<br />

kompiliert und gelinkt werden.<br />

Jede C-Quelldatei, die ODBC-Funktionen aufruft, muss eine<br />

plattformspezifische ODBC-Header-Datei einbeziehen. Jede<br />

plattformspezifische Header-Datei schließt die wichtigste ODBC-Header-<br />

Datei odbc.h ein, die alle Funktionen, Datentypen und Konstanten definiert,<br />

die erforderlich sind, um ein ODBC-Programm zu schreiben.<br />

v So wird die ODBC-Header-Datei in eine C-Quelldatei einbezogen:<br />

1 Fügen Sie eine Include-Zeile hinzu, die die betreffende<br />

plattformspezifische Header-Datei referenziert. Folgende Zeilen müssen<br />

benutzt werden:<br />

Betriebssystem Include-Zeile<br />

Windows #include "ntodbc.h"<br />

UNIX #include "unixodbc.h"<br />

Windows CE #include "ntodbc.h"<br />

2 Fügen Sie das Verzeichnis, das die Header-Datei enthält, dem Include-<br />

Pfad Ihres Compilers hinzu.<br />

Die plattformspezifischen Header-Dateien und odbc.h werden im<br />

Unterverzeichnis h Ihres SQL <strong>Anywhere</strong>-Verzeichnisses installiert.<br />

ODBC-Anwendungen unter Windows verknüpfen<br />

Dieser Abschnitt betrifft nicht Windows CE. Weitere Hinweise finden Sie<br />

unter "ODBC-Anwendungen unter Windows CE verknüpfen" auf Seite 281.<br />

Wenn Sie Ihre Anwendung linken, müssen Sie diese mit der geeigneten<br />

Importbibliothekdatei verbinden. Damit ist der Zugriff auf die ODBC-<br />

Funktionen gewährleistet: Mit der Importbibliothek werden Eintrittspunkte<br />

<strong>für</strong> den ODBC Driver Manager odbc32.dll definiert. Der Treiber-Manager<br />

seinerseits lädt den <strong>Adaptive</strong> Server <strong>Anywhere</strong>-ODBC-Treiber dbodbc8.dll.


Kapitel 7 ODBC-Programmierung<br />

Separate Importbibliotheken werden <strong>für</strong> Microsoft-, Watcom- und Borland-<br />

Compiler angeboten.<br />

v So wird eine ODBC-Anwendung verknüpft (Windows):<br />

♦ Fügen Sie das Verzeichnis mit der plattformspezifischen<br />

Importbibliothek der Liste der Bibliothekenverzeichnisse hinzu.<br />

Die Importbibliotheken werden im Unterverzeichnis lib des<br />

Verzeichnisses mit den ausführbaren Dateien von <strong>Adaptive</strong> Server<br />

<strong>Anywhere</strong> gespeichert und tragen die folgenden Bezeichnungen:<br />

Betriebssystem Compiler Importbibliothek<br />

Windows 95/98 und<br />

Windows NT<br />

Windows 95/98 und<br />

Windows NT<br />

Windows 95/98 und<br />

Windows NT<br />

Microsoft odbc32.lib<br />

Watcom<br />

C/C++<br />

wodbc32.lib<br />

Borland bodbc32.lib<br />

Windows CE Microsoft dbodbc8.lib<br />

ODBC-Anwendungen unter Windows CE verknüpfen<br />

In Windows CE-Betriebssystemen gibt es keinen ODBC-Treiber-Manager.<br />

Mit der Importbibliothek (dbodbc8.lib) werden die Eintrittspunkte direkt in<br />

den <strong>Adaptive</strong> Server <strong>Anywhere</strong>-ODBC-Treiber dbodbc8.dll definiert.<br />

Für die verschiedenen Chips, auf denen Windows CE verfügbar ist, werden<br />

separate Versionen dieser DLL zur Verfügung gestellt. Die Dateien befinden<br />

sich in betriebssystemspezifischen Unterverzeichnissen des Verzeichnisses<br />

ce in Ihrem SQL <strong>Anywhere</strong>-Verzeichnis. Zum Beispiel befindet sich der<br />

ODBC-Treiber <strong>für</strong> Windows CE mit dem SH3-Chip an folgendem<br />

Speicherort:<br />

C:\Programme\<strong>Sybase</strong>\SQL <strong>Anywhere</strong> 8\ce\SH3<br />

$ Eine Liste der unterstützten Versionen von Windows CE finden Sie<br />

unter "Erforderliche Systemausstattung <strong>für</strong> <strong>Adaptive</strong> Server <strong>Anywhere</strong>" auf<br />

Seite 31 der Dokumentation ASA Erste Schritte.<br />

v So wird eine ODBC-Anwendung gelinkt (Windows CE):<br />

1 Fügen Sie das Verzeichnis mit der plattformspezifischen<br />

Importbibliothek der Liste der Bibliothekenverzeichnisse hinzu.<br />

281


ODBC-Anwendungen erstellen<br />

Windows CE und<br />

Unicode<br />

282<br />

Die Importbibliothek trägt den Namen dbodbc8.lib und ist an einem<br />

betriebssystemabhängigen Ort im Verzeichnis ce in Ihrem<br />

SQL <strong>Anywhere</strong>-Verzeichnis gespeichert. Zum Beispiel befindet sich die<br />

Importbibliothek <strong>für</strong> Windows CE mit dem SH3-Chip an folgendem<br />

Speicherort:<br />

C:\Programme\<strong>Sybase</strong>\SQL <strong>Anywhere</strong> 8\ce\SH3\lib<br />

2 Belegen Sie den Parameter DRIVER= in der Verbindungs-<br />

Zeichenfolge, die an die Funktion SQLDriverConnect weitergegeben<br />

wird.<br />

szConnStrIn =<br />

"driver=BSSuchpfad\dbodbc8.dll;dbf=c:\asademo.db"<br />

wobei BSSuchpfad der vollständige Suchpfad bis zum Chip-spezifischen<br />

Unterverzeichnis Ihres SQL <strong>Anywhere</strong>-Verzeichnisses auf dem<br />

Windows CE-Gerät ist. Zum Beispiel:<br />

\Programme\<strong>Sybase</strong>\SQL <strong>Anywhere</strong> 8\ce\SH3\lib<br />

Das Beispielprogramm (odbc.c) verwendet eine Dateidatenquelle (FileDSN-<br />

Verbindungsparameter) mit dem Namen ASA 8.0 Sample.dsn. Sie können<br />

Dateidatenquellen auf Ihrem Desktopsystem aus dem ODBC-Treiber-<br />

Manager erstellen und sie dann auf Ihr Windows CE-Gerät kopieren.<br />

<strong>Adaptive</strong> Server <strong>Anywhere</strong> verwendet die Codierung UTF-8 ist; hierbei<br />

handelt es sich um eine Mehrbyte-Zeichenkodierung, die <strong>für</strong> die Codierung<br />

von Unicode verwendet werden kann.<br />

Der <strong>Adaptive</strong> Server <strong>Anywhere</strong> ODBC-Treiber unterstützt entweder ASCII<br />

(8-Bit)-Zeichenfolgen oder Unicode (Wide Character)-Zeichenfolgen. Das<br />

UNICODE-Makro steuert, ob ODBC-Funktionen ASCII- oder Unicode-<br />

Zeichenfolgen erwarten. Wenn Ihre Anwendung mit dem definierten<br />

UNICODE-Makro erstellt werden muss, Sie aber die ASCII ODBC-<br />

Funktionen nutzen möchten, müssen Sie ebenfalls das<br />

SQL_NOUNICODEMAP-Makro definieren.<br />

Die Beispieldatei Samples\ASA\C\odbc.c veranschaulicht, wie Sie die<br />

Unicode ODBC-Funktionen anwenden.<br />

ODBC-Anwendungen auf UNIX verknüpfen<br />

<strong>Adaptive</strong> Server <strong>Anywhere</strong> umfasst keinen ODBC-Treiber-Manager, es gibt<br />

jedoch Treiber-Manager von Drittherstellern. In diesem Abschnitt wird<br />

beschrieben, wie ODBC-Anwendungen aufgebaut werden, die den ODBC-<br />

Treiber-Manager nicht verwenden.


ODBC-Treiber<br />

Datenquelleninformation<br />

ODBC-Treiber-Manager unter UNIX<br />

Kapitel 7 ODBC-Programmierung<br />

Der ODBC-Treiber ist ein gemeinsam genutztes Objekt oder eine gemeinsam<br />

genutzte Bibliothek. Separate Versionen der <strong>Adaptive</strong> Server <strong>Anywhere</strong>-<br />

ODBC-Treiber werden <strong>für</strong> Anwendungen mit einfachem sowie mit mehreren<br />

Threads angeboten.<br />

Die ODBC-Treiber sind folgende Dateien:<br />

Betriebssystem Tread-Modell ODBC-Treiber<br />

Solaris/Sparc Ein Thread dbodbc8.so (dbodbc8.so.1)<br />

Solaris/Sparc Mehrere Threads dbodbc_r.so (dbodbc_r.so.1)<br />

Die Bibliotheken sind mit einer Versionsnummer (in Klammern) als<br />

symbolische Verknüpfungen mit der gemeinsam benutzten Bibliothek<br />

installiert.<br />

v So wird eine ODBC-Anwendung gelinkt (UNIX):<br />

1 Linken Sie Ihre Anwendung direkt mit dem geeigneten ODBC-Treiber.<br />

2 Wenn Sie Ihre Anwendung bereitstellen, achten Sie darauf, dass der<br />

geeignete ODBC-Treiber im Bibliotheks-Suchpfad des Benutzersystems<br />

enthalten ist.<br />

Wenn <strong>Adaptive</strong> Server <strong>Anywhere</strong> keinen ODBC-Treiber-Manager findet,<br />

verwendet er die Datei ~/.odbc.ini als Datenquelleninformation.<br />

ODBC-Treiber-Manager <strong>für</strong> UNIX werden von Drittherstellern angeboten.<br />

Ein ODBC-Treiber-Manager beinhaltet die folgenden Dateien:<br />

Betriebssystem Dateien<br />

Solaris/Sparc libodbc.so (libodbc.so.1)<br />

libodbcinst.so (libodbcinst.so.1)<br />

Solaris/Sparc libodbc.so (libodbc.so.1)<br />

libodbcinst.so (libodbcinst.so.1)<br />

Wenn Sie eine Anwendung bereitstellen, die einen ODBC-Treiber-Manager<br />

erfordert, und Sie keinen Treiber-Manager eines Drittanbieters benutzen,<br />

erstellen Sie symbolische Verknüpfungen <strong>für</strong> die gemeinsam genutzten<br />

Bibliotheken libodbc und libodbcinst zum <strong>Adaptive</strong> Server <strong>Anywhere</strong>-<br />

ODBC-Treiber.<br />

283


ODBC-Anwendungen erstellen<br />

284<br />

Wenn ein ODBC-Treiber-Manager vorhanden ist, fragt der <strong>Adaptive</strong> Server<br />

<strong>Anywhere</strong> diesen und nicht ~/.odbc.ini nach Datenquelleninformationen ab<br />

Standard-ODBC-Anwendungen werden im Allgemeinen nicht direkt an den<br />

ODBC-Treiber gelinkt. Statt dessen gehen ODBC-Funktionsaufrufe über den<br />

ODBC-Treiber-Manager. Bei UNIX- und Windows CE-Betriebssystemen<br />

bezieht <strong>Adaptive</strong> Server <strong>Anywhere</strong> keinen ODBC-Treiber-Manager ein. Sie<br />

können weiterhin ODBC-Anwendungen erstellen, indem Sie sie direkt an<br />

den <strong>Adaptive</strong> Server <strong>Anywhere</strong>-ODBC-Treiber linken, jedoch können Sie<br />

dann nur auf <strong>Adaptive</strong> Server <strong>Anywhere</strong>-Datenquellen zugreifen.


ODBC-Beispiele<br />

Kapitel 7 ODBC-Programmierung<br />

Mit <strong>Adaptive</strong> Server <strong>Anywhere</strong> werden mehrere Beispiele geliefert. Die<br />

Beispiele finden Sie im Unterverzeichnis Samples\ASA Ihres<br />

SQL <strong>Anywhere</strong>-Verzeichnisses. Standardmäßig ist dies<br />

C:\Programme\<strong>Sybase</strong>\SQL <strong>Anywhere</strong> 8\Samples\ASA<br />

Die Beispiele in Verzeichnissen, die mit ODBC beginnen, veranschaulichen<br />

separate und einfache ODBC-Aufgaben, wie etwa eine Verbindung mit einer<br />

Datenbank herstellen und Anweisungen ausführen. Ein vollständiges ODBC-<br />

Beispielprogramm finden Sie unter Samples\ASA\C\odbc.c. Das Programm<br />

führt dieselben Aktionen aus wie das Beispielprogramm <strong>für</strong> einen<br />

dynamischen Cursor in Embedded SQL, das sich im gleichen Verzeichnis<br />

befindet.<br />

$ Eine Beschreibung des entsprechenden Embedded SQL-Programms<br />

finden Sie unter "Beispielprogramme mit Embedded SQL" auf Seite 190.<br />

ODBC-Beispielprogramm erstellen<br />

Das ODBC-Beispielprogramm in Samples\ASA\C umfasst eine<br />

Stapelverarbeitungsdatei (Shell-Skript <strong>für</strong> UNIX), die eingesetzt werden<br />

kann, um die Beispielanwendung zu kompilieren und zu linken.<br />

v So wird das ODBC-Beispielprogramm erstellt<br />

1 Öffnen Sie eine Befehlszeile und wechseln Sie in das Unterverzeichnis<br />

Samples\ASA\C Ihres SQL <strong>Anywhere</strong>-Verzeichnisses.<br />

2 Führen Sie die Stapeldatei makeall oder das Shell-Skript aus.<br />

Die Syntax des Befehls ist wie folgt:<br />

makeall API Plattform Compiler<br />

Die Parameter sind wie folgt:<br />

♦ API Geben Sie odbc an, damit das ODBC-Beispiel kompiliert wird<br />

und nicht eine Embedded SQL-Version der Anwendung.<br />

♦ Plattform Geben Sie WINNT an wenn Sie <strong>für</strong> Windows-<br />

Betriebssystem kompilieren wollen.<br />

♦ Compiler Geben Sie den Compiler an, mit dem das Programm<br />

kompiliert werden soll. Folgende Compiler sind möglich:<br />

♦ WC - Watcom C/C++<br />

♦ MC - Microsoft Visual C++<br />

285


ODBC-Beispiele<br />

286<br />

♦ BC - Borland C++ Builder<br />

ODBC-Beispielprogramm ausführen<br />

Das Beispielprogramm odbc.c kann als Dienst laufen, wenn es <strong>für</strong> Windows-<br />

Versionen kompiliert wurde, die Dienste unterstützen.<br />

Die beiden Dateien, die den Beispielcode <strong>für</strong> Windows-Dienste enthalten,<br />

sind die Quelldatei ntsvc.c und die Header-Datei ntsvc.h. Der Code<br />

ermöglicht es, das damit gelinkte ausführbare Programm entweder als<br />

normales Programm oder als Windows-Dienst auszuführen.<br />

v So wird das ODBC-Beispiel ausgeführt:<br />

1 Starten Sie das Programm:<br />

♦ Führen Sie die Datei Samples\ASA\C\odbcwnt.exe aus.<br />

2 Wählen Sie eine Tabelle:<br />

♦ Wählen Sie eine der Tabellen in der Beispieldatenbank. Sie können<br />

z.B. Customer oder Employee eingeben.<br />

v Um das ODBC-Beispiel als Windows-Dienst auszuführen, gehen Sie<br />

wie folgt vor:<br />

1 Starten Sie <strong>Sybase</strong> Central und öffnen Sie den Ordner "Dienste".<br />

2 Klicken Sie auf "Dienst hinzufügen". Folgen Sie den Anweisungen, um<br />

das Beispielprogramm den NT-Diensten hinzuzufügen.<br />

3 Rechtsklicken Sie auf das Dienstsymbol und klicken Sie auf "Start", um<br />

den Dienst zu starten.<br />

Wird das Programm als Dienst ausgeführt, zeigt es, falls dies möglich ist, die<br />

normale Benutzeroberfläche. Es schreibt die Ausgabe in die Ereignisanzeige<br />

unter der Rubrik "Anwendungen". Falls die Benutzeroberfläche nicht<br />

gestartet werden kann, schreibt das Programm eine Seite in die<br />

Ereignisanzeige und hält an.


ODBC-Handles<br />

Kapitel 7 ODBC-Programmierung<br />

ODBC-Anwendungen verwenden eine kleine Anzahl von Handles, um<br />

grundlegende Funktionen wie Datenbankverbindungen und SQL-<br />

Anweisungen zu definieren. Ein Handle ist ein 32-Bit-Wert.<br />

Die folgenden Handles werden in nahezu allen ODBC-Anwendungen<br />

eingesetzt.<br />

♦ Umgebung Das Umgebungs-Handle liefert einen globalen Kontext, in<br />

dem auf Daten zugegriffen wird. Jede ODBC-Anwendung muss beim<br />

Start genau einen Umgebungs-Handle zuweisen und es bei Beendigung<br />

wieder freigeben.<br />

Der folgende Code veranschaulicht, wie ein Umgebungs-Handle<br />

zugewiesen wird:<br />

SQLHENV env;<br />

SQLRETURN rc;<br />

rc = SQLAllocHandle( SQL_HANDLE_ENV, SQL<br />

_NULL_HANDLE, &env );<br />

♦ Verbindung Ein Verbindungs-Handle wird von einem ODBC-Treiber<br />

und einer Datenquelle angegeben. Eine Anwendung kann über mehrere,<br />

ihrer Umgebung zugeordnete Verbindungen verfügen. Ein Verbindungs-<br />

Handle zuzuweisen heißt nicht, eine Verbindung herzustellen. Ein<br />

Verbindungs-Handle muss zunächst zugewiesen und dann verwendet<br />

werden, wenn die Verbindung hergestellt ist.<br />

Der folgende Code veranschaulicht, wie ein Verbindungs-Handle<br />

zugewiesen wird:<br />

SQLHDBC dbc;<br />

SQLRETURN rc;<br />

rc = SQLAllocHandle( SQL_HANDLE_DBC, env, &dbc );<br />

♦ Anweisung Ein Anweisungs-Handle bietet Zugriff auf eine SQL-<br />

Anweisung und damit verbundene Daten, wie etwa Ergebnisgruppen<br />

und Parameter. Jede Verbindung kann mehrere Anweisungen haben.<br />

Anweisungen werden sowohl <strong>für</strong> Cursorvorgänge (Daten abrufen) als<br />

auch <strong>für</strong> die Ausführung einfacher Anweisungen benutzt (z.B. INSERT,<br />

UPDATE und DELETE).<br />

Der folgende Code veranschaulicht, wie ein Anweisungs-Handle<br />

zugewiesen wird:<br />

SQLHSTMT stmt;<br />

SQLRETURN rc;<br />

rc = SQLAllocHandle( SQL_HANDLE_STMT, dbc, &stmt );<br />

287


ODBC-Handles<br />

ODBC-Handles zuweisen<br />

Beispiel<br />

288<br />

Die <strong>für</strong> ODBC-Programme erforderlichen Handle-Typen sind:<br />

Element Handle-Typ<br />

Umgebung SQLHENV<br />

Verbindung SQLHDBC<br />

Anweisung SQLHSTMT<br />

Deskriptor SQLHDESC<br />

v So wird ein ODBC-Handle verwendet:<br />

1 Funktion SQLAllocHandle aufrufen.<br />

SQLAllocHandle nimmt die folgenden Parameter an:<br />

♦ Einen Bezeichner <strong>für</strong> den Typ des zuzuweisenden Elements<br />

♦ Das Handle des übergeordneten Elements<br />

♦ Einen Zeiger auf den Ort, an dem das Handle zugewiesen wird<br />

$ Eine vollständige Beschreibung finden Sie unter SQLAllocHandle<br />

in der Microsoft-Dokumentation ODBC Programmer’s Reference.<br />

2 Das Handle in nachfolgenden Funktionsaufrufen verwenden.<br />

3 Das Objekt mit SQLFreeHandle freisetzen.<br />

SQLFreeHandle nimmt die folgenden Parameter an:<br />

♦ Einen Bezeichner <strong>für</strong> den Typ des freizusetzenden Elements<br />

♦ Das Handle des freizusetzenden Elements<br />

$ Eine vollständige Beschreibung finden Sie unter SQLFreeHandle<br />

in der Microsoft-Dokumentation ODBC Programmer's Reference.<br />

Mit dem folgenden Codefragment wird ein Umgebungs-Handle zugewiesen<br />

und freigesetzt:<br />

SQLHENV env;<br />

SQLRETURN retcode;<br />

retcode = SQLAllocHandle( SQL_HANDLE_ENV, SQL_NULL_HANDLE, &env );<br />

if( retcode == SQL_SUCCESS || retcode == SQL_SUCCESS_WITH_INFO ) {<br />

// Erfolg: Hier den Anwendungscode<br />

}<br />

SQLFreeHandle( SQL_HANDLE_ENV, env );<br />

$ Weitere Hinweise zu Rückgabecodes und Fehlerbehandlung finden Sie<br />

unter "Umgang mit Fehlern" auf Seite 306.


Ein erstes ODBC-Beispiel<br />

#include <br />

#include "ntodbc.h"<br />

Kapitel 7 ODBC-Programmierung<br />

Es folgt ein einfaches ODBC-Programm, dass eine Verbindung mit der<br />

<strong>Adaptive</strong> Server <strong>Anywhere</strong>-Beispieldatenbank herstellt und diese sofort<br />

wieder trennt.<br />

$ Dieses Beispiel finden Sie als<br />

Samples\ASA\ODBCConnect\odbcconnect.cpp in Ihrem SQL <strong>Anywhere</strong>-<br />

Verzeichnis.<br />

int main(int argc, char* argv[])<br />

{<br />

SQLHENV env;<br />

SQLHDBC dbc;<br />

SQLRETURN retcode;<br />

retcode = SQLAllocHandle( SQL_HANDLE_ENV, SQL_NULL_HANDLE, &env );<br />

if (retcode == SQL_SUCCESS || retcode == SQL_SUCCESS_WITH_INFO) {<br />

printf( "env allocated\n" );<br />

/* Umgebungsattribut ODBC-Version setzen */<br />

retcode = SQLSetEnvAttr( env, SQL_ATTR_ODBC_VERSION, (void*)SQL_OV_ODBC3, 0);<br />

retcode = SQLAllocHandle( SQL_HANDLE_DBC, env, &dbc );<br />

if (retcode == SQL_SUCCESS || retcode == SQL_SUCCESS_WITH_INFO) {<br />

printf( "dbc allocated\n" );<br />

retcode = SQLConnect( dbc,<br />

(SQLCHAR*) "ASA 8.0 Sample", SQL_NTS,<br />

(SQLCHAR* ) "DBA", SQL_NTS,<br />

(SQLCHAR*) "SQL", SQL_NTS );<br />

if (retcode == SQL_SUCCESS || retcode == SQL_SUCCESS_WITH_INFO) {<br />

printf( "Successfully connected\n" );<br />

}<br />

SQLDisconnect( dbc );<br />

}<br />

SQLFreeHandle( SQL_HANDLE_DBC, dbc );<br />

}<br />

SQLFreeHandle( SQL_HANDLE_ENV, env );<br />

return 0;<br />

}<br />

289


Verbindung mit einer Datenquelle herstellen<br />

Verbindung mit einer Datenquelle herstellen<br />

290<br />

In diesem Abschnitt wird beschrieben, wie ODBC-Funktionen zum<br />

Herstellen einer Verbindung mit einer <strong>Adaptive</strong> Server <strong>Anywhere</strong>-<br />

Datenbank eingesetzt werden.<br />

Eine ODBC-Verbindungsfunktion wählen<br />

ODBC bietet eine Reihe von Verbindungsfunktionen. Welche Sie<br />

verwenden, hängt davon ab, wie Ihre Anwendung bereitgestellt und benutzt<br />

werden soll:<br />

♦ SQLConnect Die einfachste Verbindungsfunktion.<br />

SQLConnect nimmt einen Datenquellennamen und eine fakultative<br />

Benutzer-ID und ein fakultatives Benutzkennkennwort an. Verwenden<br />

Sie SQLConnect, wenn Sie einen Datenquellennamen in Ihrer<br />

Anwendung hartcodieren.<br />

$ Weitere Hinweise finden Sie unter SQLConnect in der Microsoft<br />

Dokumentation ODBC Programmer’s Reference.<br />

♦ SQLDriverConnect Stellt mit Hilfe einer Verbindungszeichenfolge eine<br />

Verbindung zu einer Datenquelle her.<br />

Mit SQLDriverConnect kann die Anwendung <strong>Adaptive</strong> Server<br />

<strong>Anywhere</strong>-spezifische Verbindungsdaten verwenden, die unabhängig<br />

von der Datenquelle sind. Darüber hinaus können Sie<br />

SQLDriverConnect benutzen, um anzufordern, dass der <strong>Adaptive</strong><br />

Server <strong>Anywhere</strong>-Treiber zur Eingabe von Verbindungsdaten auffordert.<br />

SQLDriverConnect kann auch benutzt werden, um eine Verbindung<br />

herzustellen, ohne dass eine Datenquelle angegeben wird.<br />

$ Weitere Hinweise finden Sie unter SQLDriverConnect in der<br />

Microsoft Dokumentation ODBC Programmer’s Reference.<br />

♦ SQLBrowseConnect Stellt wie SQLDriverConnect mit Hilfe einer<br />

Verbindungszeichenfolge eine Verbindung zu einer Datenquelle her.<br />

Mit SQLBrowseConnect kann Ihre Anwendung eigene Dialogfelder<br />

aufbauen, die zur Eingabe von Verbindungsdaten auffordern und nach<br />

Datenquellen suchen, die von einem bestimmten Treiber verwendet<br />

werden (in diesem Fall der <strong>Adaptive</strong> Server <strong>Anywhere</strong>-Treiber).<br />

$ Weitere Hinweise finden Sie unter SQLBrowseConnect in der<br />

Microsoft Dokumentation ODBC Programmer’s Reference.


Eine Verbindung herstellen<br />

Kapitel 7 ODBC-Programmierung<br />

In den Beispielen in diesem Kapitel wird hauptsächlich SQLDriverConnect<br />

verwendet.<br />

$ Eine vollständige Liste der Verbindungsparameter, die in<br />

Verbindungszeichenfolgen eingesetzt werden können, finden Sie unter<br />

"Verbindungsparameter" auf Seite 182 der Dokumentation ASA<br />

Datenbankadministration.<br />

Ihre Anwendung muss eine Verbindung herstellen, bevor sie<br />

Datenbankvorgänge ausführen kann.<br />

v So wird eine ODBC-Verbindung hergestellt:<br />

1 ODBC-Umgebung zuweisen.<br />

Zum Beispiel:<br />

SQLHENV env;<br />

SQLRETURN retcode;<br />

retcode = SQLAllocHandle( SQL_HANDLE_ENV,<br />

SQL_NULL_HANDLE, &env );<br />

2 ODBC-Version deklarieren.<br />

Wenn Sie deklarieren, dass die Anwendung ODBC Version 3 befolgen<br />

soll, werden SLQSTATE-Werte und einige andere versionsabhängige<br />

Funktionen auf das entsprechende Verhalten eingestellt. Zum Beispiel:<br />

retcode = SQLSetEnvAttr( env,<br />

SQL_ATTR_ODBC_VERSION, (void*)SQL_OV_ODBC3, 0);<br />

3 Falls erforderlich, die Datenquelle oder Verbindungszeichenfolge<br />

zusammenstellen.<br />

Je nach Ihrer Anweisung können Sie eine Datenquelle oder<br />

Verbindungszeichenfolge hartcodieren oder sie <strong>für</strong> erhöhte Flexibilität<br />

extern speichern.<br />

4 Ein ODBC-Verbindungselement zuweisen.<br />

Zum Beispiel:<br />

retcode = SQLAllocHandle( SQL_HANDLE_DBC, env, &dbc<br />

);<br />

5 Diejenigen Verbindungsattribute festlegen, die vor dem Verbinden<br />

eingerichtet sein müssen.<br />

291


Verbindung mit einer Datenquelle herstellen<br />

Hinweise<br />

Verbindungsattribute festlegen<br />

292<br />

Einige Verbindungsattribute müssen festgelegt werden, bevor eine<br />

Verbindung hergestellt wird, während andere vorher oder nachher<br />

eingerichtet werden können. Zum Beispiel:<br />

retcode = SQLSetConnectAttr( dbc,<br />

SQL_AUTOCOMMIT, (SQLPOINTER)SQL_AUTOCOMMIT_OFF, 0<br />

);<br />

$ Weitere Hinweise finden Sie unter "Verbindungsattribute<br />

festlegen" auf Seite 292.<br />

6 ODBC-Verbindungsfunktion aufrufen.<br />

Zum Beispiel:<br />

if (retcode == SQL_SUCCESS || retcode ==<br />

SQL_SUCCESS_WITH_INFO) {<br />

printf( "dbc allocated\n" );<br />

retcode = SQLConnect( dbc,<br />

(SQLCHAR*) "ASA 8.0 Sample", SQL_NTS,<br />

(SQLCHAR* ) "DBA", SQL_NTS,<br />

(SQLCHAR*) "SQL", SQL_NTS );<br />

if (retcode == SQL_SUCCESS<br />

|| retcode == SQL_SUCCESS_WITH_INFO){<br />

// Verbindung erfolgreich hergestellt.<br />

$ Ein vollständiges Beispiel finden Sie in<br />

Samples\ASA\ODBCConnect\odbcconnect.cpp in Ihrem SQL <strong>Anywhere</strong>-<br />

Verzeichnis.<br />

♦ SQL_NTS Jede Zeichenfolge, die an ODBC übergeben wird, hat eine<br />

entsprechende Länge. Ist die Länge unbekannt, können Sie SQL_NTS<br />

als Argument verwenden, um anzuzeigen, dass es sich um einen Null<br />

Terminated String handelt, dessen Ende durch das Nullzeichen<br />

gekennzeichnet ist (\0).<br />

♦ SQLSetConnectAttr Voreingestellt arbeitet ODBC im Autocommit-<br />

Modus. Dieser Modus wird abgeschaltet, indem SQL_AUTOCOMMIT<br />

auf "false" gesetzt wird.<br />

$ Weitere Hinweise finden Sie unter "Verbindungsattribute<br />

festlegen" auf Seite 292.<br />

Die Funktion SQLSetConnectAttr wird eingesetzt, um Verbindungsdetails zu<br />

steuern. Zum Beispiel deaktiviert die folgende Anweisung das ODBC-<br />

Autocommit-Verhalten.<br />

retcode = SQLSetConnectAttr( dbc, SQL_AUTOCOMMIT,<br />

(SQLPOINTER)SQL_AUTOCOMMIT_OFF, 0 );


Kapitel 7 ODBC-Programmierung<br />

$ Weitere Hinweise sowie eine Liste der Verbindungsattribute finden Sie<br />

unter SQLSetConnectAttr in der Microsoft Dokumentation ODBC<br />

Programmer’s Reference .<br />

Viele Aspekte der Verbindung können über die Verbindungsparameter<br />

gesteuert werden. Hinweise finden Sie unter "Verbindungsparameter" auf<br />

Seite 78 der Dokumentation ASA Datenbankadministration.<br />

Threads und Verbindungen in ODBC-Anwendungen<br />

Sie können ODBC-Anwendungen mit mehreren Threads <strong>für</strong> <strong>Adaptive</strong> Server<br />

<strong>Anywhere</strong> entwickeln. Es wird empfohlen, dass Sie <strong>für</strong> jeden Thread eine<br />

eigene Verbindung benutzen.<br />

Sie können <strong>für</strong> mehrfache Threads eine einfache Verbindung benutzen. Der<br />

Datenbankserver erlaubt allerdings nicht mehr als eine aktive Anforderung<br />

<strong>für</strong> eine Verbindung zur gleichen Zeit. Falls ein Thread eine Anweisung<br />

ausführt, die lange braucht, müssen alle anderen Threads warten, bis die<br />

Anforderung abgeschlossen ist.<br />

293


SQL-Anweisungen ausführen<br />

SQL-Anweisungen ausführen<br />

Anweisungen direkt ausführen<br />

294<br />

ODBC umfasst mehrere Funktionen zum Ausführen von SQL-Anweisungen:<br />

♦ Direkte Ausführung <strong>Adaptive</strong> Server <strong>Anywhere</strong> führt eine syntaktische<br />

Analyse der SQL-Anweisung durch, bereitet einen Zugriffsplan vor und<br />

führt die Anweisung aus. Das syntaktische Analysieren und das<br />

Vorbereiten des Zugriffsplans wird Vorbereitung der Anweisung<br />

genannt.<br />

♦ Vorbereitete Ausführung Die Vorbereitung der Anweisung erfolgt<br />

getrennt von der Ausführung. Bei Anweisungen, die wiederholt<br />

ausgeführt werden sollen wird damit vermieden, dass wiederholt<br />

vorbereitet werden muss. Damit wird die Performance verbessert.<br />

$ Siehe "Vorbereitete Anweisungen ausführen" auf Seite 297.<br />

Mit der Funktion SQLExecDirect wird eine SQL-Anweisung vorbereitet<br />

und ausgeführt. Die Anweisung kann auch Parameter enthalten.<br />

Das folgende Codefragment veranschaulicht, wie eine Anweisung ohne<br />

Parameter ausgeführt wird. Die Funktion SQLExecDirect nimmt ein<br />

Anweisungs-Handle, eine SQL-Zeichenfolge und eine Länge bzw. ein<br />

Abschlusszeichen an, falls ein Zeichenfolgeindikator mit<br />

Nullabschlusszeichen erforderlich ist.<br />

Das in diesem Abschnitt beschriebene Verfahren ist zwar einfach, aber<br />

unflexibel. Die Anweisung kann keine Benutzereingabe zur Änderung der<br />

Anweisung annehmen. Flexiblere Methoden zum Aufbau von Anweisungen<br />

finden Sie unter "Anweisungen mit gebundenen Parametern ausführen" auf<br />

Seite 295.<br />

v So wird eine SQL-Anweisung in einer ODBC-Anwendung<br />

ausgeführt:<br />

1 Der Anweisung mit SQLAllocHandle ein Handle zuweisen.<br />

Mit der folgenden Anweisung wird z.B. bei einer Verbindung mit dem<br />

Handle dbc ein Handle vom Typ SQL_HANDLE_STMT mit dem Namen<br />

stmt zugewiesen:<br />

SQLAllocHandle( SQL_HANDLE_STMT, dbc, &stmt );<br />

2 Funktion SQLExecDirect aufrufen und die Anweisung ausführen:


Kapitel 7 ODBC-Programmierung<br />

Mit den folgenden Zeilen wird z.B. eine Anweisung deklariert und<br />

ausgeführt. Die Deklaration von deletestmt würde normalerweise am<br />

Anfang der Funktion auftreten:<br />

SQLCHAR deletestmt[ STMT_LEN ] =<br />

"DELETE FROM department WHERE dept_id = 201";<br />

SQLExecDirect( stmt, deletestmt, SQL_NTS) ;<br />

$ Ein vollständiges Beispiel mit Fehlerprüfung finden Sie unter<br />

Samples\ASA\ODBCExecute\odbcexecute.cpp.<br />

$ Weitere Hinweise zu SQLExecDirect finden Sie unter SQLExecDirect<br />

in der Microsoft-Dokumentation ODBC Programmer’s Reference.<br />

Anweisungen mit gebundenen Parametern ausführen<br />

In diesem Abschnitt wird beschrieben, wie eine SQL-Anweisung aufgebaut<br />

und ausgeführt wird, bei der zum Festlegen der Werte von<br />

Anweisungsparametern gebundene Parameter eingesetzt werden.<br />

v So wird eine SQL-Anweisung mit gebundenen Parametern in einer<br />

ODBC-Anwendung ausgeführt:<br />

1 Der Anweisung mit SQLAllocHandle ein Handle zuweisen.<br />

Mit der folgenden Anweisung wird z.B. bei einer Verbindung mit dem<br />

Handle dbc ein Handle vom Typ SQL_HANDLE_STMT mit dem Namen<br />

stmt zugewiesen:<br />

SQLAllocHandle( SQL_HANDLE_STMT, dbc, &stmt );<br />

2 Anweisungsparameter mit SQLBindParameter binden.<br />

Zum Beispiel werden mit den folgenden Zeilen Variable deklariert, die<br />

Werte <strong>für</strong> Abteilungs-ID, Abteilungsname und Manager-ID, sowie die<br />

Anweisungszeichenfolge selbst enthalten sollen. Als Nächstes werden<br />

Parameter an den ersten, zweiten und dritten Parameter einer Anweisung<br />

gebunden, die mit dem Anweisungs-Handle stmt ausgeführt wird.<br />

295


SQL-Anweisungen ausführen<br />

296<br />

#defined DEPT_NAME_LEN 20<br />

SQLINTEGER cbDeptID = 0,<br />

cbDeptName = SQL_NTS, cbManagerID = 0;<br />

SQLCHAR deptname[ DEPT_NAME_LEN ];<br />

SQLSMALLINT deptID, managerID;<br />

SQLCHAR insertstmt[ STMT_LEN ] =<br />

"INSERT INTO department "<br />

"( dept_id, dept_name, dept_head_id )"<br />

"VALUES (?, ?, ?,)";<br />

SQLBindParameter( stmt, 1, SQL_PARAM_INPUT,<br />

SQL_C_SSHORT, SQL_INTEGER, 0, 0,<br />

&deptID, 0, &cbDeptID);<br />

SQLBindParameter( stmt, 2, SQL_PARAM_INPUT,<br />

SQL_C_CHAR, SQL_CHAR, DEPT_NAME_LEN, 0,<br />

deptname, 0,&cbDeptName);<br />

SQLBindParameter( stmt, 3, SQL_PARAM_INPUT,<br />

SQL_C_SSHORT, SQL_INTEGER, 0, 0,<br />

&managerID, 0, &cbManagerID);<br />

3 Den Parametern Werte zuweisen.<br />

Mit den folgenden Zeilen werden z.B. den Parametern im Fragment von<br />

Schritt 2 Werte zugewiesen.<br />

deptID = 201;<br />

strcpy( (char * ) deptname, "Sales East" );<br />

managerID = 902;<br />

Im Allgemeinen werden diese Variablen als Reaktion auf eine<br />

Benutzerhandlung festgelegt.<br />

4 Führen Sie die Anweisung mit SQLExecDirect aus.<br />

Mit der folgenden Zeile wird z.B. eine Anweisungszeichenfolge<br />

ausgeführt, die sich in insertstmt im Anweisungs-Handle stmt<br />

befindet.<br />

SQLExecDirect( stmt, insertstmt, SQL_NTS) ;<br />

Gebundene Parameter werden auch mit vorbereiteten Anweisungen<br />

verwendet, um die Performance von Anweisungen zu steigern, die mehr als<br />

einmal ausgeführt werden sollen. Weitere Hinweise finden Sie unter<br />

"Vorbereitete Anweisungen ausführen" auf Seite 297.<br />

$ Die obigen Codefragmente enthalten keine Fehlerprüfung. Ein<br />

vollständiges Beispiel mit Fehlerprüfung finden Sie unter<br />

Samples\ASA\ODBCExecute\odbcexecute.cpp.<br />

$ Weitere Hinweise zu SQLExecDirect finden Sie unter SQLExecDirect<br />

in der Microsoft-Dokumentation ODBC Programmer’s Reference.


Vorbereitete Anweisungen ausführen<br />

Kapitel 7 ODBC-Programmierung<br />

Vorbereitete Anweisungen bieten Performance-Vorteile bei häufig benutzten<br />

Anweisungen. ODBC bietet eine vollständige Menge von Funktionen <strong>für</strong><br />

vorbereitete Anweisungen.<br />

$ Eine Einführung in vorbereitete Anweisungen finden Sie unter<br />

"Anweisungen vorbereiten" auf Seite 12.<br />

v So wird eine vorbereitete Anweisung ausgeführt:<br />

1 Die Anweisung mit SQLPrepare vorbereiten.<br />

Das folgende Codefragment veranschaulicht z.B., wie eine INSERT-<br />

Anweisung vorbereitet wird:<br />

SQLRETURN retcode;<br />

SQLHSTMT stmt;<br />

retcode = SQLPrepare( stmt,<br />

"INSERT INTO department<br />

( dept_id, dept_name, dept_head_id )<br />

VALUES (?, ?, ?,)",<br />

SQL_NTS);<br />

In diesem Beispiel gilt:<br />

♦ retcode Enthält einen Rückgabecode, der auf Erfolg oder<br />

Fehlschlag des Vorgangs überprüft werden sollte<br />

♦ stmt Liefert ein Handle zu der Anweisung, sodass sie später<br />

referenziert werden kann.<br />

♦ ? Die Fragezeichen sind Platzhalter <strong>für</strong> Anweisungsparameter.<br />

2 Mit SQLBindParameter Anweisungsparameter mit Werten belegen.<br />

Der folgende Funktionsaufruf zum Beispiel belegt den Wert der<br />

Variablen dept_id:<br />

SQLBindParameter( stmt,<br />

1,<br />

SQL_PARAM_INPUT,<br />

SQL_C_SSHORT,<br />

SQL_INTEGER,<br />

0,<br />

0,<br />

&sDeptID,<br />

0,<br />

&cbDeptID);<br />

In diesem Beispiel gilt:<br />

♦ stmt ist das Anweisungs-Handle<br />

297


SQL-Anweisungen ausführen<br />

298<br />

♦ 1 zeigt an, dass dieser Aufruf den ersten Platzhalter mit einem Wert<br />

belegt.<br />

♦ SQL_PARAM_INPUT zeigt an, dass der Parameter eine<br />

Eingabeanweisung ist.<br />

♦ SQL_C_SHORT zeigt den C-Datentyp an, der in der Anwendung<br />

verwendet wird.<br />

♦ SQL_INTEGER zeigt den SQL-Datentyp an, der in der Datenbank<br />

verwendet wird.<br />

♦ Die nächsten beiden Parameter zeigen die Spaltengröße und die<br />

Anzahl der Dezimalstellen an: beide sind mit 0 (Null) <strong>für</strong><br />

Ganzzahlen belegt.<br />

♦ &sDeptID ist ein Zeiger auf einen Puffer <strong>für</strong> den Parameterwert.<br />

♦ 0 gibt die Länge des Puffers in Byte an.<br />

♦ &cbDeptID ist ein Zeiger auf einen Puffer <strong>für</strong> die Länge des<br />

Parameterwerts.<br />

3 Die beiden anderen Parameter binden und sDeptId Werte zuordnen.<br />

4 Die Anweisung ausführen:<br />

retcode = SQLExecute( stmt);<br />

Schritte 2 bis 4 können mehrfach ausgeführt werden.<br />

5 Anweisung löschen.<br />

Das Löschen der Anweisung setzt die der Anweisung zugewiesenen<br />

Ressourcen frei. Anweisungen werden mit SQLFreeHandle gelöscht.<br />

$ Ein vollständiges Beispiel mit Fehlerprüfung finden Sie unter<br />

Samples\ASA\ODBCPrepare\odbcprepare.cpp.<br />

$ Weitere Hinweise zu SQLPrepare finden Sie unter SQLPrepare in der<br />

Microsoft-Dokumentation ODBC Programmer’s Reference.


Mit Ergebnismengen arbeiten<br />

Cursor-Eigenschaften wählen<br />

Kapitel 7 ODBC-Programmierung<br />

ODBC-Anwendungen verwenden Cursor zum Bearbeiten und Aktualisieren<br />

von Ergebnismengen. <strong>Adaptive</strong> Server <strong>Anywhere</strong> bietet umfassende<br />

Unterstützung <strong>für</strong> verschiedene Arten von Cursorn und Cursorvorgängen.<br />

$ Eine Einführung zu Cursorn finden Sie unter "Mit Cursorn arbeiten"<br />

auf Seite 20.<br />

ODBC-Funktionen, die Anweisungen ausführen und Ergebnismengen<br />

verarbeiten, verwenden <strong>für</strong> diese Aufgaben Cursor. Anwendungen öffnen<br />

implizit einen Cursor, wenn sie eine Funktion SQLExecute oder<br />

SQLExecDirect ausführen.<br />

Bei Anwendungen, die sich nur vorwärts durch eine Ergebnismenge<br />

bewegen und sie nicht aktualisieren, ist das Cursor-Verhalten recht einfach.<br />

Standardmäßig erwarten ODBC-Anwendungen dieses Verhalten. ODBC<br />

definiert einen Nur-Lesen-Cursor, der nur vorwärts liest und <strong>Adaptive</strong> Server<br />

<strong>Anywhere</strong> liefert einen Cursor, der <strong>für</strong> diesen Fall auf Performance optimiert<br />

ist.<br />

$ Ein einfaches Beispiel <strong>für</strong> einen nur vorwärts lesenden Cursor finden<br />

Sie unter "Daten abrufen" auf Seite 300.<br />

Bei Anwendungen, die sowohl vorwärts als auch rückwärts durch die<br />

Ergebnismenge blättern müssen, wie etwa Anwendungen mit grafischer<br />

Benutzeroberfläche, ist das Cursor-Verhalten komplexer. Wie reagiert die<br />

Anwendung, wenn sie eine Zeile zurückgibt, die von einer anderen<br />

Anwendung aktualisiert wurde? ODBC definiert eine Reihe von<br />

abrollenden Cursorn, damit Sie das gewünschte Verhalten in Ihre<br />

Anwendung einbauen können. <strong>Adaptive</strong> Server <strong>Anywhere</strong> liefert eine<br />

vollständige Gruppe von Cursorn, die mit den abrollenden ODBC-<br />

Cursortypen übereinstimmen.<br />

Die erforderlichen Cursor-Merkmale werden mit der Funktion<br />

SQLSetStmtAttr gesetzt, die die Anweisungsattribute definiert. Sie müssen<br />

SQLSetStmtAttr aufrufen, bevor Sie eine Anweisung ausführen, die eine<br />

Ergebnismenge erzeugt.<br />

Viele Cursor-Merkmale können mit SQLSetStmtAttr festgelegt werden.<br />

Folgende Merkmale bestimmen den von <strong>Adaptive</strong> Server <strong>Anywhere</strong><br />

gelieferten Cursortyp:<br />

299


Mit Ergebnismengen arbeiten<br />

Beispiel<br />

Daten abrufen<br />

300<br />

♦ SQL_ATTR_CURSOR_SCROLLABLE Für einen abrollenden Cursor<br />

auf SQL_SCROLLABLE setzen und auf SQL_NONSCROLLABLE <strong>für</strong><br />

Vorwärts-Cursor. SQL_NONSCROLLABLE ist der Standardwert.<br />

♦ SQL_ATTR_CONCURRENCY Auf einen der folgenden Werte setzen:<br />

♦ SQL_CONCUR_READ_ONLY Aktualisierungen deaktivieren.<br />

SQL_CONCUR_READ_ONLY ist der Standardwert.<br />

♦ SQL_CONCUR_LOCK Verwenden Sie die niedrigste Sperrstufe,<br />

die ausreicht, um eine Zeile zu aktualisieren.<br />

♦ SQL_CONCUR_ROWVER Verwenden Sie optimistische<br />

Parallelitätssteuerung, bei der Zeilenversionen verglichen werden,<br />

wie z.B. SQLBase ROWID oder <strong>Sybase</strong> TIMESTAMP.<br />

♦ SQL_CONCUR_VALUES Verwenden Sie optimistische<br />

Parallelitätssteuerung, bei der Werte verglichen werden.<br />

$ Weitere Hinweise finden Sie unter SQLSetStmtAttr in der Microsoft-<br />

Dokumentation ODBC Programmer’s Reference.<br />

Für das folgende Fragment ist ein abrollender Nur-Lesen-Cursor<br />

erforderlich:<br />

SQLAllocHandle( SQL_HANDLE_STMT, dbc, &stmt );<br />

SQLSetStmtAttr( stmt, SQL_ATTR_CURSOR_SCROLLABLE,<br />

SQL_SCROLLABLE, 0 );<br />

Um Zeilen aus einer Datenbank abzurufen, führen Sie mit SQLExecute oder<br />

SQLExecDirect eine SELECT-Anweisung aus. Damit wird ein Cursor <strong>für</strong><br />

die Anweisung geöffnet. Als Nächstes verwenden Sie SQLFetch oder<br />

SQLExtendedFetch, damit über den Cursor Zeilen abgerufen werden.<br />

Wenn eine Anwendung die Anweisung mit Hilfe von SQLFreeHandle<br />

freigibt, wird der Cursor geschlossen.<br />

Um Werte von einem Cursor abzurufen, kann die Anwendung entweder<br />

SQLBindCol oder SQLGetData verwenden. Falls Sie SQLBindCol<br />

benutzen, werden die Werte mit jedem Abruf (fetch) abgeholt. Falls Sie<br />

SQLGetData benutzen, müssen Sie sie <strong>für</strong> jede Spalte nach jedem Abruf<br />

(fetch) aufrufen.<br />

SQLGetData wird benutzt, um Werte in Teilen <strong>für</strong> Spalten wie LONG<br />

VARCHAR oder LONG BINARY einzulesen. Alternativ können Sie das<br />

SQL_MAX_LENGTH-Anweisungsattribut auf einen Wert setzen, der groß<br />

genug ist, um den Wert <strong>für</strong> die gesamte Spalte aufzunehmen. Der<br />

Standardwert <strong>für</strong> SQL_ATTR_MAX_LENGTH ist 256 KByte.


Kapitel 7 ODBC-Programmierung<br />

Mit dem folgenden Codefragment wird ein Cursor <strong>für</strong> eine Abfrage geöffnet<br />

und Daten über den Cursor abgerufen. Auf eine Fehlerüberprüfung wurde<br />

verzichtet, um das Beispiel leichter lesbar zu halten. Das Fragment stammt<br />

aus dem vollständigen Beispiel Samples\ASA\ODBCSelect\odbcselect.cpp.<br />

SQLINTEGER cbDeptID = 0, cbDeptName = SQL_NTS, cbManagerID = 0;<br />

SQLCHAR deptname[ DEPT_NAME_LEN ];<br />

SQLSMALLINT deptID, managerID;<br />

SQLHENV env;<br />

SQLHDBC dbc;<br />

SQLHSTMT stmt;<br />

SQLRETURN retcode;<br />

SQLAllocHandle( SQL_HANDLE_ENV, SQL_NULL_HANDLE, &env );<br />

SQLSetEnvAttr( env, SQL_ATTR_ODBC_VERSION, (void*)SQL_OV_ODBC3, 0);<br />

SQLAllocHandle( SQL_HANDLE_DBC, env, &dbc );<br />

SQLConnect( dbc,<br />

(SQLCHAR*) "ASA 8.0 Sample", SQL_NTS,<br />

(SQLCHAR*) "DBA", SQL_NTS,<br />

(SQLCHAR*) "SQL", SQL_NTS );<br />

SQLAllocHandle( SQL_HANDLE_STMT, dbc, &stmt );<br />

SQLBindCol( stmt, 1, SQL_C_SSHORT, &deptID, 0, &cbDeptID);<br />

SQLBindCol( stmt, 2, SQL_C_CHAR, deptname, sizeof(deptname),<br />

&cbDeptName);<br />

SQLBindCol( stmt, 3, SQL_C_SSHORT, &managerID, 0, &cbManagerID);<br />

SQLExecDirect( stmt, (SQLCHAR * )<br />

"SELECT dept_id, dept_name, dept_head_id FROM DEPARTMENT "<br />

"ORDER BY dept_id", SQL_NTS );<br />

while( ( retcode = SQLFetch( stmt ) ) != SQL_NO_DATA ){<br />

printf( "%d %20s %d\n", deptID, deptname, managerID );<br />

}<br />

SQLFreeHandle( SQL_HANDLE_STMT, stmt );<br />

SQLDisconnect( dbc );<br />

SQLFreeHandle( SQL_HANDLE_DBC, dbc );<br />

SQLFreeHandle( SQL_HANDLE_ENV, env );<br />

Die Anzahl der Zeilenpositionen, die Sie mit einem Fetch-Vorgang abrufen<br />

können, wird durch die Größe einer Ganzzahl bestimmt. Mit einem Fetch-<br />

Vorgang können Sie Zeilen bis zu Nummer 2147483646 abrufen, wobei es<br />

sich um die größtmögliche Ganzzahl minus 1 handelt. Wenn Sie negative<br />

Werte verwenden (Zeilen in Bezug auf das Ende), können Sie Fetch-<br />

Vorgänge nach unten bis zum niedrigsten negativen Wert, der in einer<br />

Ganzzahl möglich ist, plus 1 ausführen.<br />

301


Mit Ergebnismengen arbeiten<br />

Zeilen über einen Cursor aktualisieren und löschen<br />

302<br />

Im Dokument "Microsoft ODBC Programmer’s Reference" wird empfohlen,<br />

dass Sie SELECT ... FOR UPDATE benutzen, um anzuzeigen, dass eine<br />

Abfrage mit positionierten Vorgängen aktualisierbar ist. In <strong>Adaptive</strong> Server<br />

<strong>Anywhere</strong> brauchen Sie die Klausel FOR UPDATE nicht zu benutzen:<br />

SELECT-Anweisungen können automatisch aktualisiert werden, sofern die<br />

folgenden Bedingungen erfüllt sind:<br />

♦ Die zu Grunde liegende Abfrage unterstützt Aktualisierungen.<br />

Unter der Voraussetzung, dass eine Datenänderungsanweisung <strong>für</strong> die<br />

Spalten im Ergebnis sinnvoll ist, kann also die<br />

Datenänderungsanweisung im Cursor ausgeführt werden.<br />

Die Datenbankoption ANSI_UPDATE_CONSTRAINTS schränkt den<br />

Typ aktualisierbarer Abfragen ein.<br />

$ Weitere Hinweise finden Sie unter<br />

"ANSI_UPDATE_CONSTRAINTS" auf Seite 615 der Dokumentation<br />

ASA Datenbankadministration.<br />

♦ Der Cursortyp unterstützt Aktualisierungen.<br />

Wenn Sie einen Nur-Lese-Cursor verwenden, können Sie die<br />

Ergebnismenge nicht aktualisieren.<br />

Es gibt in ODBC zwei Alternativen, um positionsbasierte Updates und<br />

positionsbasiertes Löschen durchzuführen.<br />

♦ Die Funktion SQLSetPos.<br />

Abhängig von den angegebenen Parametern (SQL_POSITION,<br />

SQL_REFRESH, SQL_UPDATE, SQL_DELETE) legt SQLSetPos die<br />

Cursorposition fest und ermöglicht es der Anwendung, die Darstellung<br />

der Daten in der Ergebnismenge oder die Daten selbst zu aktualisieren<br />

oder die Daten zu löschen.<br />

Diese Methode muss bei <strong>Adaptive</strong> Server <strong>Anywhere</strong> angewendet<br />

werden.<br />

♦ Mit Hilfe von SQLExecute positionsbasierte UPDATE- und DELETE-<br />

ANWEISUNGEN senden. Diese Methode darf nicht bei <strong>Adaptive</strong><br />

Server <strong>Anywhere</strong> angewendet werden.


Bookmarks verwenden<br />

Kapitel 7 ODBC-Programmierung<br />

ODBC bietet Bookmarks, die benutzt werden, um Zeilen in einem Cursor zu<br />

identifizieren. <strong>Adaptive</strong> Server <strong>Anywhere</strong> unterstützt Lesezeichen<br />

(Bookmarks, Textmarken) <strong>für</strong> alle Arten von Cursorn, mit Ausnahme von<br />

dynamischen Cursorn.<br />

Vor der ODBC-Version 3.0 konnte eine Datenbank nur angeben, ob sie<br />

Bookmarks unterstützt oder nicht: Es gab keine Schnittstelle, die diese<br />

Informationen <strong>für</strong> jeden Cursortyp bereitstellte. Der Datenbankserver hatte<br />

keine Möglichkeit, anzugeben, welche Typen von Cursor-Bookmarks<br />

unterstützt werden. Für ODBC 2-Anwendungen gibt <strong>Adaptive</strong> Server<br />

<strong>Anywhere</strong> nur zurück, dass er Bookmarks unterstützt. ODBC wird Sie also<br />

nicht an dem Versuch hindern, Bookmarks mit dynamischen Cursorn zu<br />

benutzen; Sie sollten diese Kombination allerdings vermeiden.<br />

303


Gespeicherte Prozeduren aufrufen<br />

Gespeicherte Prozeduren aufrufen<br />

Prozeduren und<br />

Ergebnismengen<br />

Beispiel<br />

304<br />

In diesem Abschnitt wird beschrieben, wie gespeicherte Prozeduren<br />

aufgerufen und die Ergebnisse in einer ODBC-Anwendung bearbeitet<br />

werden.<br />

$ Eine vollständige Beschreibung von gespeicherten Prozeduren und<br />

Triggern finden Sie unter "Prozeduren, Trigger und Anweisungsfolgen<br />

verwenden" auf Seite 565 der Dokumentation ASA SQL-Benutzerhandbuch.<br />

Es gibt zwei Arten von Prozeduren: Prozeduren, die Ergebnismengen<br />

zurückgeben und solche, die keine zurückgeben. Sie können<br />

SQLNumResultCols verwenden, um den Unterschied festzustellen: die<br />

Anzahl der Ergebnisspalten ist 0 (Null), falls die Prozedur keine<br />

Ergebnismenge zurückgibt. Falls eine Ergebnismenge zurückgegeben wird,<br />

können Sie die Werte mit SQLFetch oder SQLExtendedFetch abrufen, wie<br />

bei jedem anderen Cursor.<br />

Parameter müssen an Prozeduren mit Parametermarkierungen (Fragezeichen)<br />

übergeben werden. Verwenden Sie SQLBindParameter, um jeder<br />

Parametermarkierung einen Speicherbereich zuzuweisen: INPUT, OUTPUT<br />

oder INOUT.<br />

Um mehrfache Ergebnismengen verarbeiten zu können, muss ODBC den<br />

aktuell ausgeführten Cursor beschreiben, und nicht die von der Prozedur<br />

definierte Ergebnismenge. Deshalb bezeichnet ODBC die Spaltennamen<br />

nicht immer so, wie sie in der RESULT-Klausel der gespeicherten Prozedur<br />

definiert sind. Um dieses Problem zu vermeiden, können Sie im<br />

Ergebnismengencursor Ihrer Prozedur einen Spaltenalias verwenden.<br />

Mit diesem Beispiel wird eine Prozedur erstellt und aufgerufen, die keine<br />

Ergebnismenge zurückgibt. Die Prozedur übernimmt einen INOUT-<br />

Parameter und erhöht seinen Wert. Im Beispiel wird die Variable num_col<br />

den Wert 0 (Null) haben, denn die Prozedur gibt keine Ergebnismenge<br />

zurück. Auf eine Fehlerüberprüfung wurde verzichtet, um das Beispiel<br />

leichter lesbar zu halten.<br />

HDBC dbc;<br />

HSTMT stmt;<br />

long i;<br />

SWORD num_col;<br />

/* Prozedur erstellen */<br />

SQLAllocStmt( dbc, &stmt );<br />

SQLExecDirect( stmt,<br />

"CREATE PROCEDURE Increment( INOUT a INT )" \<br />

" BEGIN" \<br />

" SET a = a + 1" \<br />

" END", SQL_NTS );


Beispiel<br />

Kapitel 7 ODBC-Programmierung<br />

/* Prozedur zur Erhöhung von 'i' aufrufen */<br />

i = 1;<br />

SQLBindParameter( stmt, 1, SQL_C_LONG, SQL_INTEGER, 0,<br />

0, &i, NULL );<br />

SQLExecDirect( stmt, "CALL Increment( ? )",<br />

SQL_NTS );<br />

SQLNumResultCols( stmt, &num_col );<br />

do_something( i );<br />

Mit dem folgenden Beispiel wird eine Prozedur aufgerufen, die eine<br />

Ergebnismenge zurückgibt. Im Beispiel hat die Variable num_col den Wert<br />

2, denn die Prozedur gibt eine Ergebnismenge mit zwei Spalten zurück. Auf<br />

eine Fehlerüberprüfung wurde auch hier verzichtet, um das Beispiel leichter<br />

lesbar zu halten.<br />

HDBC dbc;<br />

HSTMT stmt;<br />

SWORD num_col;<br />

RETCODE retcode;<br />

char emp_id[ 10 ];<br />

char emp_lame[ 20 ];<br />

/* Prozedur erstellen */<br />

SQLExecDirect( stmt,<br />

"CREATE PROCEDURE employees()" \<br />

" RESULT( emp_id CHAR(10), emp_lname CHAR(20))"\<br />

" BEGIN" \<br />

" SELECT emp_id, emp_lame FROM employee" \<br />

" END", SQL_NTS );<br />

/* Prozedur aufrufen - Ergebnisse ausgeben */<br />

SQLExecDirect( stmt, "CALL employees()", SQL_NTS );<br />

SQLNumResultCols( stmt, &num_col );<br />

SQLBindCol( stmt, 1, SQL_C_CHAR, &emp_id,<br />

sizeof(emp_id), NULL );<br />

SQLBindCol( stmt, 2, SQL_C_CHAR, &emp_lname,<br />

sizeof(emp_lname), NULL );<br />

for( ;; ) {<br />

retcode = SQLFetch( stmt );<br />

if( retcode == SQL_NO_DATA_FOUND ) {<br />

retcode = SQLMoreResults( stmt );<br />

if( retcode == SQL_NO_DATA_FOUND ) break;<br />

} else {<br />

do_something( emp_id, emp_lname );<br />

}<br />

}<br />

305


Umgang mit Fehlern<br />

Umgang mit Fehlern<br />

306<br />

Fehler in ODBC werden mit dem Rückgabewert jedes einzelnen ODBC-<br />

Funktionsaufrufs und entweder mit der Funktion SQLError oder der<br />

Funktion SQLGetDiagRec gemeldet. Die Funktion SQLError wurde in<br />

ODBC-Versionen bis Version 3 (ausschließlich Version 3) verwendet. Ab<br />

Version 3 wird die Funktion SQLError nicht mehr weiter entwickelt und<br />

durch die Funktion SQLGetDiagRec ersetzt.<br />

Jede ODBC-Funktion gibt einen SQLRETURN zurück, der einen der<br />

folgenden Statuscodes annehmen kann:<br />

Statuscode Beschreibung<br />

SQL_SUCCESS Kein Fehler.<br />

SQL_SUCCESS_WITH_INFO Die Funktion wurde vollständig ausgeführt, aber<br />

ein Aufruf von SQLError zeigt eine Warnung an.<br />

Der häufigste Grund <strong>für</strong> diesen Status ist, dass ein<br />

Wert zurückgegeben wurde, der <strong>für</strong> den von der<br />

Anwendung zur Verfügung gestellten Puffer zu<br />

lang ist.<br />

SQL_ERROR Die Funktion wurde wegen eines Fehlers nicht<br />

vollständig ausgeführt. Sie können SQLError<br />

ausführen, um mehr Informationen über das<br />

Problem zu erhalten.<br />

SQL_INVALID_HANDLE Ein ungültiger Umgebungs-, Verbindungs- oder<br />

Statement-Handle wurden als Argument<br />

übergeben.<br />

Dies passiert häufig, wenn ein Handle benutzt<br />

wird, nachdem es freigegeben wurde, oder falls<br />

das Handle ein Null-Zeiger ist.<br />

SQL_NO_DATA_FOUND Keine Hinweise verfügbar.<br />

Der häufigste Grund <strong>für</strong> diesen Staus ist, dass -<br />

beim Abrufen von einem Cursor - keine weiteren<br />

Zeilen mehr in dem Cursor waren.<br />

SQL_NEED_DATA Für einen Parameter werden Daten benötigt.<br />

Dies ist eine erweiterte Funktion, die in der<br />

Hilfedatei unter SQLParamData und<br />

SQLPutData beschrieben wird.


Beispiel 1<br />

Kapitel 7 ODBC-Programmierung<br />

Mit jeder Umgebung, jeder Verbindung und jedem Statement-Handle können<br />

ein oder mehrere Fehler oder Warnungen verbunden sein. Jeder Aufruf von<br />

SQLError oder SQLGetDiagRec gibt Hinweise <strong>für</strong> einen Fehler zurück<br />

und entfernt die Hinweise über diesen Fehler. Falls Sie SQLError oder<br />

SQLGetDiagRec nicht aufrufen, um alle Fehlermeldungen zu entfernen,<br />

werden die Fehlermeldungen beim nächsten Funktionsaufruf entfernt, der<br />

das gleiche Handle als Parameter übergibt.<br />

Jeder Aufruf von SQLError kann drei Handles <strong>für</strong> Umgebung, Verbindung<br />

und Anweisung übergeben. Der erste Aufruf benutzt SQL_NULL_HSTMT,<br />

um den mit einer Verbindung zusammenhängenden Fehler zu erhalten. Auf<br />

die gleiche Weise gibt ein Aufruf mit SQL_NULL_DBC und<br />

SQL_NULL_HSTMT alle mit dem Umgebungshandle zusammenhängenden<br />

Fehler zurück.<br />

Jeder Aufruf von SQLGetDiagRec kann entweder ein Umgebungs-,<br />

Verbindungs- oder Anweisungshandle übergeben. Der erste Aufruf benutzt<br />

SQL_HANDLE_DBC, um den mit einer Verbindung zusammenhängenden<br />

Fehler zurückzugeben. Der zweite Aufruf benutzt SQL_HANDLE_STMT,<br />

um den mit der soeben ausgeführten Anweisung zusammenhängenden Fehler<br />

zurückzugeben.<br />

SQLError und SQLGetDiagRec geben SQL_SUCCESS zurück, falls ein<br />

Fehler zu melden ist (nicht SQL_ERROR), und SQL_NO_DATA_FOUND,<br />

falls keine weiteren Fehler zu melden sind.<br />

Das folgende Programmfragment benutzt SQLError und gibt<br />

Rückgabecodes zurück:<br />

307


Umgang mit Fehlern<br />

Beispiel 2<br />

308<br />

/* Erforderliche Variable deklarieren */<br />

SQLHDBC dbc;<br />

SQLHSTMT stmt;<br />

SQLRETURN retcode;<br />

UCHAR errmsg[100];<br />

/* Hier wurde Code ausgelassen */<br />

retcode = SQLAllocHandle(SQL_HANDLE_STMT, dbc, &stmt );<br />

if( retcode == SQL_ERROR ){<br />

SQLError( env, dbc, SQL_NULL_HSTMT, NULL, NULL,<br />

errmsg, sizeof(errmsg), NULL );<br />

/* Annahme: print_error ist definiert.<br />

print_error( "Failed SQLAllocStmt", errmsg );<br />

return;<br />

}<br />

/* Artikel <strong>für</strong> Auftrag 2015 löschen */<br />

retcode = SQLExecDirect( stmt,<br />

"delete from sales_order_items where id=2015",<br />

SQL_NTS );<br />

if( retcode == SQL_ERROR ) {<br />

SQLError( env, dbc, stmt, NULL, NULL,<br />

errmsg, sizeof(errmsg), NULL );<br />

/* Annahme: print_error ist definiert.<br />

print_error( "Elemente konnten nicht gelöscht<br />

werden", errmsg );<br />

return;<br />

Die Beispiele übergeben den Null-Zeiger <strong>für</strong> einige der Parameter von<br />

SQLError. Die ODBC-Dokumentation enthält eine vollständige<br />

Beschreibung von SQLError und all seinen Parametern.<br />

Der folgende Auszug aus einem Beispielcode benutzt SQLGetDiagRec und<br />

Rückgabecodes:<br />

/* Erforderliche Variablen deklarieren */<br />

SQLHDBC dbc;<br />

SQLHSTMT stmt;<br />

SQLRETURN retcode;<br />

SQLSMALLINT errmsglen;<br />

SQLINTEGER errnative;<br />

UCHAR errmsg[255];<br />

UCHAR errstate[5];<br />

/* Hier wurde Code weggelassen */<br />

retcode = SQLAllocHandle(SQL_HANDLE_STMT, dbc, &stmt );<br />

if( retcode == SQL_ERROR ){<br />

SQLGetDiagRec(SQL_HANDLE_DBC, dbc, 1, errstate,<br />

&errnative, errmsg, sizeof(errmsg), &errmsglen);<br />

/* Annahme: print_error ist definiert */<br />

print_error( "Allocation failed", errstate,<br />

errnative, errmsg );<br />

return;


}<br />

/* Artikel <strong>für</strong> Auftrag 2015 löschen */<br />

Kapitel 7 ODBC-Programmierung<br />

retcode = SQLExecDirect( stmt,<br />

"delete from sales_order_items where id=2015",<br />

SQL_NTS );<br />

if( retcode == SQL_ERROR ) {<br />

SQLGetDiagRec(SQL_HANDLE_STMT, stmt, recnum,<br />

errstate,<br />

&errnative, errmsg, sizeof(errmsg), &errmsglen);<br />

/* Annahme: print_error ist definiert*/<br />

print_error("Failed to delete items", errstate,<br />

errnative, errmsg );<br />

return;<br />

}<br />

309


Umgang mit Fehlern<br />

310


KAPITEL 8<br />

Die DBTools-Schnittstelle<br />

Über dieses<br />

Kapitel<br />

Inhalt<br />

In diesem Kapitel wird beschrieben, wie die DBTools-Bibliothek benutzt<br />

wird, die zum Lieferumfang von <strong>Adaptive</strong> Server <strong>Anywhere</strong> gehört und Coder<br />

C++-Anwendungen zusätzlich mit Funktionen der<br />

Datenbankverwaltung ausstattet.<br />

Thema Seite<br />

Einführung in die DBTools-Schnittstelle 312<br />

DBTools-Schnittstelle verwenden 314<br />

DBTools-Funktionen 323<br />

DBTools-Strukturen 335<br />

DBTools-Aufzählungstypen 367<br />

311


Einführung in die DBTools-Schnittstelle<br />

Einführung in die DBTools-Schnittstelle<br />

Unterstützte<br />

Plattformen<br />

Windows CE<br />

Die dbtools.h-<br />

Header-Datei<br />

312<br />

Mit dem <strong>Sybase</strong> <strong>Adaptive</strong> Server <strong>Anywhere</strong> wird <strong>Sybase</strong> Central und eine<br />

Serie von Dienstprogrammen mitgeliefert, die <strong>für</strong> die Verwaltung von<br />

Datenbanken verwendet werden können. Diese Dienstprogramme <strong>für</strong> die<br />

Datenbankverwaltung übernehmen bestimmte Aufgaben, wie etwa das<br />

Sichern und Erstellen von Datenbanken, die Übersetzung von<br />

Transaktionslogs in SQL, usw.<br />

Alle Dienstprogramme <strong>für</strong> die Datenbankverwaltung benutzen eine<br />

gemeinsame Bibliothek, die DBTools-Bibliothek. Sie wird <strong>für</strong> die<br />

Betriebssysteme Windows Windows 95/98 und Windows NT mitgeliefert.<br />

Der Name der Bibliothek lautet dbtool8.dll.<br />

Sie können Ihre eigenen Dienstprogramme <strong>für</strong> die Datenbankverwaltung<br />

entwickeln oder Funktionen der Datenbankverwaltung in Ihre Anwendungen<br />

einbauen, indem Sie die DBTools-Bibliothek aufrufen. In diesem Kapitel<br />

wird die Schnittstelle zur DBTools-Bibliothek beschrieben. Wenn Sie dieses<br />

Kapitel lesen, sollten Sie mit der Methode vertraut sein, mit der die von<br />

Ihnen benutzte Entwicklungsumgebung DLLs aufruft.<br />

Die DBTools-Bibliothek hat Funktionen oder Eintrittspunkte <strong>für</strong> jedes<br />

einzelne Dienstprogramm zur Datenbankverwaltung. Außerdem müssen<br />

Funktionen vor dem Aufruf anderer DBTools-Funktionen, sowie im<br />

Anschluss an die Verwendung anderer DBTools-Funktionen aufgerufen<br />

werden.<br />

Die Bibliothek dbtool8.dll wird <strong>für</strong> Windows CE geliefert, enthält aber nur<br />

Programmeinstiegspunkte <strong>für</strong> DBToolsInit, DBToolsFini, DBRemoteSQL<br />

und DBSynchronizeLog. Andere Tools werden <strong>für</strong> Windows CE nicht<br />

bereitgestellt.<br />

Die DBTools-Header-Datei, die mit dem <strong>Adaptive</strong> Server <strong>Anywhere</strong><br />

mitgeliefert wird, enthält eine Liste der Eintrittspunkte zur DBTools-<br />

Bibliothek und liefert die Strukturen, die benutzt werden, um Daten an die<br />

Bibliothek zu übergeben und von ihr zu beziehen. Die Datei dbtools.h wird<br />

im Unterverzeichnis h im Installationsverzeichnis eingerichtet. In der Datei<br />

dbtools.h finden Sie die neuesten Informationen über die Eintrittspunkte und<br />

die Strukturbestandteile.<br />

Die Header-Datei dbtools.H enthält zwei andere Dateien:<br />

♦ sqlca.h Diese Datei ist <strong>für</strong> die Auflösung diverser Makros, nicht <strong>für</strong><br />

SQLCA selbst, vorgesehen.<br />

♦ dllapi.h Diese Datei definiert Präprozessor-Makros <strong>für</strong><br />

betriebssystemabhängige und sprachenabhängige Makros.


Kapitel 8 Die DBTools-Schnittstelle<br />

Die Header-Datei sqldef.h enthält außerdem Fehler-Rückgabewerte.<br />

313


DBTools-Schnittstelle verwenden<br />

DBTools-Schnittstelle verwenden<br />

Importbibliotheken verwenden<br />

Unterstützte<br />

Plattformen<br />

314<br />

Dieser Abschnitt enthält einen Überblick über die Entwicklung von<br />

Anwendungen, die die DBTools-Schnittstelle <strong>für</strong> die Verwaltung der<br />

Datenbanken verwenden.<br />

Damit die DBTools-Funktionen verwendet werden können, müssen Sie Ihre<br />

Anwendung mit einer DBTools Importbibliothek verknüpfen, die die<br />

erforderlichen Funktionsdefinitionen enthält.<br />

Importbibliotheken sind Compiler-spezifisch und werden <strong>für</strong> Windows-<br />

Betriebssysteme mit Ausnahme von Windows CE geliefert.<br />

Importbibliotheken <strong>für</strong> die DBTools-Schnittstelle werden mit dem <strong>Adaptive</strong><br />

Server <strong>Anywhere</strong> mitgeliefert und können im Unterverzeichnis lib des<br />

jeweiligen Betriebssystemverzeichnisses im Installationsverzeichnis<br />

gefunden werden. Folgende DBTools-Importbibliotheken werden geliefert:<br />

Compiler Bibliothek<br />

Watcom win32\dbtlstw.lib<br />

Microsoft win32\dbtlstM.lib<br />

Borland win32\dbtlstB.lib<br />

DBTools-Bibliothek starten und beenden<br />

Bevor Sie andere DBTools-Funktionen verwenden, müssen Sie DBToolsInit<br />

aufrufen. Wenn Sie die DBTools DLL nicht mehr verwenden, müssen Sie<br />

DBToolsFini aufrufen.<br />

Die Funktionen DBToolsInit und DBToolsFini bezwecken hauptsächlich,<br />

der DBTools-DLL das Laden der <strong>Adaptive</strong> Server <strong>Anywhere</strong> Sprachen-DLL<br />

zu ermöglichen. Die Sprachen-DLL enthält lokalisierte Versionen aller<br />

Fehlermeldungen und Bedieneraufforderungen, die DBTools intern<br />

verwendet. Wenn DBToolsFini nicht aufgerufen wird, kann die<br />

Referenznummer der Sprachen-DLL nicht heruntergezählt werden, sodass<br />

diese DLL nicht entladen wird. Achten Sie daher immer darauf, dass zu<br />

jedem Aufruf von DBToolsInit als Gegenstück DBToolsFini aufgerufen<br />

wird.


Kapitel 8 Die DBTools-Schnittstelle<br />

Im folgenden Programmcodebeispiel wird gezeigt, wie DBTools aufgerufen<br />

und wieder bereinigt werden:<br />

// Deklarationen<br />

a_dbtools_info info;<br />

short ret;<br />

DBTools-Funktionen aufrufen<br />

//Initialisierung der a_dbtools_info-Struktur<br />

memset( &info, 0, sizeof( a_dbtools_info) );<br />

info.errorrtn = (MSG_CALLBACK)MyErrorRtn;<br />

// Initialisierung von DBTools<br />

ret = DBToolsInit( &info );<br />

if( ret != EXIT_OKAY ) {<br />

// DLL-Initialisierung fehlgeschlagen<br />

…<br />

}<br />

// einige DBTools-Routinen aufrufen. . .<br />

…<br />

// DBTools dll bereinigen<br />

DBToolsFini( &info );<br />

Alle Tools werden aufgerufen, indem erst eine Struktur ausgefüllt und dann<br />

eine Funktion (oder ein Eintrittspunkt) in der DBTools-DLL aufgerufen<br />

wird. Jeder Eintrittspunkt nimmt einen Zeiger zu einer bestimmten Struktur<br />

als Argument.<br />

Im folgenden Beispiel wird gezeigt, wie die DBBackup-Funktion unter<br />

einem Windows-Betriebssystem verwendet wird.<br />

// Initialisierung der Struktur<br />

a_backup_db backup_info;<br />

memset( &backup_info, 0, sizeof( backup_info ) );<br />

// Struktur ausfüllen<br />

backup_info.version = DB_TOOLS_VERSION_NUMBER;<br />

backup_info.output_dir = "C:\BACKUP";<br />

backup_info.connectparms<br />

="uid=DBA;pwd=SQL;dbf=asademo.db";<br />

backup_info.startline = "dbeng8.EXE";<br />

backup_info.confirmrtn = (MSG_CALLBACK) ConfirmRtn ;<br />

backup_info.errorrtn = (MSG_CALLBACK) ErrorRtn ;<br />

backup_info.msgrtn = (MSG_CALLBACK) MessageRtn ;<br />

backup_info.statusrtn = (MSG_CALLBACK) StatusRtn ;<br />

backup_info.backup_database = TRUE;<br />

// Sicherung starten<br />

DBBackup( &backup_info );<br />

315


DBTools-Schnittstelle verwenden<br />

316<br />

$ Hinweise zu den Bestandteilen der DBTools-Strukturen finden Sie<br />

unter "DBTools-Strukturen" auf Seite 335.<br />

Rückgabecodes der Softwarekomponenten<br />

Alle Datenbanktools werden als Eintrittspunkt in einer DLL geliefert. Diese<br />

Eintrittspunkte verwenden die folgenden Rückgabecodes:<br />

Program<br />

mcode<br />

Erklärung<br />

0 Erfolg<br />

1 Allgemeiner Ausfall<br />

2 Ungültiges Dateiformat<br />

3 Datei nicht gefunden, kann nicht geöffnet werden<br />

4 Kein Speicher mehr<br />

5 Beendet vom Benutzer<br />

6 Fehlgeschlagene Kommunikationen<br />

7 Erforderlicher Datenbankname fehlt<br />

8 Falsches Client/Server-Protokoll<br />

9 Keine Verbindung mit dem Datenbankserver möglich<br />

10 Datenbankserver läuft nicht<br />

11 Datenbankserver nicht gefunden<br />

254 Stoppzeit erreicht<br />

Callback-Funktionen verwenden<br />

Nutzung der<br />

Callback-<br />

Funktionen<br />

255 Ungültige Parameter in der Befehlszeile<br />

Einige Elemente in der DBTools-Struktur sind vom Typ<br />

MSG_CALLBACK. Es handelt sich dabei um Zeiger auf Callback-<br />

Funktionen.<br />

Mit Callback-Funktionen können DBTools-Funktionen die Kontrolle der<br />

Verarbeitung an die aufrufende Anwendung des Benutzers zurückgeben. Die<br />

DBTools-Bibliothek benutzt Callback-Funktionen zur Verarbeitung von<br />

Nachrichten, die von den DBTools-Funktionen an den Benutzer gesandt<br />

werden, <strong>für</strong> vier Zwecke:


Callback-Funktion<br />

einer Struktur<br />

zuordnen<br />

Beispiel <strong>für</strong> eine<br />

Callback-Funktion<br />

mit Bestätigung<br />

Beispiel <strong>für</strong> eine<br />

Callback-Funktion<br />

mit Fehlermeldung<br />

Kapitel 8 Die DBTools-Schnittstelle<br />

♦ Bestätigung Wird aufgerufen, wenn eine Aktion vom Benutzer bestätigt<br />

werden muss. Falls zum Beispiel das Sicherungsverzeichnis nicht<br />

vorhanden ist, fragt die Tools-DLL, ob es erzeugt werden soll.<br />

♦ Fehlermeldung Wird aufgerufen, um eine Nachricht zu bearbeiten,<br />

wenn ein Fehler auftritt, zum Beispiel, wenn ein Vorgang nicht<br />

genügend Speicherplatz hat<br />

♦ Informationsnachricht Wird aufgerufen, um den Benutzer zu<br />

informieren, wie zum Beispiel eine Nachricht mit den Namen der<br />

Tabelle, die gerade gesichert wird<br />

♦ Statusinformation Wird aufgerufen, um den Status eines Vorgangs<br />

anzuzeigen, wie zum Beispiel, wie viel Prozent einer Tabelle entladen<br />

sind<br />

Sie können der Struktur direkt eine Callback-Routine zuordnen. Die folgende<br />

Anweisung ist ein Beispiel <strong>für</strong> die Verwendung einer Sicherungsstruktur:<br />

backup_info.errorrtn = (MSG_CALLBACK) MyFunction<br />

MSG_CALLBACK ist in der Header-Datei dllapi.h definiert, die im<br />

<strong>Adaptive</strong> Server <strong>Anywhere</strong> enthalten ist. Tools-Routinen können<br />

Nachrichten in die aufrufende Anwendung übergeben, die dann in der<br />

passenden Benutzeroberfläche dargestellt werden sollten; das kann eine<br />

Fensterumgebung sein, die Standardausgabe eines zeichenbasierten Systems<br />

oder andere Benutzeroberflächen.<br />

Im folgenden Beispiel fragt eine Routine den Benutzer nach einer<br />

Bestätigung mit YES oder NO und gibt die Antwort des Benutzers zurück:<br />

extern short _callback ConfirmRtn(<br />

char far * question )<br />

{<br />

int ret;<br />

if( question != NULL ) {<br />

ret = MessageBox( HwndParent, question,<br />

"Confirm", MB_ICONEXCLAMTION|MB_YESNO );<br />

}<br />

return( 0 );<br />

}<br />

Im folgenden Beispiel zeigt eine Routine zur Behandlung einer<br />

Fehlermeldung die Fehlermeldung in einer Meldungsbox an.<br />

extern short _callback ErrorRtn(<br />

char far * errorstr )<br />

{<br />

if( errorstr != NULL ) {<br />

ret = MessageBox( HwndParent, errorstr,<br />

"Backup Error", MB_ICONSTOP|MB_OK );<br />

}<br />

317


DBTools-Schnittstelle verwenden<br />

Beispiel <strong>für</strong> eine<br />

Callback-Funktion<br />

mit Nachricht<br />

Beispiel <strong>für</strong> eine<br />

Callback-Funktion<br />

mit Statusmeldung<br />

318<br />

}<br />

return( 0 );<br />

Eine typische Implementierung einer Callback-Funktion, die eine Nachricht<br />

am Bildschirm ausgibt:<br />

extern short _callback MessageRtn(<br />

char far * errorstr )<br />

{<br />

if( messagestr != NULL ) {<br />

OutputMessageToWindow( messagestr );<br />

}<br />

return( 0 );<br />

}<br />

Eine Status-Callback-Routine wird aufgerufen, wenn die Tools den Status<br />

eines Vorgangs anzeigen müssen (zum Beispiel wie viel Prozent einer<br />

Tabelle entladen sind). Im folgenden Beispiel sehen Sie eine typische<br />

Implementierung, die lediglich die Nachricht am Bildschirm ausgibt:<br />

extern short _callback StatusRtn(<br />

char far * statusstr )<br />

{<br />

if( statusstr == NULL ) {<br />

return FALSE;<br />

}<br />

OutputMessageToWindow( statustr );<br />

return TRUE;<br />

}<br />

Versionsnummern und Kompatibilität<br />

Jede Struktur enthält ein Element, das die Versionsnummer angibt. Sie<br />

sollten dieses Versionselement benutzen, um die Version der DBTools-<br />

Bibliothek zu speichern, <strong>für</strong> die Ihre Anwendung entwickelt wurde. Die<br />

aktuelle Version der DBTools-Bibliothek ist als Konstante in der Header-<br />

Datei dbtools.h enthalten.<br />

v Um einer Struktur die aktuelle Versionsnummer zuzuordnen, gehen<br />

Sie wie folgt vor:<br />

♦ Ordnen Sie die Versionskonstante dem Versionselement der Struktur zu,<br />

bevor Sie die DBTools-Funktion aufrufen. Die folgende Zeile ordnet die<br />

aktuelle Version einer Sicherungsstruktur zu:<br />

backup_info.version = DB_TOOLS_VERSION_NUMBER;


Kompatibilität<br />

Bit-Felder benutzen<br />

Ein Beispiel <strong>für</strong> DBTools<br />

Kapitel 8 Die DBTools-Schnittstelle<br />

Die Versionsnummer ermöglicht es der Anwendung, auch in Zukunft mit<br />

neueren Versionen der DBTools-Bibliothek weiterzuarbeiten. Die DBTools-<br />

Funktionen sorgen mit Hilfe der Versionsnummern, die von Ihrer<br />

Anwendung zur Verfügung gestellt werden, da<strong>für</strong>, dass Ihre Anwendung<br />

auch dann weiterarbeiten kann, wenn neue Elemente zur DBTools-Struktur<br />

hinzugefügt wurden.<br />

Anwendungen arbeiten nicht mit älteren Versionen der DBTools-Bibliothek<br />

zusammen.<br />

Viele DBTools-Strukturen benutzen Bit-Felder, um Boolesche Informationen<br />

kompakt zu speichern. Die Sicherungsstruktur zum Beispiel hat folgende<br />

Bit-Felder:<br />

a_bit_field backup_database : 1;<br />

a_bit_field backup_logfile : 1;<br />

a_bit_field backup_writefile: 1;<br />

a_bit_field no_confirm : 1;<br />

a_bit_field quiet : 1;<br />

a_bit_field rename_log : 1;<br />

a_bit_field truncate_log : 1;<br />

a_bit_field rename_local_log: 1;<br />

Jedes Bit-Feld ist ein Bit lang, angezeigt durch eine 1 rechts neben dem<br />

Doppelpunkt in der Strukturdeklaration. Der hier verwendete Datentyp hängt<br />

vom Wert ab, der am Anfang von dbtools.h a_bit_field zugeordnet wurde,<br />

und ist abhängig vom Betriebssystem.<br />

Sie ordnen dem Bit-Feld einen Wert von 0 (Null) oder 1 zu, um einen<br />

Booleschen Wert an die Struktur zu übergeben.<br />

Dieses Beispiel sowie Hinweise zum Kompilieren finden Sie im<br />

Unterverzeichnis Samples\ASA\DBTools Ihres SQL <strong>Anywhere</strong>-<br />

Verzeichnisses. Das Beispielprogramm selbst ist<br />

Samples\ASA\DBTools\main.c. Das Beispiel veranschaulicht, wie die<br />

DBTools-Bibliothek zum Sichern der Datenbank eingesetzt werden kann.<br />

# define WINNT<br />

319


DBTools-Schnittstelle verwenden<br />

320<br />

#include <br />

#include "windows.h"<br />

#include "string.h"<br />

#include "dbtools.h"<br />

extern short _callback ConfirmCallBack(char far * str){<br />

if( MessageBox( NULL, str, "Backup",<br />

MB_YESNO|MB_ICONQUESTION ) == IDYES ) {<br />

return 1;<br />

}<br />

return 0;<br />

}<br />

extern short _callback MessageCallBack( char far * str){<br />

if( str != NULL ) {<br />

fprintf( stdout, "%s", str );<br />

fprintf( stdout, "\n" );<br />

fflush( stdout );<br />

}<br />

return 0;<br />

}<br />

extern short _callback StatusCallBack( char far * str ){<br />

if( str != NULL ) {<br />

fprintf( stdout, "%s", str );<br />

fprintf( stdout, "\n" );<br />

fflush( stdout );<br />

}<br />

return 0;<br />

}<br />

extern short _callback ErrorCallBack( char far * str ){<br />

if( str != NULL ) {<br />

fprintf( stdout, "%s", str );<br />

fprintf( stdout, "\n" );<br />

fflush( stdout );<br />

}<br />

return 0;<br />

}<br />

// Haupteintrittspunkt in das Programm.<br />

int main( int argc, char * argv[] ){<br />

a_backup_db backup_info;<br />

a_dbtools_info dbtinfo;<br />

char dir_name[ _MAX_PATH + 1];<br />

char connect[ 256 ];<br />

HINSTANCE hinst;<br />

FARPROC dbbackup;<br />

FARPROC dbtoolsinit;<br />

FARPROC dbtoolsfini;


Kapitel 8 Die DBTools-Schnittstelle<br />

// Immer mit 0 initialisieren, sodass neue Versionen<br />

// der Struktur kompatibel sind.<br />

memset( &backup_info, 0, sizeof( a_backup_db ) );<br />

backup_info.version = DB_TOOLS_VERSION_8_0_00;<br />

backup_info.quiet = 0;<br />

backup_info.no_confirm = 0;<br />

backup_info.confirmrtn =<br />

(MSG_CALLBACK)ConfirmCallBack;<br />

backup_info.errorrtn = (MSG_CALLBACK)ErrorCallBack;<br />

backup_info.msgrtn = (MSG_CALLBACK)MessageCallBack;<br />

backup_info.statusrtn = (MSG_CALLBACK)StatusCallBack;<br />

if( argc > 1 ) {<br />

strncpy( dir_name, argv[1], _MAX_PATH );<br />

} else {<br />

// DBTools erwartet nicht den<br />

// nachgestellten Schraegstrich<br />

strcpy( dir_name, "c:\\temp" );<br />

}<br />

backup_info.output_dir = dir_name;<br />

if( argc > 2 ) {<br />

strncpy( connect, argv[2], 255 );<br />

} else {<br />

// Annahme: die Engine läuft bereits.<br />

strcpy( connect, "DSN=ASA 8.0 Sample" );<br />

}<br />

backup_info.connectparms = connect;<br />

backup_info.startline = "";<br />

backup_info.quiet = 0;<br />

backup_info.no_confirm = 0;<br />

backup_info.backup_database = 1;<br />

backup_info.backup_logfile = 1;<br />

backup_info.backup_writefile = 1;<br />

backup_info.rename_log = 0;<br />

backup_info.truncate_log = 0;<br />

hinst = LoadLibrary( "dbtool8.dll" );<br />

if( hinst == NULL ) {<br />

// Fehlgeschlagen<br />

return 0;<br />

}<br />

321


DBTools-Schnittstelle verwenden<br />

322<br />

}<br />

dbtinfo.errorrtn = (MSG_CALLBACK)ErrorCallBack;<br />

dbbackup = GetProcAddress( (HMODULE)hinst,<br />

"_DBBackup@4" );<br />

dbtoolsinit = GetProcAddress( (HMODULE)hinst,<br />

"_DBToolsInit@4" );<br />

dbtoolsfini = GetProcAddress( (HMODULE)hinst,<br />

"_DBToolsFini@4" );<br />

(*dbtoolsinit)( &dbtinfo );<br />

(*dbbackup)( &backup_info );<br />

(*dbtoolsfini)( &dbtinfo );<br />

FreeLibrary( hinst );<br />

return 0;


DBTools-Funktionen<br />

DBBackup-Funktion<br />

Funktion<br />

Prototyp<br />

Parameter<br />

Rückgabewert<br />

Anwendung<br />

Siehe auch<br />

Kapitel 8 Die DBTools-Schnittstelle<br />

Dieser Abschnitt beschreibt die Funktionen in der DBTools-Bibliothek. Die<br />

Funktionen sind alphabetisch aufgelistet.<br />

Datenbanksicherungs-Funktion. Diese Funktion wird von dem Befehlszeilen-<br />

Dienstprogramm dbbackup benutzt.<br />

short DBBackup ( const a_backup_db * Sicherungsdatenbank );<br />

Parameter Beschreibung<br />

Sicherungsdatenbank<br />

Zeiger auf eine "a_backup_db-Struktur" auf Seite 335<br />

Ein Rückgabecode wie in "Rückgabecodes der Softwarekomponenten" auf<br />

Seite 316 beschrieben.<br />

Die Funktion DBBackup verwaltet alle Datenbanksicherungs-Aufgaben.<br />

$ Die Beschreibung dieser Aufgaben finden Sie unter "Das<br />

Sicherungsdienstprogramm" auf Seite 484 der Dokumentation ASA<br />

Datenbankadministration.<br />

"a_backup_db-Struktur" auf Seite 335<br />

DBChangeLogName-Funktion<br />

Funktion<br />

Prototyp<br />

Parameter<br />

Rückgabewert<br />

Anwendung<br />

Ändert den Namen der Transaktionslogdatei. Diese Funktion wird von dem<br />

Befehlszeilen-Dienstprogramm dblog benutzt.<br />

short DBChangeLogName ( const a_change_log * Änderungslog );<br />

Parameter Beschreibung<br />

Änderungslog Zeiger auf eine "a_change_log-Struktur" auf Seite 337<br />

Ein Rückgabecode wie in "Rückgabecodes der Softwarekomponenten" auf<br />

Seite 316 beschrieben.<br />

Die Option -t des Dienstprogramms dblog ändert den Namen des<br />

Transaktionslogs. DBChangeLogName liefert eine Programmierschnittstelle<br />

zu dieser Funktion.<br />

323


DBTools-Funktionen<br />

Siehe auch<br />

DBChangeWriteFile-Funktion<br />

Funktion<br />

Prototyp<br />

Parameter<br />

Rückgabewert<br />

Anwendung<br />

Siehe auch<br />

DBCollate-Funktion<br />

Funktion<br />

Prototyp<br />

Parameter<br />

Rückgabewert<br />

Anwendung<br />

324<br />

$ Eine Beschreibung des Dienstprogramms dblog finden Sie unter "Das<br />

Transaktionslog-Dienstprogramm" auf Seite 564 der Dokumentation ASA<br />

Datenbankadministration.<br />

"a_change_log-Struktur" auf Seite 337<br />

Ändert eine Write-Datei, sodass sie auf eine andere Datenbankdatei zugreift.<br />

Diese Funktion wird von dem Dienstprogramm dbwrite benutzt, wenn die<br />

Option -d angewendet wird.<br />

short DBChangeWriteFile ( const a_writefile * Write-Datei );<br />

Parameter Beschreibung<br />

Write-Datei Zeiger auf eine "a_writefile-Struktur" auf Seite 364<br />

Ein Rückgabecode wie in "Rückgabecodes der Softwarekomponenten" auf<br />

Seite 316 beschrieben.<br />

$ Informationen über das Write-Datei-Dienstprogramm und seine<br />

Eigenschaften finden Sie unter "Das Write-Datei-Dienstprogramm" auf<br />

Seite 592 der Dokumentation ASA Datenbankadministration.<br />

"DBCreateWriteFile-Funktion" auf Seite 326<br />

"DBStatusWriteFile-Funktion" auf Seite 329<br />

"a_writefile-Struktur" auf Seite 364<br />

Extrahiert eine Kollatierungssequenz aus einer Datenbank.<br />

short DBCollate ( const a_db_collation * DB-Kollatierung );<br />

Parameter Beschreibung<br />

DB-Kollatierung Zeiger auf eine "a_db_collation-Struktur" auf Seite 344<br />

Ein Rückgabecode wie in "Rückgabecodes der Softwarekomponenten" auf<br />

Seite 316 beschrieben.<br />

$ Informationen über das Kollatierungs-Dienstprogramm und seine<br />

Eigenschaften finden Sie unter "Das Kollatierungs-Dienstprogramm" auf<br />

Seite 489 der Dokumentation ASA Datenbankadministration


Siehe auch<br />

DBCompress-Funktion<br />

Funktion<br />

Prototyp<br />

Parameter<br />

Rückgabewert<br />

Anwendung<br />

Siehe auch<br />

DBCreate-Funktion<br />

Funktion<br />

Prototyp<br />

Parameter<br />

Rückgabewert<br />

Anwendung<br />

Siehe auch<br />

"a_db_collation-Struktur" auf Seite 344<br />

Kapitel 8 Die DBTools-Schnittstelle<br />

Komprimiert eine Datenbankdatei. Diese Funktion wird von dem<br />

Dienstprogramm dbshrink benutzt.<br />

short DBCompress ( const a_compress_db * Komprimierte_DB );<br />

Parameter Beschreibung<br />

Komprimierte_DB<br />

Zeiger auf eine "a_compress_db-Struktur" auf Seite 339<br />

Ein Rückgabecode wie in "Rückgabecodes der Softwarekomponenten" auf<br />

Seite 316 beschrieben.<br />

$ Informationen über das Komprimierungs-Dienstprogramm und seine<br />

Eigenschaften finden Sie unter "Das Komprimierungs-Dienstprogramm" auf<br />

Seite 495 der Dokumentation ASA Datenbankadministration.<br />

"a_compress_db-Struktur" auf Seite 339<br />

Erstellt eine Datenbank. Diese Funktion wird von dem Dienstprogramm<br />

dbinit benutzt.<br />

short DBCreate ( const a_create_db * Erstellte_DB );<br />

Parameter Beschreibung<br />

Erstellte_DB Zeiger auf eine "a_create_db-Struktur" auf Seite 341<br />

Ein Rückgabecode wie in "Rückgabecodes der Softwarekomponenten" auf<br />

Seite 316 beschrieben.<br />

$ Informationen über das Initialisierungsdienstprogramm finden Sie unter<br />

"Das Initialisierungs-Dienstprogramm" auf Seite 515 der Dokumentation<br />

ASA Datenbankadministration.<br />

"a_create_db-Struktur" auf Seite 341<br />

325


DBTools-Funktionen<br />

DBCreateWriteFile-Funktion<br />

Funktion<br />

Prototyp<br />

Parameter<br />

Rückgabewert<br />

Anwendung<br />

Siehe auch<br />

DBCrypt-Funktion<br />

Funktion<br />

Prototyp<br />

Parameter<br />

Rückgabewert<br />

Anwendung<br />

Siehe auch<br />

326<br />

Erstellt eine Write-Datei. Diese Funktion wird von dem Dienstprogramm<br />

dbwrite benutzt, wenn die Option -c angewendet wird.<br />

short DBCreateWriteFile ( const a_writefile * Write-Datei );<br />

Parameter Beschreibung<br />

Write-Datei Zeiger auf eine "a_writefile-Struktur" auf Seite 364<br />

Ein Rückgabecode wie in "Rückgabecodes der Softwarekomponenten" auf<br />

Seite 316 beschrieben.<br />

$ Informationen über das Write-Datei-Dienstprogramm und seine<br />

Eigenschaften finden Sie unter "Das Write-Datei-Dienstprogramm" auf<br />

Seite 592 der Dokumentation ASA Datenbankadministration.<br />

"DBChangeWriteFile-Funktion" auf Seite 324<br />

"DBStatusWriteFile-Funktion" auf Seite 329<br />

"a_writefile-Struktur" auf Seite 364<br />

Dient zum Verschlüsseln einer Datenbankdatei. Diese Funktion wird von<br />

dem Dienstprogramm dbinit benutzt, wenn die Option -e angewendet wird.<br />

short DBCrypt ( const a_crypt_db * Verschlüsselte_DB );<br />

Parameter Beschreibung<br />

Verschlüsselte_DB<br />

Zeiger auf eine "a_crypt_db-Struktur" auf Seite 343<br />

Ein Rückgabecode wie in "Rückgabecodes der Softwarekomponenten" auf<br />

Seite 316 beschrieben.<br />

$ Weitere Hinweise zum Verschlüsseln von Datenbanken finden Sie<br />

unter "Datenbank mit dem Befehlszeilenprogramm ""dbinit"" erstellen" auf<br />

Seite 516 der Dokumentation ASA Datenbankadministration.<br />

"a_crypt_db-Struktur" auf Seite 343


DBErase-Funktion<br />

Funktion<br />

Prototyp<br />

Parameter<br />

Rückgabewert<br />

Anwendung<br />

Siehe auch<br />

DBExpand-Funktion<br />

Funktion<br />

Prototyp<br />

Parameter<br />

Rückgabewert<br />

Anwendung<br />

Siehe auch<br />

DBInfo-Funktion<br />

Funktion<br />

Kapitel 8 Die DBTools-Schnittstelle<br />

Löscht eine Datenbankdatei und/oder ein Transaktionslog. Diese Funktion<br />

wird von dem Dienstprogramm dberase benutzt.<br />

short DBErase ( const an_erase_db * Zu_löschende_DB );<br />

Parameter Beschreibung<br />

Zu_löschende_DB<br />

Zeiger auf eine "an_erase_db-Struktur" auf Seite 349<br />

Ein Rückgabecode wie in "Rückgabecodes der Softwarekomponenten" auf<br />

Seite 316 beschrieben.<br />

$ Informationen über das Lösch-Dienstprogramm und seine<br />

Eigenschaften finden Sie unter "Das Dienstprogramm zum Löschen der<br />

Datenbank" auf Seite 508 der Dokumentation ASA Datenbankadministration.<br />

"an_erase_db-Struktur" auf Seite 349<br />

Dekomprimiert eine Datenbankdatei. Diese Funktion wird von dem<br />

Dienstprogramm dbexpand benutzt.<br />

short DBExpand ( const an_expand_db * Zu_expandierende_DB );<br />

Parameter Beschreibung<br />

Zu_expandierende_DB<br />

Zeiger auf eine "an_expand_db-Struktur" auf Seite 350<br />

Ein Rückgabecode wie in "Rückgabecodes der Softwarekomponenten" auf<br />

Seite 316 beschrieben.<br />

$ Informationen über das Dekomprimierungs-Dienstprogramm und seine<br />

Eigenschaften finden Sie unter "Das Dekomprimierungs-Dienstprogramm"<br />

auf Seite 569 der Dokumentation ASA Datenbankadministration.<br />

"an_expand_db-Struktur" auf Seite 350<br />

Gibt Informationen über eine Datenbankdatei zurück. Diese Funktion wird<br />

von dem Dienstprogramm dbinfo benutzt.<br />

327


DBTools-Funktionen<br />

Prototyp<br />

Parameter<br />

Rückgabewert<br />

Anwendung<br />

Siehe auch<br />

DBInfoDump-Funktion<br />

Funktion<br />

Prototyp<br />

Parameter<br />

Rückgabewert<br />

Anwendung<br />

Siehe auch<br />

DBInfoFree-Funktion<br />

Funktion<br />

Prototyp<br />

328<br />

short DBInfo ( const a_db_info * DB-Info );<br />

Parameter Beschreibung<br />

DB-Info Zeiger auf eine "a_db_info-Struktur" auf Seite 345<br />

Ein Rückgabecode wie in "Rückgabecodes der Softwarekomponenten" auf<br />

Seite 316 beschrieben.<br />

$ Informationen über das Informations-Dienstprogramm und seine<br />

Eigenschaften finden Sie unter "Das Informations-Dienstprogramm" auf<br />

Seite 513 der Dokumentation ASA Datenbankadministration.<br />

"DBInfoDump-Funktion" auf Seite 328<br />

"DBInfoFree-Funktion" auf Seite 328<br />

"a_db_info-Struktur" auf Seite 345<br />

Gibt Informationen über eine Datenbankdatei zurück. Diese Funktion wird<br />

von dem Dienstprogramm dbinfo benutzt, wenn die Option -u angewendet<br />

wird.<br />

short DBInfoDump ( const a_db_info * DB-Info );<br />

Parameter Beschreibung<br />

DB-Info Zeiger auf eine "a_db_info-Struktur" auf Seite 345<br />

Ein Rückgabecode wie in "Rückgabecodes der Softwarekomponenten" auf<br />

Seite 316 beschrieben.<br />

$ Informationen über das Informations-Dienstprogramm und seine<br />

Eigenschaften finden Sie unter "Das Informations-Dienstprogramm" auf<br />

Seite 513 der Dokumentation ASA Datenbankadministration.<br />

"DBInfo-Funktion" auf Seite 327<br />

"DBInfoFree-Funktion" auf Seite 328<br />

"a_db_info-Struktur" auf Seite 345<br />

Wird aufgerufen, um nach dem Aufruf der Funktion DBInfoDump<br />

Ressourcen freizugeben.<br />

short DBInfoFree ( const a_db_info * DB-Info );


Parameter<br />

Rückgabewert<br />

Anwendung<br />

Siehe auch<br />

DBLicense-Funktion<br />

Funktion<br />

Prototyp<br />

Parameter<br />

Rückgabewert<br />

Anwendung<br />

Siehe auch<br />

DBStatusWriteFile-Funktion<br />

Funktion<br />

Prototyp<br />

Parameter<br />

Parameter Beschreibung<br />

Kapitel 8 Die DBTools-Schnittstelle<br />

DB-Info Zeiger auf eine "a_db_info-Struktur" auf Seite 345<br />

Ein Rückgabecode wie in "Rückgabecodes der Softwarekomponenten" auf<br />

Seite 316 beschrieben.<br />

$ Informationen über das Informations-Dienstprogramm und seine<br />

Eigenschaften finden Sie unter "Das Informations-Dienstprogramm" auf<br />

Seite 513 der Dokumentation ASA Datenbankadministration.<br />

"DBInfo-Funktion" auf Seite 327<br />

"DBInfoDump-Funktion" auf Seite 328<br />

"a_db_info-Struktur" auf Seite 345<br />

Wird aufgerufen, um die Lizenzdaten des Datenbankservers zu ändern oder<br />

mitzuteilen.<br />

short DBLicense ( const a_db_lic_info * DB-Liz.-Info );<br />

Parameter Beschreibung<br />

DB-Liz.-Info Zeiger auf eine "a_dblic_info-Struktur" auf Seite 348<br />

Ein Rückgabecode wie in "Rückgabecodes der Softwarekomponenten" auf<br />

Seite 316 beschrieben.<br />

$ Informationen über das Informations-Dienstprogramm und seine<br />

Eigenschaften finden Sie unter "Das Informations-Dienstprogramm" auf<br />

Seite 513 der Dokumentation ASA Datenbankadministration.<br />

"a_dblic_info-Struktur" auf Seite 348<br />

Ruft den Status einer Write-Datei ab. Diese Funktion wird von dem<br />

Dienstprogramm dbwrite benutzt, wenn die Option -s angewendet wird.<br />

short DBStatusWriteFile ( const a_writefile * Write-Datei );<br />

Parameter Beschreibung<br />

Write-Datei Zeiger auf eine "a_writefile-Struktur" auf Seite 364<br />

329


DBTools-Funktionen<br />

Rückgabewert<br />

Anwendung<br />

Siehe auch<br />

DBSynchronizeLog-Funktion<br />

Funktion<br />

Prototyp<br />

Parameter<br />

Rückgabewert<br />

Anwendung<br />

DBToolsFini-Funktion<br />

Funktion<br />

Prototyp<br />

Parameter<br />

Rückgabewert<br />

Anwendung<br />

330<br />

Ein Rückgabecode wie in "Rückgabecodes der Softwarekomponenten" auf<br />

Seite 316 beschrieben.<br />

$ Informationen über das Write-Datei-Dienstprogramm und seine<br />

Eigenschaften finden Sie unter "Das Write-Datei-Dienstprogramm" auf<br />

Seite 592 der Dokumentation ASA Datenbankadministration.<br />

"DBChangeWriteFile-Funktion" auf Seite 324<br />

"DBCreateWriteFile-Funktion" auf Seite 326<br />

"a_writefile-Struktur" auf Seite 364<br />

Synchronisiert eine Datenbank mit einem MobiLink Synchronisationsserver.<br />

short DBSynchronizeLog( const a _sync_db * Synchronisierte_DB );<br />

Parameter Beschreibung<br />

Synchronisierte_DB<br />

Zeiger auf eine "a_sync_db-Struktur" auf Seite 352<br />

Ein Rückgabecode wie in "Rückgabecodes der Softwarekomponenten" auf<br />

Seite 316 beschrieben.<br />

$ Weitere Informationen über diese Features finden Sie unter<br />

"Synchronisation einleiten" auf Seite 149 der Dokumentation MobiLink<br />

Benutzerhandbuch.<br />

Vermindert den Zähler und gibt Ressourcen frei, nachdem eine Anwendung<br />

die DBTools-Bibliothek nicht mehr benötigt.<br />

short DBToolsFini ( const a_dbtools_info * DBTools-Info );<br />

Parameter Beschreibung<br />

DBTools-Info Zeiger auf eine "a_dbtools_info-Struktur" auf Seite 349<br />

Ein Rückgabecode wie in "Rückgabecodes der Softwarekomponenten" auf<br />

Seite 316 beschrieben.<br />

Die Funktion DBToolsFini muss am Ende jeder Anwendung aufgerufen<br />

werden, die die DBTools-Schnittstelle benutzt. Falls diese Funktion nicht<br />

aufgerufen wird, kann das zum Verlust von Speicherressourcen führen.


Siehe auch<br />

DBToolsInit-Funktion<br />

Funktion<br />

Prototyp<br />

Parameter<br />

Rückgabewert<br />

Anwendung<br />

Beispiel<br />

Siehe auch<br />

"DBToolsInit-Funktion" auf Seite 331<br />

"a_dbtools_info-Struktur" auf Seite 349<br />

Bereitet die DBTools-Bibliothek <strong>für</strong> die Benutzung vor.<br />

Kapitel 8 Die DBTools-Schnittstelle<br />

short DBToolsInit t( const a_dbtools_info * DBTools-Info );<br />

Parameter Beschreibung<br />

DBTools-Info Zeiger auf eine "a_dbtools_info-Struktur" auf Seite 349<br />

Ein Rückgabecode wie in "Rückgabecodes der Softwarekomponenten" auf<br />

Seite 316 beschrieben.<br />

Der hauptsächliche Zweck der Funktion DBToolsInit ist es, die Sprach-DLL<br />

von <strong>Adaptive</strong> Server <strong>Anywhere</strong> zu laden. Die Sprach-DLL enthält lokale<br />

Versionen der Fehlermeldungen und Bedieneraufforderungen, die DBTools<br />

intern verwendet.<br />

Die Funktion DBToolsInit muss zu Beginn jeder Anwendung aufgerufen<br />

werden, die die DBTools-Schnittstelle benutzt, bevor irgend eine andere<br />

DBTools-Funktion benutzt wird.<br />

♦ Das folgende Code-Beispiel zeigt, wie man DBTools initialisiert und<br />

ordnungsgemäß beendet:<br />

a_dbtools_info info;<br />

short ret;<br />

memset( &info, 0, sizeof( a_dbtools_info) );<br />

info.errorrtn = (MSG_CALLBACK)MakeProcInstance(<br />

(FARPROC)MyErrorRtn, hInst );<br />

// Initialisierung von DBTools<br />

ret = DBToolsInit( &info );<br />

if( ret != EXIT_OKAY ) {<br />

// DLL-Initialisierung fehlgeschlagen<br />

…<br />

}<br />

// einige DBTools-Routinen aufrufen. . .<br />

…<br />

// DBTools dll bereinigen<br />

DBToolsFini( &info );<br />

"DBToolsFini-Funktion" auf Seite 330<br />

"a_dbtools_info-Struktur" auf Seite 349<br />

331


DBTools-Funktionen<br />

DBToolsVersion-Funktion<br />

Funktion<br />

Prototyp<br />

Rückgabewert<br />

Anwendung<br />

Siehe auch<br />

DBTranslateLog-Funktion<br />

Funktion<br />

Prototyp<br />

Parameter<br />

Rückgabewert<br />

Anwendung<br />

Siehe auch<br />

DBTruncateLog-Funktion<br />

Funktion<br />

Prototyp<br />

Parameter<br />

332<br />

Gibt die Versionsnummer der DBTools-Bibliothek zurück.<br />

short DBToolsVersion ( void );<br />

Eine Ganzzahl (short integer), die die Versionsnummer der DBTools-<br />

Bibliothek angibt<br />

Verwenden Sie die Funktion DBToolsVersion, um zu überprüfen, dass die<br />

DBTools-Bibliothek nicht älter ist als diejenige, mit der Ihre Anwendung<br />

entwickelt wurde. Anwendungen können mit neueren Versionen von<br />

DBTools laufen, nicht aber mit älteren Versionen.<br />

"Versionsnummern und Kompatibilität" auf Seite 318<br />

Übersetzt eine Transaktionslogdatei in SQL. Diese Funktion wird von dem<br />

Dienstprogramm dbtran benutzt.<br />

short DBTranslateLog ( const a_translate_log * Zu_übersetzendes_Log );<br />

Parameter Beschreibung<br />

Zu_übersetzendes_Log<br />

Zeiger auf eine "a_translate_log-Struktur" auf Seite 357<br />

Ein Rückgabecode wie in "Rückgabecodes der Softwarekomponenten" auf<br />

Seite 316 beschrieben.<br />

$ Informationen über das Logkonvertierungs-Dienstprogramm finden Sie<br />

unter "Das Logkonvertierungs-Dienstprogramm" auf Seite 543 der<br />

Dokumentation ASA Datenbankadministration.<br />

"a_translate_log-Struktur" auf Seite 357<br />

Kürzt eine Transaktionslogdatei. Diese Funktion wird von dem<br />

Dienstprogramm dbbackup benutzt.<br />

short DBTruncateLog ( const a_truncate_log * Zu_kürzendes_Log );<br />

Parameter Beschreibung<br />

Zu_kürzendes_Log<br />

Zeiger auf eine "a_truncate_log-Struktur" auf Seite 358


Rückgabewert<br />

Anwendung<br />

Siehe auch<br />

DBUnload-Funktion<br />

Funktion<br />

Prototyp<br />

Parameter<br />

Rückgabewert<br />

Anwendung<br />

Siehe auch<br />

DBUpgrade-Funktion<br />

Funktion<br />

Prototyp<br />

Parameter<br />

Rückgabewert<br />

Kapitel 8 Die DBTools-Schnittstelle<br />

Ein Rückgabecode wie in "Rückgabecodes der Softwarekomponenten" auf<br />

Seite 316 beschrieben.<br />

$ Informationen über das Sicherungsdienstprogramm finden Sie unter<br />

"Das Sicherungsdienstprogramm" auf Seite 484 der Dokumentation ASA<br />

Datenbankadministration<br />

"a_truncate_log-Struktur" auf Seite 358<br />

Entlädt eine Datenbank. Diese Funktion wird von dem Dienstprogramm<br />

dbunload wie auch von dem Dienstprogramm dbxtract <strong>für</strong> SQL Remote<br />

benutzt.<br />

short DBUnload ( const an_unload_db * Zu_entladende_DB );<br />

Parameter Beschreibung<br />

Zu_entladende_DB<br />

Zeiger auf eine "an_unload_db-Struktur" auf Seite 359<br />

Ein Rückgabecode wie in "Rückgabecodes der Softwarekomponenten" auf<br />

Seite 316 beschrieben.<br />

$ Informationen über das Entladungs-Dienstprogramm finden Sie unter<br />

"Das Dienstprogramm UNLOAD zum Entladen der Datenbank" auf<br />

Seite 572 der Dokumentation ASA Datenbankadministration.<br />

"an_unload_db-Struktur" auf Seite 359<br />

Installiert ein Upgrade <strong>für</strong> eine Datenbankdatei. Diese Funktion wird von<br />

dem Dienstprogramm dbupgrade benutzt.<br />

short DBUpgrade ( const an_upgrade_db * DB_<strong>für</strong>_Upgrade );<br />

Parameter Beschreibung<br />

DB_<strong>für</strong>_Upgrade Zeiger auf eine "an_upgrade_db-Struktur" auf Seite 361<br />

Ein Rückgabecode wie in "Rückgabecodes der Softwarekomponenten" auf<br />

Seite 316 beschrieben.<br />

333


DBTools-Funktionen<br />

Anwendung<br />

Siehe auch<br />

DBValidate-Funktion<br />

Funktion<br />

Prototyp<br />

Parameter<br />

Rückgabewert<br />

Anwendung<br />

Siehe auch<br />

334<br />

$ Informationen über das Upgrade-Dienstprogramm finden Sie unter<br />

"Das Upgrade-Dienstprogramm" auf Seite 582 der Dokumentation ASA<br />

Datenbankadministration.<br />

"an_upgrade_db-Struktur" auf Seite 361<br />

Validiert eine Datenbank oder Teile einer Datenbank. Diese Funktion wird<br />

von dem Dienstprogramm dbvalid benutzt.<br />

short DBValidate ( const a_validate_db * Zu_validierende_DB );<br />

Parameter Beschreibung<br />

Zu_validierende_DB<br />

Zeiger auf eine "a_validate_db-Struktur" auf Seite 363<br />

Ein Rückgabecode wie in "Rückgabecodes der Softwarekomponenten" auf<br />

Seite 316 beschrieben.<br />

$ Informationen über das Validierungs-Dienstprogramm finden Sie unter<br />

"Das Validierungs-Dienstprogramm" auf Seite 588 der Dokumentation ASA<br />

Datenbankadministration.<br />

"a_validate_db-Struktur" auf Seite 363


DBTools-Strukturen<br />

a_backup_db-Struktur<br />

Funktion<br />

Syntax<br />

Kapitel 8 Die DBTools-Schnittstelle<br />

In diesem Abschnitt sind die Strukturen aufgeführt, mit deren Hilfe<br />

Informationen mit der DBTools-Bibliothek ausgetauscht werden. Die<br />

Strukturen sind alphabetisch aufgeführt.<br />

Viele der Strukturelemente entsprechen Befehlszeilenoptionen des<br />

entsprechenden Dienstprogramms. Einige Strukturen zum Beispiel haben ein<br />

Element namens "quiet", das mit den Werten 0 oder 1 belegt sein kann.<br />

Dieses Element entspricht der Befehlszeilenoption (-q) des Vorgangs<br />

"quiet", der von vielen Dienstprogrammen benutzt wird.<br />

Enthält die Informationen, die gebraucht werden, um Sicherungsaufgaben<br />

mit der DBTools-Bibliothek auszuführen.<br />

typedef struct a_backup_db {<br />

unsigned short version;<br />

const char * output_dir;<br />

const char * connectparms;<br />

const char * startline;<br />

MSG_CALLBACK confirmrtn;<br />

MSG_CALLBACK errorrtn;<br />

MSG_CALLBACK msgrtn;<br />

MSG_CALLBACK statusrtn;<br />

a_bit_field backup_database: 1;<br />

a_bit_field backup_logfile : 1;<br />

a_bit_field backup_writefile : 1;<br />

a_bit_field no_confirm : 1;<br />

a_bit_field quiet : 1;<br />

a_bit_field rename_log : 1;<br />

a_bit_field truncate_log : 1;<br />

a_bit_field rename_local_log: 1;<br />

const char * hotlog_filename;<br />

char backup_interrupted;<br />

} a_backup_db;<br />

335


DBTools-Strukturen<br />

Parameter<br />

Siehe auch<br />

336<br />

Mitglied Beschreibung<br />

Version DBTools-Versionsnummer<br />

output_dir Suchpfad des Ausgabeverzeichnisses. Zum Beispiel:<br />

"c:\backup"<br />

connectparms Parameter <strong>für</strong> die Verbindung zur Datenbank. Sie haben<br />

die Form von Zeichenfolgen, zum Beispiel:<br />

"UID=DBA;PWD=SQL;DBF=c:\asa\asademo.db"<br />

$ Alle Zeichenfolgen <strong>für</strong> die Verbindung finden Sie<br />

unter "Verbindungsparameter" auf Seite 78 der<br />

Dokumentation ASA Datenbankadministration<br />

startline Befehlszeile zum Starten der Datenbank-Engine. Das<br />

folgende Beispiel zeigt eine Startzeile:<br />

"c:\asa\win32\dbeng8.exe"<br />

Die standardmäßige Startzeile wird benutzt, wenn dieses<br />

Element NULL ist.<br />

confirmrtn Callback-Routine <strong>für</strong> die Bestätigung einer Aktion<br />

errorrtn Callback-Routine <strong>für</strong> die Behandlung einer Fehlermeldung<br />

msgrtn Callback-Routine <strong>für</strong> die Behandlung einer<br />

Informationsnachricht<br />

statusrtn Callback-Routine <strong>für</strong> die Behandlung einer Statusmeldung<br />

backup_database Datenbankdatei sichern (1) oder nicht (0)<br />

backup_logfile Transaktionslogdatei sichern (1) oder nicht (0)<br />

backup_writefile Datenbank-Write-Datei sichern (1) oder nicht (0), falls<br />

eine Datenbank-Write-Datei benutzt wird<br />

no_confirm Mit (0) oder ohne (1) Bestätigung arbeiten<br />

quiet Ohne die Ausgabe von Nachrichten arbeiten (1) oder<br />

Nachrichten ausgeben (0)<br />

rename_log Transaktionslog umbenennen<br />

truncate_log Transaktionslog löschen<br />

rename_local_log Lokale Sicherung des Transaktionslogs umbenennen<br />

hotlog_filename Dateiname <strong>für</strong> die gerade benutzte Sicherungsdatei<br />

backup_interrupted Gibt an, dass der Vorgang unterbrochen wurde<br />

"DBBackup-Funktion" auf Seite 323<br />

$ Weitere Hinweise zu Callback-Funktionen finden Sie unter "Callback-<br />

Funktionen verwenden" auf Seite 316.


a_change_log-Struktur<br />

Funktion<br />

Syntax<br />

Parameter<br />

Kapitel 8 Die DBTools-Schnittstelle<br />

Enthält die Informationen, die gebraucht werden, um dblog-Aufgaben mit<br />

der DBTools-Bibliothek auszuführen.<br />

typedef struct a_change_log {<br />

unsigned short version;<br />

const char * dbname;<br />

const char * logname;<br />

MSG_CALLBACK errorrtn;<br />

MSG_CALLBACK msgrtn;<br />

a_bit_field query_only : 1;<br />

a_bit_field quiet : 1;<br />

a_bit_field mirrorname_present : 1;<br />

a_bit_field change_mirrorname : 1;<br />

a_bit_field change_logname : 1;<br />

a_bit_field ignore_ltm_trunc : 1;<br />

a_bit_field ignore_remote_trunc : 1;<br />

a_bit_field set_generation_number : 1;<br />

a_bit_field ignore_dbsync_trunc : 1;<br />

const char * mirrorname;<br />

unsigned short generation_number;<br />

const char * key_file;<br />

char * zap_current_offset;<br />

char * sap_starting_offset;<br />

char * encryption_key;<br />

} a_change_log;<br />

Mitglied Beschreibung<br />

version DBTools-Versionsnummer<br />

dbname Datenbankdateiname<br />

logname Name der Transaktionslogdatei. Wenn dieser Wert<br />

gleich NULL gesetzt wird, gibt es kein Log<br />

errorrtn Callback-Routine <strong>für</strong> die Behandlung einer<br />

Fehlermeldung<br />

msgrtn Callback-Routine <strong>für</strong> die Behandlung einer<br />

Informationsnachricht<br />

query_only Name des Transaktionslogs anzeigen. 0: Änderung des<br />

Lognamens erlauben<br />

quiet Ohne die Ausgabe von Nachrichten arbeiten (1) oder<br />

Nachrichten ausgeben (0)<br />

mirrorname_present Auf 1 setzen; zeigt an, dass die DBTools-Version neu<br />

genug ist, um das Feld mirrorname zu unterstützen<br />

change_mirrorname Änderung des Namens der Logspiegeldatei erlauben<br />

change_logname Änderung des Transaktionslognamens erlauben.<br />

337


DBTools-Strukturen<br />

Siehe auch<br />

338<br />

Mitglied Beschreibung<br />

ignore_ltm_trunc Wird der Log Transfer Manager verwandt, wird die<br />

gleiche Funktion wie mit Funktion dbcc settrunc( ’ltm’,<br />

'gen_id', n ) des Replication Server ausgeführt:<br />

$ Weitere Informationen finden Sie in der<br />

Dokumentation zum Replication Server.<br />

ignore_remote_trunc Für SQL Remote. Setzt den Ausgangspunkt <strong>für</strong> die<br />

Option DELETE_OLD_LOGS zurück, der es erlaubt,<br />

ein Transaktionslog zu löschen, wenn es nicht länger<br />

gebraucht wird.<br />

set_generation_number Wird - falls der Log Transfer Manager benutzt wird -<br />

nach der Wiederherstellung einer Sicherung verwendet,<br />

um die Generierungsnummer zu setzen.<br />

ignore_dbsync_trunc Wenn dbmlsync verwendet wird, wird hiermit der<br />

Ausgangspunkt <strong>für</strong> die Option DELETE_OLD_LOGS<br />

zurückgesetzt, mit dem ein Transaktionslog gelöscht<br />

werden kann, wenn es nicht mehr gebraucht wird.<br />

mirrorname Der neue Name des Transaktionslogspiegels<br />

generation_number Die neue Generationsnummer. Wird zusammen mit<br />

set_generation_number benutzt.<br />

key_file Eine Datei mit dem Chiffrierschlüssel<br />

zap_current_offset Aktuellen Ausgangspunkt auf den angegebenen Wert<br />

ändern. Dies ist nur <strong>für</strong> das Zurücksetzen eines<br />

Transaktionslogs nach Entladen und Aktualisieren zur<br />

Abstimmung mit den Einstellungen <strong>für</strong> dbremote oder<br />

dbmlsync vorgesehen.<br />

zap_starting_offset Ausgangspunkt auf den angegebenen Wert ändern.<br />

Dies ist nur <strong>für</strong> das Zurücksetzen eines<br />

Transaktionslogs nach Entladen und Aktualisieren zur<br />

Abstimmung mit den Einstellungen <strong>für</strong> dbremote oder<br />

dbmlsync vorgesehen.<br />

encryption_key Der Chiffrierschlüssel <strong>für</strong> die Datenbankdatei.<br />

"DBChangeLogName-Funktion" auf Seite 323<br />

$ Weitere Hinweise zu Callback-Funktionen finden Sie unter "Callback-<br />

Funktionen verwenden" auf Seite 316.


a_compress_db-Struktur<br />

Funktion<br />

Syntax<br />

Parameter<br />

Kapitel 8 Die DBTools-Schnittstelle<br />

Enthält die Informationen, die gebraucht werden, um<br />

Datenbank-Komprimierungsaufgaben mit der DBTools-Bibliothek<br />

auszuführen.<br />

typedef struct a_compress_db {<br />

unsigned short version;<br />

const char * dbname;<br />

const char * compress_name;<br />

MSG_CALLBACK errorrtn;<br />

MSG_CALLBACK msgrtn;<br />

MSG_CALLBACK statusrtn;<br />

a_bit_field display_free_pages : 1;<br />

a_bit_field quiet : 1;<br />

a_bit_field record_unchanged : 1;<br />

a_compress_stats * stats;<br />

MSG_CALLBACK confirmrtn;<br />

a_bit_field noconfirm : 1;<br />

const char * encryption_key<br />

} a_compress_db;<br />

Mitglied Beschreibung<br />

version DBTools-Versionsnummer<br />

dbname Name der zu komprimierenden Datenbank<br />

compress_name Dateiname der komprimierten Datenbank<br />

errorrtn Callback-Routine <strong>für</strong> die Behandlung einer<br />

Fehlermeldung<br />

msgrtn Callback-Routine <strong>für</strong> die Behandlung einer<br />

Informationsnachricht<br />

statusrtn Callback-Routine <strong>für</strong> die Behandlung einer<br />

Statusmeldung<br />

display_free_pages Informationen über freie Seiten anzeigen<br />

quiet Ohne die Ausgabe von Nachrichten arbeiten (1) oder<br />

Nachrichten ausgeben (0)<br />

339


DBTools-Strukturen<br />

Siehe auch<br />

a_compress_stats-Struktur<br />

Funktion<br />

Syntax<br />

Parameter<br />

340<br />

Mitglied Beschreibung<br />

record_unchanged Auf 1 gesetzt. Zeigt an, dass die Struktur<br />

a_compress_stats neu genug ist, um das Element<br />

unchanged zu haben<br />

a_compress_stats Zeiger auf eine Struktur vom Typ a_compress_stats. Wird<br />

belegt, wenn das Element nicht NULL ist und wenn<br />

display_free_pages nicht 0 (Null) ist<br />

confirmrtn Callback-Routine <strong>für</strong> die Bestätigung einer Aktion<br />

noconfirm Mit (0) oder ohne (1) Bestätigung arbeiten<br />

encryption_key Der Chiffrierschlüssel <strong>für</strong> die Datenbankdatei.<br />

"DBCompress-Funktion" auf Seite 325<br />

"a_compress_stats-Struktur" auf Seite 340<br />

$ Weitere Hinweise zu Callback-Funktionen finden Sie unter "Callback-<br />

Funktionen verwenden" auf Seite 316.<br />

Enthält statistische Informationen über komprimierte Datenbankdateien.<br />

typedef struct a_compress_stats {<br />

a_stats_line tables;<br />

a_stats_line indices;<br />

a_stats_line other;<br />

a_stats_line free;<br />

a_stats_line total;<br />

a_sql_int32 free_pages;<br />

a_sql_int32 unchanged;<br />

} a_compress_stats;<br />

Mitglied Beschreibung<br />

tables Enthält Information zur Komprimierung von Tabellen<br />

Indices Enthält Information zur Komprimierung von Indizes<br />

Other Enthält weitere Information zur Komprimierung<br />

Free Enthält Informationen über freien Speicherplatz<br />

Total Enthält allgemeine Information zur Komprimierung<br />

free_pages Enthält Informationen über freie Seiten<br />

Unchanged Anzahl der Seiten, die der Komprimierungsalgorithmus nicht<br />

schrumpfen konnte


Siehe auch<br />

a_create_db-Struktur<br />

Funktion<br />

Syntax<br />

"DBCompress-Funktion" auf Seite 325<br />

"a_compress_db-Struktur" auf Seite 339<br />

Kapitel 8 Die DBTools-Schnittstelle<br />

Enthält die Informationen, die gebraucht werden, um eine Datenbank mit der<br />

DBTools-Bibliothek zu erstellen.<br />

typedef struct a_create_db {<br />

unsigned short version;<br />

const char * dbname;<br />

const char * logname;<br />

const char * startline;<br />

short page_size;<br />

const char * default_collation;<br />

MSG_CALLBACK errorrtn;<br />

MSG_CALLBACK msgrtn;<br />

short database_version;<br />

char verbose;<br />

a_bit_field blank_pad : 2;<br />

a_bit_field respect_case : 1;<br />

a_bit_field encrypt : 1;<br />

a_bit_field debug : 1;<br />

a_bit_field dbo_avail : 1;<br />

a_bit_field mirrorname_present : 1;<br />

a_bit_field avoid_view_collisions : 1;<br />

short collation_id;<br />

const char * dbo_username;<br />

const char * mirrorname;<br />

const char * encryption_dllname;<br />

a_bit_field java_classes : 1;<br />

a_bit_field jconnect : 1;<br />

const char * data_store_type<br />

const char * encryption_key;<br />

const char * encryption_algorithm;<br />

const char * jdK_version;<br />

} a_create_db;<br />

341


DBTools-Strukturen<br />

Parameter<br />

342<br />

Mitglied Beschreibung<br />

version DBTools-Versionsnummer<br />

dbname Datenbankdateiname<br />

logname Neuer Transaktionslogname<br />

startline Befehlszeile zum Starten der Datenbank-Engine. Das<br />

folgende Beispiel zeigt eine Startzeile:<br />

"c:\asa\win32\dbeng8.exe"<br />

Die standardmäßige Startzeile wird benutzt, wenn dieses<br />

Element NULL ist.<br />

page_size Die Seitengröße der Datenbank<br />

default_collation Die Kollatierung <strong>für</strong> die Datenbank<br />

errorrtn Callback-Routine <strong>für</strong> die Behandlung einer<br />

Fehlermeldung<br />

msgrtn Callback-Routine <strong>für</strong> die Behandlung einer<br />

Informationsnachricht<br />

database_version Die Versionsnummer der Datenbank<br />

verbose Im ausführlichen Darstellungsmodus ausführen<br />

blank_pad Leerzeichen in Zeichenfolgevergleichen beachten und<br />

entsprechende Indexinformationen speichern<br />

respect_case Groß/Kleinschreibung in Zeichenfolgevergleichen<br />

beachten und entsprechende Indexinformationen<br />

speichern<br />

encrypt Datenbank verschlüsseln<br />

debug Reserviert<br />

dbo_avail Auf 1 gesetzt. Der Benutzer dbo ist in dieser Datenbank<br />

verfügbar.<br />

mirrorname_present Auf 1 setzen; zeigt an, dass die DBTools-Version neu<br />

genug ist, um das Feld mirrorname zu unterstützen<br />

avoid_view_collisions Die Erzeugung der Watcom SQL-Kompatibilitäts-<br />

Ansichten SYS.SYSCOLUMNS und<br />

SYS.SYSINDEXES vermeiden<br />

collation_id Kollatierungsname (identifier)<br />

dbo_username Nicht mehr benutzt: auf NULL gesetzt<br />

mirrorname Name des Transaktionslogspiegels<br />

encryption_dllname Die zum Verschlüsseln der Datenbank verwendete DLL.<br />

java_classes Für Java aktivierte Datenbank erstellen


Siehe auch<br />

a_crypt_db-Struktur<br />

Funktion<br />

Syntax<br />

Parameter<br />

Mitglied Beschreibung<br />

Kapitel 8 Die DBTools-Schnittstelle<br />

jconnect Für jConnect erforderliche Systemprozeduren<br />

einbeziehen<br />

data_store_type Reserviert NULL benutzen<br />

encryption_key Der Chiffrierschlüssel <strong>für</strong> die Datenbankdatei.<br />

encryption_algorithm AESoder MDSR eingeben.<br />

jdk_version Einer der Werte <strong>für</strong> die Option dbinit -jdk.<br />

"DBCreate-Funktion" auf Seite 325<br />

$ Weitere Hinweise zu Callback-Funktionen finden Sie unter "Callback-<br />

Funktionen verwenden" auf Seite 316 .<br />

Enthält die Informationen, die zum Verschlüsseln einer Datenbankdatei<br />

verwendet werden, die auch das dbinit-Dienstprogramm benutzt.<br />

typedef struct a_crypt_db {<br />

const char _fd_ * dbname;<br />

const char _fd_ * dllname;<br />

MSG_CALLBACK errorrtn;<br />

MSG_CALLBACK msgrtn;<br />

MSG_CALLBACK statusrtn;<br />

char verbose;<br />

a_bit_field quiet : 1;<br />

a_bit_field debug : 1;<br />

} a_crypt_db;<br />

Mitglied Beschreibung<br />

dbname Datenbankdateiname<br />

dllname Der Name der DLL, die <strong>für</strong> die Ausführung der<br />

Verschlüsselung verwendet wird<br />

errorrtn Callback-Routine <strong>für</strong> die Behandlung einer Fehlermeldung<br />

msgrtn Callback-Routine <strong>für</strong> die Behandlung einer<br />

Informationsnachricht<br />

statusrtn Callback-Routine <strong>für</strong> die Behandlung einer Statusmeldung<br />

verbose Im ausführlichen Darstellungsmodus ausführen<br />

quiet Ohne Nachrichten arbeiten<br />

debug Reserviert<br />

343


DBTools-Strukturen<br />

Siehe auch<br />

a_db_collation-Struktur<br />

Funktion<br />

Syntax<br />

Parameter<br />

344<br />

"DBCrypt-Funktion" auf Seite 326<br />

"Datenbank mit dem Befehlszeilenprogramm ""dbinit"" erstellen" auf<br />

Seite 516 der Dokumentation ASA Datenbankadministration<br />

Enthält die Informationen, die gebraucht werden, um mit der DBTools-<br />

Bibliothek eine Kollatierungssequenz aus der Datenbank zu extrahieren.<br />

typedef struct a_db_collation {<br />

unsigned short version;<br />

const char * connectparms;<br />

const char * startline;<br />

const char * collation_label;<br />

const char * filename;<br />

MSG_CALLBACK confirmrtn;<br />

MSG_CALLBACK errorrtn;<br />

MSG_CALLBACK msgrtn;<br />

a_bit_field include_empty : 1;<br />

a_bit_field hex_for_extended : 1;<br />

a_bit_field replace : 1;<br />

a_bit_field quiet : 1;<br />

const char * input_filename;<br />

const char _fd_ * mapping_filename;<br />

} a_db_collation;<br />

Mitglied Beschreibung<br />

version DBTools-Versionsnummer<br />

connectparms Parameter <strong>für</strong> die Verbindung zur Datenbank. Sie haben<br />

die Form von Zeichenfolgen, zum Beispiel:<br />

"UID=DBA;PWD=SQL;DBF=c:\asa\asademo.db"<br />

$ Alle Zeichenfolgen <strong>für</strong> die Verbindung finden Sie<br />

unter "Verbindungsparameter" auf Seite 78 der<br />

Dokumentation ASA Datenbankadministration<br />

startline Befehlszeile zum Starten der Datenbank-Engine. Das<br />

folgende Beispiel zeigt eine Startzeile:<br />

"c:\asa\win32\dbeng8.exe"<br />

Die standardmäßige Startzeile wird benutzt, wenn dieses<br />

Element NULL ist.<br />

confirmrtn Callback-Routine <strong>für</strong> die Bestätigung einer Aktion<br />

errorrtn Callback-Routine <strong>für</strong> die Behandlung einer Fehlermeldung<br />

msgrtn Callback-Routine <strong>für</strong> die Behandlung einer<br />

Informationsnachricht


Siehe auch<br />

a_db_info-Struktur<br />

Funktion<br />

Mitglied Beschreibung<br />

include_empty Leere Zuordnungen <strong>für</strong> Lücken in der<br />

Kollatierungssequenz schreiben<br />

Kapitel 8 Die DBTools-Schnittstelle<br />

hex_for_extended Zweiziffrige Hexadezimalzahlen benutzen, um high-value-<br />

Zeichen zu repräsentieren<br />

replace Ohne Bestätigungsaktionen arbeiten<br />

quiet Ohne Nachrichten arbeiten<br />

input_filename Kollatierungsdefinition eingeben<br />

mapping_filename Ausgabe von syscollationmapping<br />

"DBCollate-Funktion" auf Seite 324<br />

$ Weitere Hinweise zu Callback-Funktionen finden Sie unter "Callback-<br />

Funktionen verwenden" auf Seite 316.<br />

Enthält die Informationen, die gebraucht werden, um dbinfo-Informationen<br />

mit der DBTools-Bibliothek zurückzugeben.<br />

345


DBTools-Strukturen<br />

Syntax<br />

Parameter<br />

346<br />

typedef struct a_db_info {<br />

unsigned short version;<br />

MSG_CALLBACK errorrtn;<br />

const char * dbname;<br />

unsigned short dbbufsize;<br />

char * dbnamebuffer;<br />

unsigned short logbufsize;<br />

char * lognamebuffer;<br />

unsigned short wrtbufsize;<br />

char * wrtnamebuffer;<br />

a_bit_field quiet : 1;<br />

a_bit_field mirrorname_present : 1;<br />

a_sysinfo sysinfo;<br />

unsigned long free_pages;<br />

a_bit_field compressed : 1;<br />

const char * connectparms;<br />

const char * startline;<br />

MSG_CALLBACK msgrtn;<br />

MSG_CALLBACK statusrtn;<br />

a_bit_field page_usage : 1;<br />

a_table_info * totals;<br />

unsigned long file_size;<br />

unsigned long unused_pages;<br />

unsigned long other_pages;<br />

unsigned short mirrorbufsize;<br />

char * mirrornamebuffer;<br />

char * unused_field;<br />

char * collationnamebuffer;<br />

unsigned short collationnamebufsize;<br />

char * classesversionbuffer;<br />

unsigned short classesversionbufsize;<br />

} a_db_info;<br />

Mitglied Beschreibung<br />

version DBTools-Versionsnummer<br />

errortrn Callback-Routine <strong>für</strong> die Behandlung einer<br />

Fehlermeldung<br />

dbname Datenbankdateiname<br />

dbbufsize Länge des Elements dbnamebuffer<br />

dbnamebuffer Datenbankdateiname<br />

logbufsize Länge des Elements lognamebuffer<br />

lognamebuffer Transaktionslog-Dateiname<br />

wrtbufsize Länge des Elements wrtnamebuffer<br />

wrtnamebuffer Name der Write-Datei


Mitglied Beschreibung<br />

Kapitel 8 Die DBTools-Schnittstelle<br />

quiet Ohne Bestätigungsnachrichten arbeiten<br />

mirrorname_present Auf 1 setzen; zeigt an, dass die DBTools-Version neu<br />

genug ist, um das Feld mirrorname zu unterstützen<br />

sysinfo Zeiger auf eine a_sysinfo-Struktur<br />

free_pages Anzahl der freien Seiten<br />

compressed 1 falls komprimiert, sonst 0<br />

connectparms Parameter <strong>für</strong> die Verbindung zur Datenbank. Sie haben<br />

die Form von Zeichenfolgen, zum Beispiel:<br />

"UID=DBA;PWD=SQL;DBF=c:\Programme<br />

\<strong>Sybase</strong>\SQL <strong>Anywhere</strong> 8\asademo.db"<br />

$ Alle Zeichenfolgen <strong>für</strong> die Verbindung finden Sie<br />

unter "Verbindungsparameter" auf Seite 78 der<br />

Dokumentation ASA Datenbankadministration<br />

startline Befehlszeile zum Starten der Datenbank-Engine. Das<br />

folgende Beispiel zeigt eine Startzeile:<br />

"c:\asa\win32\dbeng8.exe"<br />

Die standardmäßige Startzeile wird benutzt, wenn dieses<br />

Element NULL ist.<br />

msgrtn Callback-Routine <strong>für</strong> die Behandlung einer<br />

Informationsnachricht<br />

statusrtn Callback-Routine <strong>für</strong> die Behandlung einer<br />

Statusmeldung<br />

page_usage 1, um Auskunft zu geben über Seitennutzungs-Statistiken,<br />

sonst 0<br />

totals Zeiger auf eine a_table_info-Struktur<br />

file_size Größe der Datenbankdatei<br />

unused_pages Anzahl der nicht genutzten Seiten<br />

other_pages Anzahl der Seiten, die weder Tabellen- noch Indexseiten<br />

sind<br />

mirrorbufsize Länge des Elements mirrornamebuffer<br />

mirrornamebuffer Name des Transaktionslogspiegels<br />

347


DBTools-Strukturen<br />

Siehe auch<br />

a_dblic_info-Struktur<br />

Funktion<br />

Syntax<br />

Parameter<br />

348<br />

Mitglied Beschreibung<br />

collationnamebuffer Name und Bezeichnung der Datenbankkollatierung<br />

(Maximum ist 128+1)<br />

collationnamebufsize Länge des Elements collationnamebuffer<br />

key_file Eine Datei mit dem Chiffrierschlüssel<br />

classesversionbuffer Die JDK-Version der installierten Java-Klassen, wie z.B.<br />

1.1.3, 1.1.8, 1.3 oder eine leere Zeichenfolge, falls Java-<br />

Klassen nicht in der Datenbank installiert sind (die<br />

maximale Größe beträgt 10+1)<br />

classesversionbufsize Länge des Elements classesversionbuffer<br />

"DBInfo-Funktion" auf Seite 327<br />

$ Weitere Hinweise zu Callback-Funktionen finden Sie unter "Callback-<br />

Funktionen verwenden" auf Seite 316.<br />

Enthält Angaben zu den Lizenzdaten. Sie dürfen diese Informationen nur<br />

gemäß Ihrem Lizenzvertrag benutzen.<br />

typedef struct a_dblic_info {<br />

unsigned short version;<br />

char * exename;<br />

char * username;<br />

char * compname;<br />

char * platform_str;<br />

a_sql_int32 nodecount;<br />

a_sql_int32 conncount;<br />

a_license_type type;<br />

MSG_CALLBACK errorrtn;<br />

MSG_CALLBACK msgrtn;<br />

a_bit_field quiet : 1;<br />

a_bit_field query_only : 1;<br />

} a_dblic_info;<br />

Mitglied Beschreibung<br />

version DBTools-Versionsnummer<br />

exename Name der ausführbaren Datei<br />

username Benutzername <strong>für</strong> die Lizenz<br />

compname Name des Unternehmens <strong>für</strong> die Lizenz<br />

platform_str Betriebssystem: WinNT oder NLM oder UNIX<br />

nodecount Anzahl der Knotenlizenzen.


a_dbtools_info-Struktur<br />

Funktion<br />

Syntax<br />

Parameter<br />

Siehe auch<br />

an_erase_db-Struktur<br />

Funktion<br />

Mitglied Beschreibung<br />

conncount Muss 1000000L sein<br />

type Werte finden Sie unter lictype.h<br />

Kapitel 8 Die DBTools-Schnittstelle<br />

errorrtn Callback-Routine <strong>für</strong> die Behandlung einer Fehlermeldung<br />

msgrtn Callback-Routine <strong>für</strong> die Behandlung einer<br />

Informationsnachricht<br />

quiet Ohne die Ausgabe von Nachrichten arbeiten (1) oder<br />

Nachrichten ausgeben (0)<br />

query_only Wenn 1, nur die Lizenzinformationen anzeigen. Wenn 0,<br />

Änderung der Informationen zulassen.<br />

Enthält die Informationen, die gebraucht werden, um die Arbeit mit der<br />

DBTools-Bibliothek zu beginnen und zu beenden.<br />

typedef struct a_dbtools_info {<br />

MSG_CALLBACK errorrtn;<br />

} a_dbtools_info;<br />

Mitglied Beschreibung<br />

errorrtn Callback-Routine <strong>für</strong> die Behandlung einer Fehlermeldung<br />

"DBToolsFini-Funktion" auf Seite 330<br />

"DBToolsInit-Funktion" auf Seite 331<br />

$ Weitere Hinweise zu Callback-Funktionen finden Sie unter "Callback-<br />

Funktionen verwenden" auf Seite 316.<br />

Enthält die Informationen, die gebraucht werden, um eine Datenbank mit der<br />

DBTools-Bibliothek zu löschen.<br />

349


DBTools-Strukturen<br />

Syntax<br />

Parameter<br />

Siehe auch<br />

an_expand_db-Struktur<br />

Funktion<br />

350<br />

typedef struct an_erase_db {<br />

unsigned short version;<br />

const char * dbname;<br />

MSG_CALLBACK confirmrtn;<br />

MSG_CALLBACK errorrtn;<br />

MSG_CALLBACK msgrtn;<br />

a_bit_field quiet : 1;<br />

a_bit_field erase : 1;<br />

const char * encryption_key;<br />

} an_erase_db;<br />

Mitglied Beschreibung<br />

version DBTools-Versionsnummer<br />

dbname Name der zu löschenden Datenbankdatei<br />

confirmrtn Callback-Routine <strong>für</strong> die Bestätigung einer Aktion<br />

errorrtn Callback-Routine <strong>für</strong> die Behandlung einer Fehlermeldung<br />

msgrtn Callback-Routine <strong>für</strong> die Behandlung einer<br />

Informationsnachricht<br />

quiet Ohne die Ausgabe von Nachrichten arbeiten (1) oder<br />

Nachrichten ausgeben (0)<br />

erase Ohne Bestätigung löschen (1) oder mit Bestätigung (0)<br />

encryption_key Der Chiffrierschlüssel <strong>für</strong> die Datenbankdatei.<br />

"DBErase-Funktion" auf Seite 327<br />

$ Weitere Hinweise zu Callback-Funktionen finden Sie unter "Callback-<br />

Funktionen verwenden" auf Seite 316.<br />

Enthält Informationen, die <strong>für</strong> die Datenbankdekomprimierung mit der<br />

DBTools-Bibliothek gebraucht werden.


Syntax<br />

Parameter<br />

Siehe auch<br />

a_name-Struktur<br />

Funktion<br />

Kapitel 8 Die DBTools-Schnittstelle<br />

typedef struct an_expand_db {<br />

unsigned short version;<br />

const char * compress_name;<br />

const char * dbname;<br />

MSG_CALLBACK errorrtn;<br />

MSG_CALLBACK msgrtn;<br />

MSG_CALLBACK statusrtn;<br />

a_bit_field quiet : 1;<br />

MSG_CALLBACK confirmrtn;<br />

a_bit_field noconfirm : 1;<br />

const char * key_file;<br />

const char * encryption_key;<br />

} an_expand_db;<br />

Mitglied Beschreibung<br />

version DBTools-Versionsnummer<br />

compress_name Name der komprimierten Datenbankdatei<br />

dbname Datenbankdateiname<br />

errorrtn Callback-Routine <strong>für</strong> die Behandlung einer Fehlermeldung<br />

msgrtn Callback-Routine <strong>für</strong> die Behandlung einer<br />

Informationsnachricht<br />

statusrtn Callback-Routine <strong>für</strong> die Behandlung einer Statusmeldung<br />

quiet Ohne die Ausgabe von Nachrichten arbeiten (1) oder<br />

Nachrichten ausgeben (0)<br />

confirmrtn Callback-Routine <strong>für</strong> die Bestätigung einer Aktion<br />

noconfirm Mit (0) oder ohne (1) Bestätigung arbeiten<br />

key_file Eine Datei mit dem Chiffrierschlüssel<br />

encryption_key Der Chiffrierschlüssel <strong>für</strong> die Datenbankdatei.<br />

"DBExpand-Funktion" auf Seite 327<br />

$ Weitere Hinweise zu Callback-Funktionen finden Sie unter "Callback-<br />

Funktionen verwenden" auf Seite 316.<br />

Enthält eine verkettete Liste von Namen. Wird von anderen Strukturen<br />

benutzt, die Namenslisten erfordern.<br />

351


DBTools-Strukturen<br />

Syntax<br />

Parameter<br />

Siehe auch<br />

a_stats_line-Struktur<br />

Funktion<br />

Syntax<br />

Parameter<br />

Siehe auch<br />

a_sync_db-Struktur<br />

Funktion<br />

352<br />

typedef struct a_name {<br />

struct a_name * next;<br />

char name[1];<br />

} a_name, * p_name;<br />

Mitglied Beschreibung<br />

next Zeiger auf eine next a_name-Struktur in der Liste<br />

Name Der Name<br />

p_name Zeiger auf die vorangehende a_name-Struktur<br />

"a_translate_log-Struktur" auf Seite 357<br />

"a_validate_db-Struktur" auf Seite 363<br />

"an_unload_db-Struktur" auf Seite 359<br />

Enthält Informationen, welche <strong>für</strong> die Komprimierung und<br />

Dekomprimierung der Datenbank mit der DBTools-Bibliothek gebraucht<br />

werden.<br />

typedef struct a_stats_line {<br />

long pages;<br />

long bytes;<br />

long compressed_bytes;<br />

} a_stats_line;<br />

Mitglied Beschreibung<br />

Pages Anzahl der Seiten<br />

Bytes Anzahl der Bytes <strong>für</strong> die nicht komprimierte Datenbank<br />

Compressed_bytes Anzahl der Bytes <strong>für</strong> die komprimierte Datenbank<br />

"a_compress_stats-Struktur" auf Seite 340<br />

Enthält Informationen, die <strong>für</strong> den Gebrauch des Dienstprogramms dbmlsync<br />

mit der DBTools-Bibliothek benötigt werden.


Syntax<br />

typedef struct a_sync_db {<br />

unsigned short version;<br />

char _fd_ * connectparms;<br />

char _fd_ * publication;<br />

const char _fd_ * offline_dir;<br />

char _fd_ * extended_options;<br />

char _fd_ * script_full_path;<br />

const char _fd_ * include_scan_range;<br />

const char _fd_ * raw_file;<br />

MSG_CALLBACK confirmrtn;<br />

MSG_CALLBACK errorrtn;<br />

MSG_CALLBACK msgrtn;<br />

MSG_CALLBACK logrtn;<br />

Kapitel 8 Die DBTools-Schnittstelle<br />

353


DBTools-Strukturen<br />

354<br />

a_SQL_uint32 debug_dump_size;<br />

a_SQL_uint32 dl_insert_width;<br />

a_bit_field verbose : 1;<br />

a_bit_field debug : 1;<br />

a_bit_field debug_dump_hex : 1;<br />

a_bit_field debug_dump_char : 1;<br />

a_bit_field debug_page_offsets : 1;<br />

a_bit_field use_hex_offsets : 1;<br />

a_bit_field use_relative_offsets : 1;<br />

a_bit_field output_to_file : 1;<br />

a_bit_field output_to_mobile_link : 1;<br />

a_bit_field dl_use_put : 1;<br />

a_bit_field dl_use_upsert : 1;<br />

a_bit_field kill_other_connections : 1;<br />

a_bit_field retry_remote_behind : 1;<br />

a_bit_field ignore_debug_interrupt : 1;<br />

SET_WINDOW_TITLE_CALLBACK set_window_title_rtn;<br />

char * default_window_title;<br />

MSG_QUEUE_CALLBACK msgqueuertn;<br />

MSG_CALLBACK progress_msg_rtn;<br />

SET_PROGRESS_CALLBACK progress_index_rtn;<br />

char ** argv;<br />

char ** ce_argv;<br />

a_bit_field connectparms_allocated : 1;<br />

a_bit_field entered_dialog : 1;<br />

a_bit_field used_dialog_allocation : 1;<br />

a_bit_field ignore_scheduling : 1;<br />

a_bit_field ignore_hook_errors : 1;<br />

a_bit_field changing_pwd : 1;<br />

a_bit_field prompt_again : 1;<br />

a_bit_field retry_remote_ahead : 1;<br />

a_bit_field rename_log : 1;<br />

a_bit_field hide_conn_str : 1;<br />

a_bit_field hide_ml_pwd : 1;<br />

a_bit_field delay_ml_disconn : 1;<br />

a_SQL_uint32 dlg_launch_focus;<br />

char _fd_ * mlpassword;<br />

char _fd_ * new_mlpassword;<br />

char _fd_ * verify_mlpassword;<br />

a_SQL_uint32 pub_name_cnt;<br />

char ** pub_name_list;<br />

USAGE_CALLBACK usage_rtn;<br />

a_sql_uint32 hovering_frequency;<br />

a_bit_short ignore_hovering : 1;<br />

a_bit_short verbose_upload : 1;<br />

a_bit_short verbose_upload_data : 1;<br />

a_bit_short verbose_download : 1;<br />

a_bit_short verbose_download_data : 1;<br />

a_bit_short autoclose : 1;<br />

a_bit_short ping : 1;<br />

a_bit_short _unused : 9;


Parameter<br />

Siehe auch:<br />

a_syncpub-Struktur<br />

Funktion<br />

Syntax<br />

Parameter<br />

char _fd_ * encryption_key;<br />

a_syncpub _fd_ * upload_defs;<br />

char _fd_ * log_file_name;<br />

char _fd_ * user_name;<br />

} a_sync_db;<br />

Kapitel 8 Die DBTools-Schnittstelle<br />

Die Parameter entsprechen Funktionen, die über das Dienstprogramm<br />

dbmlsync zugänglich sind.<br />

In der Header-Datei dbtools.h finden Sie weitere Kommentare.<br />

$ Weitere Hinweise finden Sie unter "MobiLink-Synchronisationsclient"<br />

auf Seite 440 der Dokumentation MobiLink Benutzerhandbuch.<br />

"DBSynchronizeLog-Funktion" auf Seite 330<br />

Enthält Informationen, die <strong>für</strong> das Dienstprogramm dbmlsync benötigt<br />

werden.<br />

typedef struct a_syncpub {<br />

struct a_syncpub _fd_ * next;<br />

char _fd_ * pub_name;<br />

char _fd_ * ext_opt;<br />

a_bit_field alloced_by_dbsync: 1;<br />

} a_syncpub;<br />

Mitglied Beschreibung<br />

a_syncpub Zeiger auf den nächsten Knoten in der Liste, NULL <strong>für</strong><br />

den letzten Knoten<br />

pub_name Für diesen –n-Parameter angegebene<br />

Publikationsnamen. Dies ist die exakte Zeichenfolge<br />

nach -n in der Befehlszeile.<br />

ext_opt Erweiterte Optionen, die mit dem Parameter -eu<br />

angegeben werden<br />

encryption 1 falls die Datenbank verschlüsselt ist, 0 (Null) falls<br />

nicht<br />

alloced_by_dbsync FALSE, mit Ausnahme der von dbtool8.dll erstellten<br />

Knoten<br />

355


DBTools-Strukturen<br />

a_sysinfo-Struktur<br />

Funktion<br />

Parameter<br />

Siehe auch<br />

a_table_info-Struktur<br />

Funktion<br />

Syntax<br />

356<br />

Enthält Informationen, die <strong>für</strong> den Gebrauch der Dienstprogramme dbinfo<br />

und dbunload mit der DBTools-Bibliothek benötigt werden.<br />

typedef struct a_sysinfo {<br />

a_bit_field valid_data : 1;<br />

a_bit_field blank_padding : 1;<br />

a_bit_field case_sensitivity : 1;<br />

a_bit_field encryption : 1;<br />

char default_collation[11];<br />

unsigned short page_size;<br />

} a_sysinfo;<br />

Mitglied Beschreibung<br />

valid_date Bit-Feld, das angibt, ob die folgenden Werte gesetzt sind<br />

blank_padding 1 falls Auffüllen mit Leerzeichen in der Datenbank benutzt<br />

wird, 0 (Null) falls nicht<br />

case_sensitivity 1 falls die Datenbank Groß/Kleinschreibung beachtet, 0 (Null)<br />

falls nicht<br />

encryption 1 falls die Datenbank verschlüsselt ist, 0 (Null) falls nicht<br />

default_collation Die Kollatierungssequenz <strong>für</strong> die Datenbank<br />

page_size Die Seitengröße <strong>für</strong> die Datenbank<br />

"a_db_info-Struktur" auf Seite 345<br />

Enthält Informationen über eine Tabelle, die als Teil der a_db_info-Struktur<br />

gebraucht wird.<br />

typedef struct a_table_info {<br />

struct a_table_info * next;<br />

unsigned short table_id;<br />

unsigned long table_pages;<br />

unsigned long index_pages;<br />

unsigned long table_used;<br />

unsigned long index_used;<br />

char * table_name;<br />

a_sql_uint32 table_used_pct;<br />

a_sql_uint32 index_used_pct;<br />

} a_table_info;


Parameter<br />

Siehe auch<br />

a_translate_log-Struktur<br />

Funktion<br />

Syntax<br />

Mitglied Beschreibung<br />

next Nächste Tabelle in der Liste<br />

table_id ID-Nummer <strong>für</strong> diese Tabelle<br />

table_pages Anzahl der Tabellenseiten<br />

index_pages Anzahl der Indexseiten<br />

Kapitel 8 Die DBTools-Schnittstelle<br />

table_used Anzahl der in den Tabellenseiten benutzten Bytes<br />

index_used Anzahl der in den Indexseiten benutzten Bytes<br />

table_name Name der Tabelle<br />

table_used_pct Verwendung des Tabellenbereichs als Prozentsatz<br />

index_used_pct Verwendung des Indexbereichs als Prozentsatz<br />

"a_db_info-Struktur" auf Seite 345<br />

Enthält Informationen, die <strong>für</strong> die Konvertierung des Transaktionslogs mit<br />

der DBTools-Bibliothek gebraucht werden.<br />

typedef struct a_translate_log {<br />

unsigned short version;<br />

const char * logname;<br />

const char * sqlname;<br />

p_name userlist;<br />

MSG_CALLBACK confirmrtn;<br />

MSG_CALLBACK errorrtn;<br />

MSG_CALLBACK msgrtn;<br />

char userlisttype;<br />

a_bit_field remove_rollback : 1;<br />

a_bit_field ansi_SQL : 1;<br />

a_bit_field since_checkpoint: 1;<br />

a_bit_field omit_comments : 1;<br />

a_bit_field replace : 1;<br />

a_bit_field debug : 1;<br />

a_bit_field include_trigger_trans : 1;<br />

a_bit_field comment_trigger_trans : 1;<br />

unsigned long since_time;<br />

const char _fd_ * reserved_1;<br />

357


DBTools-Strukturen<br />

Parameter<br />

Siehe auch<br />

a_truncate_log-Struktur<br />

Funktion<br />

358<br />

const char _fd_ * reserved_2;<br />

a_sql_uint32 debug_dump_size;<br />

a_bit_field debug_sql_remote : 1;<br />

a_bit_field debug_dump_hex : 1;<br />

a_bit_field debug_dump_char : 1;<br />

a_bit_field debug_page_offsets : 1;<br />

a_bit_field reserved_3 : 1;<br />

a_bit_field use_hex_offsets : 1;<br />

a_bit_field use_relative_offsets : 1;<br />

a_bit_field include_audit : 1;<br />

a_bit_field chronological_order : 1;<br />

a_bit_field force_recovery : 1;<br />

a_bit_field include_subsets : 1;<br />

a_bit_field force_chaining : 1;<br />

a_sql_uint32 recovery_ops;<br />

a_sql_uint32 recovery_bytes;<br />

const char _fd_ * include_source_sets;<br />

const char _fd_ * include_destination_sets;<br />

const char _fd_ * include_scan_range;<br />

const char _fd_ * repserver_users;<br />

const char _fd_ * include_tables;<br />

const char _fd_ * include_publications;<br />

const char _fd_ * queueparms;<br />

a_bit_field generate_reciprocals :1;<br />

a_bit_field match_mode :1;<br />

const char _fd_ * match_pos;<br />

MSG_CALLBACK statusrtn;<br />

const char _fd_ * encryption_key;<br />

a_bit_field show_undo :1;<br />

const char _fd_ * logs_dir;<br />

} a_translate_log;<br />

Die Parameter entsprechen Funktionen, die über das Dienstprogramm dbtran<br />

zugänglich sind.<br />

In der Header-Datei dbtools.h finden Sie weitere Kommentare.<br />

"DBTranslateLog-Funktion" auf Seite 332<br />

"a_name-Struktur" auf Seite 351<br />

"dbtran_userlist_type-Aufzählungstyp" auf Seite 368<br />

$ Weitere Hinweise zu Callback-Funktionen finden Sie unter "Callback-<br />

Funktionen verwenden" auf Seite 316.<br />

Enthält Informationen, die <strong>für</strong> das Kürzen des Transaktionslogs mit der<br />

DBTools-Bibliothek gebraucht werden.


Syntax<br />

Parameter<br />

Siehe auch<br />

an_unload_db-Struktur<br />

Funktion<br />

typedef struct a_truncate_log {<br />

unsigned short version;<br />

const char * connectparms;<br />

const char * startline;<br />

MSG_CALLBACK errorrtn;<br />

MSG_CALLBACK msgrtn;<br />

a_bit_field quiet : 1;<br />

char truncate_interrupted;<br />

} a_truncate_log;<br />

Kapitel 8 Die DBTools-Schnittstelle<br />

Mitglied Beschreibung<br />

version DBTools-Versionsnummer<br />

connectparms Parameter <strong>für</strong> die Verbindung zur Datenbank. Sie haben<br />

die Form von Zeichenfolgen, zum Beispiel:<br />

"UID=DBA;PWD=SQL;DBF=c:\asa\asademo.db"<br />

$ Alle Zeichenfolgen <strong>für</strong> die Verbindung finden Sie<br />

unter "Verbindungsparameter" auf Seite 78 der<br />

Dokumentation ASA Datenbankadministration<br />

startline Befehlszeile zum Starten der Datenbank-Engine. Das<br />

folgende Beispiel zeigt eine Startzeile:<br />

"c:\asa\win32\dbeng8.exe"<br />

Die standardmäßige Startzeile wird benutzt, wenn dieses<br />

Element NULL ist.<br />

errorrtn Callback-Routine <strong>für</strong> die Behandlung einer Fehlermeldung<br />

msgrtn Callback-Routine <strong>für</strong> die Behandlung einer<br />

Informationsnachricht<br />

quiet Ohne die Ausgabe von Nachrichten arbeiten (1) oder<br />

Nachrichten ausgeben (0)<br />

truncate_interrupted Gibt an, dass der Vorgang unterbrochen wurde<br />

"DBTruncateLog-Funktion" auf Seite 332<br />

$ Weitere Hinweise zu Callback-Funktionen finden Sie unter "Callback-<br />

Funktionen verwenden" auf Seite 316.<br />

Enthält die Informationen, die gebraucht werden, um eine Datenbank mit der<br />

DBTools-Bibliothek zu entladen oder um eine entfernte Datenbank <strong>für</strong> SQL<br />

Remote zu extrahieren. Die Felder, die vom SQL Remote-<br />

Extraktionsdienstprogramm dbxtract benutzt werden, sind gekennzeichnet.<br />

359


DBTools-Strukturen<br />

Syntax<br />

360<br />

typedef struct an_unload_db {<br />

unsigned short version;<br />

const char * connectparms;<br />

const char * startline;<br />

const char * temp_dir;<br />

const char * reload_filename;<br />

MSG_CALLBACK errorrtn;<br />

MSG_CALLBACK msgrtn;<br />

MSG_CALLBACK statusrtn;<br />

MSG_CALLBACK confirmrtn;<br />

char unload_type;<br />

char verbose;<br />

a_bit_field unordered : 1;<br />

a_bit_field no_confirm : 1;<br />

a_bit_field use_internal_unload : 1;<br />

a_bit_field dbo_avail : 1;<br />

a_bit_field extract : 1;<br />

a_bit_field table_list_provided : 1;<br />

a_bit_field exclude_tables : 1;<br />

a_bit_field more_flag_bits_present : 1;<br />

a_sysinfo sysinfo;<br />

const char * remote_dir;<br />

const char * dbo_username;<br />

const char * subscriber_username;<br />

const char * publisher_address_type;<br />

const char * publisher_address;<br />

unsigned short isolation_level;<br />

a_bit_field start_subscriptions : 1;<br />

a_bit_field exclude_foreign_keys : 1;<br />

a_bit_field exclude_procedures : 1;<br />

a_bit_field exclude_triggers : 1;<br />

a_bit_field exclude_views : 1;<br />

a_bit_field isolation_set : 1;<br />

a_bit_field include_where_subscribe : 1;<br />

a_bit_field debug : 1;<br />

p_name table_list;<br />

a_bit_short escape_char_present : 1;<br />

a_bit_short view_iterations_present : 1;<br />

unsigned short view_iterations;


Parameter<br />

Siehe auch<br />

an_upgrade_db-Struktur<br />

Funktion<br />

Kapitel 8 Die DBTools-Schnittstelle<br />

char escape_char;<br />

char _fd_ * reload_connectparms;<br />

char _fd_ * reload_db_filename;<br />

a_bit_field output_connections:1;<br />

char unload_interrupted;<br />

a_bit_field replace_db:1;<br />

const char _fd_ * locale;<br />

const char _fd_ * site_name;<br />

const char _fd_ * template_name;<br />

a_bit_field preserve_ids:1;<br />

a_bit_field exclude_hooks:1;<br />

char _fd_ * reload_db_logname;<br />

const char _fd_ * encryption_key;<br />

const char _fd_ * encryption_algorithm;<br />

a_bit_field syntax_version_7:1;<br />

a_bit_field remove_java:1;<br />

} an_unload_db;<br />

Die Parameter entsprechen Funktionen, die über die Dienstprogramme<br />

dbunload und dbxtract und mlxtract zugänglich sind.<br />

In der Header-Datei dbtools.h finden Sie weitere Kommentare.<br />

"DBUnload-Funktion" auf Seite 333<br />

"a_name-Struktur" auf Seite 351<br />

"dbunload-Aufzählungstyp" auf Seite 368<br />

$ Weitere Hinweise zu Callback-Funktionen finden Sie unter "Callback-<br />

Funktionen verwenden" auf Seite 316.<br />

Enthält die Informationen, die gebraucht werden, um eine Datenbank mit der<br />

DBTools-Bibliothek zu aktualisieren.<br />

361


DBTools-Strukturen<br />

Syntax<br />

Parameter<br />

362<br />

typedef struct an_upgrade_db {<br />

unsigned short version;<br />

const char * connectparms;<br />

const char * startline;<br />

MSG_CALLBACK errorrtn;<br />

MSG_CALLBACK msgrtn;<br />

MSG_CALLBACK statusrtn;<br />

a_bit_field quiet : 1;<br />

a_bit_field dbo_avail : 1;<br />

const char * dbo_username;<br />

a_bit_field java_classes : 1;<br />

a_bit_field jconnect : 1;<br />

a_bit_field remove_java : 1;<br />

a_bit_field java_switch_specified : 1;<br />

const char * jdk_version;<br />

} an_upgrade_db;<br />

Mitglied Beschreibung<br />

version DBTools-Versionsnummer<br />

connectparms Parameter <strong>für</strong> die Verbindung zur Datenbank. Sie haben die<br />

Form von Zeichenfolgen, zum Beispiel:<br />

"UID=DBA;PWD=SQL;DBF=c:\asa\asademo.db"<br />

$ Alle Zeichenfolgen <strong>für</strong> die Verbindung finden Sie unter<br />

"Verbindungsparameter" auf Seite 78 der Dokumentation ASA<br />

Datenbankadministration<br />

startline Befehlszeile zum Starten der Datenbank-Engine. Das folgende<br />

Beispiel zeigt eine Startzeile:<br />

"c:\asa\win32\dbeng8.exe"<br />

Die standardmäßige Startzeile wird benutzt, wenn dieses<br />

Element NULL ist.<br />

errorrtn Callback-Routine <strong>für</strong> die Behandlung einer Fehlermeldung<br />

msgrtn Callback-Routine <strong>für</strong> die Behandlung einer<br />

Informationsnachricht<br />

statusrtn Callback-Routine <strong>für</strong> die Behandlung einer Statusmeldung<br />

quiet Ohne die Ausgabe von Nachrichten arbeiten (1) oder<br />

Nachrichten ausgeben (0)<br />

dbo_avail Auf 1 gesetzt. Zeigt an, dass die DBTools-Version neu genug<br />

ist, um das Feld dbo_mirrorname zu unterstützen


Siehe auch<br />

a_validate_db-Struktur<br />

Funktion<br />

Syntax<br />

Mitglied Beschreibung<br />

dbo_username Der <strong>für</strong> den dbo zu benutzende Name<br />

Kapitel 8 Die DBTools-Schnittstelle<br />

java_classes Datenbank umstellen, sodass sie Java enthält<br />

jconnect Datenbank umstellen, sodass sie jConnect-Prozeduren<br />

akzeptiert<br />

remove_java Datenbank umstellen, sodass die Java-Funktionen entfernt<br />

werden<br />

jdk_version Einer der Werte <strong>für</strong> die Option dbinit -jdk<br />

"DBUpgrade-Funktion" auf Seite 333<br />

$ Weitere Hinweise zu Callback-Funktionen finden Sie unter "Callback-<br />

Funktionen verwenden" auf Seite 316.<br />

Enthält Informationen, die <strong>für</strong> Datenbankvalidierung mit der DBTools-<br />

Bibliothek gebraucht werden.<br />

typedef struct a_validate_db {<br />

unsigned short version;<br />

const char * connectparms;<br />

const char * startline;<br />

p_name tables;<br />

MSG_CALLBACK errorrtn;<br />

MSG_CALLBACK msgrtn;<br />

MSG_CALLBACK statusrtn;<br />

a_bit_field quiet : 1;<br />

a_bit_field index : 1;<br />

a_validate_type type;<br />

} a_validate_db;<br />

363


DBTools-Strukturen<br />

Parameter<br />

Siehe auch<br />

a_writefile-Struktur<br />

Funktion<br />

364<br />

Mitglied Beschreibung<br />

version DBTools-Versionsnummer<br />

connectparms Parameter <strong>für</strong> die Verbindung zur Datenbank. Sie haben die<br />

Form von Zeichenfolgen, zum Beispiel:<br />

"UID=DBA;PWD=SQL;DBF=c:\asa\asademo.db"<br />

$ Alle Zeichenfolgen <strong>für</strong> die Verbindung finden Sie unter<br />

"Verbindungsparameter" auf Seite 78 der Dokumentation ASA<br />

Datenbankadministration<br />

startline Befehlszeile zum Starten der Datenbank-Engine. Das folgende<br />

Beispiel zeigt eine Startzeile:<br />

"c:\Programme\<strong>Sybase</strong>\SA\win32\dbeng8.exe"<br />

Die standardmäßige Startzeile wird benutzt, wenn dieses Element<br />

NULL ist.<br />

tables Zeiger auf eine verknüpfte Liste mit Tabellennamen<br />

errorrtn Callback-Routine <strong>für</strong> die Behandlung einer Fehlermeldung<br />

msgrtn Callback-Routine <strong>für</strong> die Behandlung einer<br />

Informationsnachricht<br />

statusrtn Callback-Routine <strong>für</strong> die Behandlung einer Statusmeldung<br />

quiet Ohne die Ausgabe von Nachrichten arbeiten (1) oder<br />

Nachrichten ausgeben (0)<br />

index Indizes validieren<br />

type Weitere Hinweise unter "a_validate_type-Aufzählungstyp" auf<br />

Seite 369<br />

"DBValidate-Funktion" auf Seite 334<br />

"a_name-Struktur" auf Seite 351<br />

$ Weitere Hinweise zu Callback-Funktionen finden Sie unter "Callback-<br />

Funktionen verwenden" auf Seite 316.<br />

Enthält Informationen, die <strong>für</strong> die Verwaltung der Datenbank-Write-Datei<br />

mit der DBTools-Bibliothek gebraucht werden.


Syntax<br />

Parameter<br />

Kapitel 8 Die DBTools-Schnittstelle<br />

typedef struct a_writefile {<br />

unsigned short version;<br />

const char * writename;<br />

const char * wlogname;<br />

const char * dbname;<br />

const char * forcename;<br />

MSG_CALLBACK confirmrtn;<br />

MSG_CALLBACK errorrtn;<br />

MSG_CALLBACK msgrtn;<br />

char action;<br />

a_bit_field quiet : 1;<br />

a_bit_field erase : 1;<br />

a_bit_field force : 1;<br />

a_bit_field mirrorname_present : 1;<br />

const char * wlogmirrorname;<br />

a_bit_field make_log_and_mirror_names: 1;<br />

const char * encryption_key;<br />

} a_writefile;<br />

Mitglied Beschreibung<br />

version DBTools-Versionsnummer<br />

writename Name der Write-Datei<br />

wlogname Wird nur <strong>für</strong> die Erstellung von Write-Dateien benutzt<br />

dbname Wird zum Ändern und Erstellen von Write-Dateien<br />

benutzt<br />

forcename Erzwungene Referenz auf einen Dateinamen<br />

confirmrtn Callback-Routine <strong>für</strong> die Bestätigung einer Aktion. Wird<br />

nur <strong>für</strong> die Erstellung einer Write-Datei benutzt<br />

errorrtn Callback-Routine <strong>für</strong> die Behandlung einer<br />

Fehlermeldung<br />

msgrtn Callback-Routine <strong>für</strong> die Behandlung einer<br />

Informationsnachricht<br />

action Reserviert <strong>für</strong> <strong>Sybase</strong><br />

quiet Ohne die Ausgabe von Nachrichten arbeiten (1) oder<br />

Nachrichten ausgeben (0)<br />

erase Wird nur <strong>für</strong> die Erstellung von Write-Dateien benutzt.<br />

Ohne Bestätigung löschen (1) oder mit Bestätigung (0)<br />

365


DBTools-Strukturen<br />

Siehe auch<br />

366<br />

Mitglied Beschreibung<br />

force Falls 1, Write-Datei zwingend auf die angegebene Datei<br />

zeigen lassen<br />

mirrorname_present Wird nur <strong>für</strong> die Erstellung von Write-Dateien benutzt.<br />

Auf 1 setzen; zeigt an, dass die DBTools-Version neu<br />

genug ist, um das Feld mirrorname zu unterstützen<br />

wlogmirrorname Name des Transaktionslogspiegels<br />

make_log_and_mirro<br />

r_names<br />

Wenn auf TRUE, verwenden Sie die Werte in wlogname<br />

und wlogmirrorname benutzt zum Festlegen der<br />

Dateinamen.<br />

encryption_key Der Chiffrierschlüssel <strong>für</strong> die Datenbankdatei.<br />

"DBChangeWriteFile-Funktion" auf Seite 324<br />

"DBCreateWriteFile-Funktion" auf Seite 326<br />

"DBStatusWriteFile-Funktion" auf Seite 329<br />

$ Weitere Hinweise zu Callback-Funktionen finden Sie unter "Callback-<br />

Funktionen verwenden" auf Seite 316.


DBTools-Aufzählungstypen<br />

Verbosity (Ausführlichkeit)<br />

Funktion<br />

Syntax<br />

Parameter<br />

Siehe auch<br />

Kapitel 8 Die DBTools-Schnittstelle<br />

Dieser Abschnitt führt die Aufzählungstypen auf, die von der DBTools-<br />

Bibliothek benutzt werden. Die Aufzählungstypen sind alphabetisch<br />

aufgeführt.<br />

Gibt die Ausführlichkeit der Ausgabe an.<br />

enum {<br />

VB_QUIET,<br />

VB_NORMAL,<br />

VB_VERBOSE<br />

};<br />

Auffüllen mit Leerzeichen<br />

Funktion<br />

Syntax<br />

Parameter<br />

Siehe auch<br />

Wert Beschreibung<br />

VB_QUIET Keine Ausgabe<br />

VB_NORMAL Normale Ausgabemenge<br />

VB_VERBOSE Ausgabe ausführlich darstellen, nützlich <strong>für</strong> die<br />

Fehlersuche<br />

"a_create_db-Struktur" auf Seite 341<br />

"an_unload_db-Struktur" auf Seite 359<br />

Wird in der Struktur "a_create_db" (siehe "a_create_db-Struktur" auf<br />

Seite 341) benutzt, um den Wert von blank_pad anzugeben.<br />

enum {<br />

NO_BLANK_PADDING,<br />

BLANK_PADDING<br />

};<br />

Wert Beschreibung<br />

NO_BLANK_PADDING Benutzt kein Auffüllen mit Leerzeichen<br />

BLANK_PADDING Benutzt Auffüllen mit Leerzeichen<br />

"a_create_db-Struktur" auf Seite 341<br />

367


DBTools-Aufzählungstypen<br />

dbtran_userlist_type-Aufzählungstyp<br />

Funktion<br />

Syntax<br />

Parameter<br />

Siehe auch<br />

dbunload-Aufzählungstyp<br />

Funktion<br />

Syntax<br />

Parameter<br />

Siehe auch<br />

368<br />

Typ einer Benutzerliste, wie er unter "a_translate_log-Struktur" auf Seite 357<br />

beschrieben ist.<br />

typedef enum dbtran_userlist_type {<br />

DBTRAN_INCLUDE_ALL,<br />

DBTRAN_INCLUDE_SOME,<br />

DBTRAN_EXCLUDE_SOME<br />

} dbtran_userlist_type;<br />

Wert Beschreibung<br />

DBTRAN_INCLUDE_ALL Alle Benutzervorgänge einschliessen<br />

DBTRAN_INCLUDE_SOME Nur Vorgänge der in der Benutzerliste<br />

aufgeführten Benutzer einschliessen<br />

DBTRAN_EXCLUDE_SOME Vorgänge der in der Benutzerliste<br />

aufgeführten Benutzer ausschliessen<br />

"a_translate_log-Struktur" auf Seite 357<br />

Der Entladungstyp, der von der Struktur "an_unload-db" (siehe<br />

"an_unload_db-Struktur" auf Seite 359) benutzt wird.<br />

enum {<br />

UNLOAD_ALL,<br />

UNLOAD_DATA_ONLY,<br />

UNLOAD_NO_DATA<br />

};<br />

Wert Beschreibung<br />

UNLOAD_ALL Sowohl Daten wie auch Schema entladen<br />

UNLOAD_DATA_ONLY Daten entladen Schema nicht entladen.<br />

UNLOAD_NO_DATA Nur Schema entladen<br />

"an_unload_db-Struktur" auf Seite 359


a_validate_type-Aufzählungstyp<br />

Funktion<br />

Syntax<br />

Parameter<br />

Siehe auch<br />

Kapitel 8 Die DBTools-Schnittstelle<br />

Der ausgeführte Validierungstyp gemäß "a_validate_db-Struktur" auf<br />

Seite 363.<br />

typedef enum {<br />

VALIDATE_NORMAL = 0,<br />

VALIDATE_DATA,<br />

VALIDATE_INDEX,<br />

VALIDATE_EXPRESS,<br />

VALIDATE_FULL<br />

} a_validate_type;<br />

Wert Beschreibung<br />

VALIDATE_NORMAL Nur mit der Standardprüfung validieren<br />

VALIDATE_DATA Zusätzlich zur Standardprüfung mit der Datenprüfung<br />

validieren<br />

VALIDATE_INDEX Zusätzlich zur Standardprüfung mit der Indexprüfung<br />

validieren<br />

VALIDATE_EXPRESS Zusätzlich zur Standard- und Datenprüfung mit der<br />

Expressprüfung validieren<br />

VALIDATE_FULL Zusätzlich zur Standardprüfung mit der Daten- und<br />

Indexprüfung validieren<br />

"Datenbank mit dem Befehlszeilenprogramm ""dbvalid"" validieren" auf<br />

Seite 589 der Dokumentation ASA Datenbankadministration<br />

"VALIDATE TABLE-Anweisung" auf Seite 632 der Dokumentation ASA<br />

SQL-Referenzhandbuch<br />

369


DBTools-Aufzählungstypen<br />

370


KAPITEL 9<br />

Die OLE DB- und ADO-<br />

Programmierschnittstellen<br />

Über dieses<br />

Kapitel<br />

Inhalt<br />

In diesem Kapitel wird beschrieben, wie Sie die OLE DB-Schnittstelle zu<br />

<strong>Adaptive</strong> Server <strong>Anywhere</strong> verwenden.<br />

Viele Anwendungen, welche die OLE DB-Schnittstelle verwenden, tun dies<br />

nicht direkt, sondern über das Microsoft ActiveX-Datenobjekt (ADO)-<br />

Programmierungsmodell. In diesem Kapitel wird auch die ADO-<br />

Programmierung mit <strong>Adaptive</strong> Server <strong>Anywhere</strong> beschrieben.<br />

Thema Seite<br />

Einführung zu OLE DB 372<br />

ADO-Programmierung mit <strong>Adaptive</strong> Server <strong>Anywhere</strong> 374<br />

Unterstützte OLE DB-Schnittstellen 382<br />

371


Einführung zu OLE DB<br />

Einführung zu OLE DB<br />

Unterstützte Plattformen<br />

372<br />

OLE DB ist ein Datenzugriffsmodell von Microsoft. Es verwendet<br />

Component Object Model (COM)-Schnittstellen und, anders als bei ODBC,<br />

wird hier nicht vorausgesetzt, dass die Datenquelle einen SQL-<br />

Abfrageprozessor verwendet.<br />

<strong>Adaptive</strong> Server <strong>Anywhere</strong> enthält einen OLE DB-Provider namens<br />

ASAProv. Dieser Provider steht <strong>für</strong> aktuelle Windows- sowie <strong>für</strong><br />

Windows CE-Plattformen zur Verfügung.<br />

Sie können auf <strong>Adaptive</strong> Server <strong>Anywhere</strong> auch über den Microsoft OLE<br />

DB Provider <strong>für</strong> ODBC (MSDASQL) zusammen mit dem ODBC-Treiber<br />

von <strong>Adaptive</strong> Server <strong>Anywhere</strong> zugreifen.<br />

Die Verwendung des OLE DB-Providers von <strong>Adaptive</strong> Server <strong>Anywhere</strong><br />

bietet mehrere Vorteile:<br />

♦ Einige Funktionen, wie z.B. die Aktualisierung über einen Cursor, sind<br />

bei Verwendung der OLE DB/ODBC Brücke nicht verfügbar.<br />

♦ Wenn Sie <strong>Adaptive</strong> Server <strong>Anywhere</strong> OLE DB-Provider verwenden, ist<br />

ODBC <strong>für</strong> Ihre Entwicklung nicht erforderlich.<br />

♦ Mit MSDASQL können OLE DB-Clients mit jedem ODBC-Treiber<br />

arbeiten, wobei jedoch nicht garantiert wird, dass Sie sämtliche<br />

Funktionen jedes ODBC-Treibers nutzen können. Wenn Sie <strong>Adaptive</strong><br />

Server <strong>Anywhere</strong>-Provider verwenden, haben Sie Zugriff auf sämtliche<br />

<strong>Adaptive</strong> Server <strong>Anywhere</strong>-Funktionen aus OLE DB-<br />

Programmierumgebungen.<br />

Der <strong>Adaptive</strong> Server <strong>Anywhere</strong> OLE DB-Provider wurde so entwickelt, dass<br />

er mit OLE DB 2.5 und höher arbeitet. Für Windows CE und Nachfolger<br />

wurde der OLE DB-Provider <strong>für</strong> ADOCE 3.0 und höher entwickelt.<br />

ADOCE ist der Microsoft ADO <strong>für</strong> Windows CE SDK und bietet<br />

Datenbankfunktionen <strong>für</strong> Anwendungen, die mit den Windows CE Toolkits<br />

<strong>für</strong> Visual Basic 5.0 und Visual Basic 6.0 entwickelt wurden.<br />

$ Eine Liste der unterstützten Plattformen finden Sie unter<br />

"Betriebssystemversionen" auf Seite 150 der Dokumentation SQL <strong>Anywhere</strong><br />

Studio Erste Orientierung.


Verteilte Transaktionen<br />

Kapitel 9 Die OLE DB- und ADO-Programmierschnittstellen<br />

Der OLE DB-Treiber kann in einer Umgebung mit verteilten Transaktionen<br />

als Ressourcen-Manager eingesetzt werden.<br />

$ Weitere Hinweise finden Sie unter "Dreischichtige Datenverarbeitung<br />

und verteilte Transaktionen" auf Seite 399.<br />

373


ADO-Programmierung mit <strong>Adaptive</strong> Server <strong>Anywhere</strong><br />

ADO-Programmierung mit <strong>Adaptive</strong> Server<br />

<strong>Anywhere</strong><br />

374<br />

Bei ADO (ActiveX-Datenobjekte) handelt es sich um ein<br />

Datenzugriffsmodell, das über eine Automationsschnittstelle zugänglich<br />

wird, die es Clientanwendungen ermöglicht, die Methoden und<br />

Eigenschaften von Objekten in Laufzeit zu erfassen, ohne das Objekt vorher<br />

zu kennen. Mit Hilfe von Automation können Skriptsprachen wie Visual<br />

Basic ein Standardmodell <strong>für</strong> Datenzugriffsobjekte verwenden. ADO<br />

verwendet OLE DB, um den Datenzugriff bereitzustellen.<br />

Wenn Sie den <strong>Adaptive</strong> Server <strong>Anywhere</strong> OLE DB-Provider verwenden,<br />

haben Sie aus einer ADO-Programmierungsumgebung Zugriff auf sämtliche<br />

<strong>Adaptive</strong> Server <strong>Anywhere</strong>-Funktionen.<br />

In diesem Abschnitt wird beschrieben, wie grundlegende Aufgaben während<br />

der Verwendung von ADO aus Visual Basic ausgeführt werden. Er stellt<br />

keine vollständige Anleitung zur Programmierung mit ADO dar.<br />

Codebeispiele aus diesem Abschnitt finden Sie in den folgenden Dateien:<br />

Entwicklungs-Tool Beispiel<br />

Microsoft Visual Basic<br />

6.0<br />

Samples\ASA\VBSampler\vbsampler.vbp<br />

Microsoft eMbedded<br />

Visual Basic 3.0<br />

Samples\ASA\ADOCE\OLEDB_PocketPC.ebp<br />

$ Weitere Hinweise zur Programmierung in ADO finden Sie im<br />

<strong>Handbuch</strong> Ihres Entwicklungstools.<br />

$ Detaillierte Erläuterungen zur Verwendung von ADO und Visual<br />

Basic, um auf Daten in einer <strong>Adaptive</strong> Server <strong>Anywhere</strong>-Datenbank<br />

zuzugreifen, finden Sie im Whitepaper "Accessing Data in <strong>Adaptive</strong> Server<br />

<strong>Anywhere</strong> Using ADO and Visual Basic" unter<br />

http://www.sybase.com/detail?id=1017429.<br />

Eine Datenbank mit einem Verbindungsobjekt verbinden<br />

In diesem Abschnitt wird eine einfache Visual Basic-Routine beschrieben,<br />

die eine Verbindung zu einer Datenbank herstellt.


Beispielcode<br />

Hinweise<br />

Kapitel 9 Die OLE DB- und ADO-Programmierschnittstellen<br />

Sie können diese Routine ausprobieren, indem Sie eine Befehlsschaltfläche<br />

namens Command1 in einer Maske platzieren und die Routine in ihr Click-<br />

Ereignis einfügen. Führen Sie das Programm aus und klicken Sie auf die<br />

Schaltfläche, um eine Verbindung herzustellen und trennen Sie die<br />

Verbindung dann.<br />

Private Sub cmdTestConnection_Click()<br />

’ Variable deklarieren<br />

Dim myConn As New ADODB.Connection<br />

Dim myCommand As New ADODB.Command<br />

Dim cAffected As Long<br />

On Error GoTo HandleError<br />

’ Verbindung herstellen<br />

myConn.Provider = "ASAProv"<br />

myConn.ConnectionString = _<br />

"Data Source=ASA 8.0 Sample"<br />

myConn.Open<br />

MsgBox "Verbindung erfolgreich"<br />

myConn.Close<br />

Exit Sub<br />

HandleError:<br />

MsgBox "Verbindung nicht erfolgreich"<br />

Exit Sub<br />

End Sub<br />

Das Beispiel führt die folgenden Aufgaben aus:<br />

♦ Es deklariert die Variablen, die in der Routine verwendet werden.<br />

♦ Es stellt mit Hilfe des OLE DB-Providers von <strong>Adaptive</strong> Server<br />

<strong>Anywhere</strong> eine Verbindung zur Beispieldatenbank her.<br />

♦ Es verwendet ein Befehlsobjekt zur Ausführung einer einfachen<br />

Anweisung, die eine Meldung im Fenster des Datenbankservers anzeigt.<br />

♦ Es beendet die Verbindung.<br />

Wenn der ASAProv-Provider installiert ist, registriert er sich selbst. Der<br />

Registriervorgang umfasst auch die Registriereinträge in dem Abschnitt<br />

COM der Registry, sodass ADO die Position der DLL ermitteln kann, wenn<br />

der ASAProv-Provider aufgerufen wird. Wenn Sie den Speicherort Ihrer<br />

DLL ändern, müssen Sie sie neu registrieren.<br />

v So registrieren Sie den OLE DB-Provider:<br />

1 Öffnen Sie eine Befehlszeile.<br />

375


ADO-Programmierung mit <strong>Adaptive</strong> Server <strong>Anywhere</strong><br />

376<br />

2 Wechseln Sie zu dem Verzeichnis, in dem der OLE DB-Provider<br />

installiert ist.<br />

3 Geben Sie den folgenden Befehl ein, um den Provider zu registrieren:<br />

regsvr32 dboledb8.dll<br />

$ Weitere Hinweise, wie Sie mit OLE DB eine Verbindung zu einer<br />

Datenbank herstellen, finden Sie unter "Verbinden mit einer Datenbank über<br />

OLE DB" auf Seite 75 der Dokumentation ASA Datenbankadministration.<br />

Anweisungen mit dem Befehlsobjekt ausführen<br />

Beispielcode<br />

Hinweise<br />

In diesem Abschnitt wird eine einfache Routine beschrieben, die eine<br />

einfache SQL-Anweisung an die Datenbank sendet.<br />

Sie können diese Routine ausprobieren, indem Sie eine Befehlsschaltfläche<br />

namens Command2 in einer Maske platzieren und die Routine in ihr Click-<br />

Ereignis einfügen. Führen Sie das Programm aus und klicken Sie auf die<br />

Schaltfläche, um eine Verbindung herzustellen, eine Meldung im Fenster des<br />

Datenbankservers anzuzeigen, und trennen Sie die Verbindung dann.<br />

Private Sub cmdUpdate_Click()<br />

’ Variable deklarieren<br />

Dim myConn As New ADODB.Connection<br />

Dim myCommand As New ADODB.Command<br />

Dim cAffected As Long<br />

’Verbindung herstellen<br />

myConn.Provider = "ASAProv"<br />

myConn.ConnectionString = _<br />

"Data Source=ASA 8.0 Sample"<br />

myConn.Open<br />

'Befehl ausführen<br />

myCommand.CommandText = _<br />

"update customer set fname='Liz' where id=102"<br />

Set myCommand.ActiveConnection = myConn<br />

myCommand.Execute cAffected<br />

MsgBox CStr(cAffected) +<br />

" rows affected.", vbInformation<br />

myConn.Close<br />

End Sub<br />

Nachdem eine Verbindung hergestellt wurde, erstellt der Beispielcode ein<br />

Befehlsobjekt und stellt die Eigenschaft CommandText auf eine Update-<br />

Anweisung und die Eigenschaft ActiveConnection auf die aktuelle<br />

Verbindung ein. Dann führt er die Update-Anweisung aus und zeigt die<br />

Anzahl der von der Aktualisierung betroffenen Zeilen in einem<br />

Meldungsfeld an.


Kapitel 9 Die OLE DB- und ADO-Programmierschnittstellen<br />

In diesem Beispiel wird die Aktualisierung an die Datenbank gesendet und<br />

festgeschrieben, sobald sie ausgeführt wurde.<br />

$ Weitere Hinweise zur Verwendung von Transaktionen in ADO finden<br />

Sie unter "Transaktionen verwenden" auf Seite 381.<br />

Sie können Aktualisierungen auch über einen Cursor ausführen.<br />

$ Weitere Hinweise finden Sie unter "Daten mit einem Cursor<br />

aktualisieren" auf Seite 379.<br />

Datenbank mit dem Recordset-Objekt abfragen<br />

Beispielcode<br />

Das ADO-Recordset-Objekt stellt die Ergebnismenge einer Abfrage dar. Sie<br />

können es benutzen, um Daten aus einer Datenbank anzuzeigen.<br />

Sie können diese Routine ausprobieren, indem Sie eine Befehlsschaltfläche<br />

mit dem Namen cmdQuery in ein Formular einfügen und die Routine in ihr<br />

Click-Ereignis einfügen. Führen Sie das Programm aus und klicken Sie auf<br />

die Schaltfläche, um eine Verbindung herzustellen, eine Meldung im Fenster<br />

des Datenbankservers anzuzeigen, eine Abfrage auszuführen und die ersten<br />

Zeilen in Meldungsfeldern anzuzeigen. Danach trennen Sie die Verbindung.<br />

377


ADO-Programmierung mit <strong>Adaptive</strong> Server <strong>Anywhere</strong><br />

Hinweise<br />

378<br />

Private Sub cmdQuery_Click()<br />

’ Variable deklarieren<br />

Dim myConn As New ADODB.Connection<br />

Dim myCommand As New ADODB.Command<br />

Dim myRS As New ADODB.Recordset<br />

On Error GoTo ErrorHandler:<br />

’ Verbindung herstellen<br />

myConn.Provider = "ASAProv"<br />

myConn.ConnectionString = _<br />

"Data Source=ASA 8.0 Sample"<br />

myConn.CursorLocation = adUseServer<br />

myConn.Mode = adModeReadWrite<br />

myConn.IsolationLevel = adXactCursorStability<br />

myConn.Open<br />

'Eine Abfrage ausführen<br />

Set myRS = New Recordset<br />

myRS.CacheSize = 50<br />

myRS.Source = "Select * from customer"<br />

myRS.ActiveConnection = myConn<br />

myRS.CursorType = adOpenKeyset<br />

myRS.LockType = adLockOptimistic<br />

myRS.Open<br />

'Durch die ersten Ergebnisse blättern<br />

myRS.MoveFirst<br />

For i = 1 To 5<br />

MsgBox myRS.Fields("company_name"), vbInformation<br />

myRS.MoveNext<br />

Next<br />

myRS.Close<br />

myConn.Close<br />

Exit Sub<br />

ErrorHandler:<br />

MsgBox Error(Err)<br />

Exit Sub<br />

End Sub<br />

Das Recordset-Objekt in diesem Beispiel enthält die Ergebnisse aus einer<br />

Abfrage der Tabelle Kunden. Die Schleife For blättert durch die ersten<br />

Zeilen und zeigt den Wert company_name <strong>für</strong> jede Zeile an.<br />

Hierbei handelt es sich um ein einfaches Beispiel <strong>für</strong> die Verwendung eines<br />

Cursors aus ADO.<br />

$ Weiterführende Beispiele <strong>für</strong> die Verwendung eines Cursors aus ADO<br />

finden Sie unter "Mit dem Recordset-Objekt arbeiten" auf Seite 379.


Mit dem Recordset-Objekt arbeiten<br />

Cursortypen<br />

Beispielcode<br />

Kapitel 9 Die OLE DB- und ADO-Programmierschnittstellen<br />

Bei der Arbeit mit <strong>Adaptive</strong> Server <strong>Anywhere</strong> stellt die ADO Recordset<br />

einen Cursor dar. Sie können den Cursortyp auswählen, indem Sie eine<br />

CursorType-Eigenschaft des Recordset-Objekts deklarieren, bevor Sie das<br />

Recordset öffnen. Die Auswahl des Cursortyps beeinflusst die Aktionen, die<br />

Sie am Recordset vornehmen können und hat Auswirkungen auf die<br />

Performance.<br />

Die von <strong>Adaptive</strong> Server <strong>Anywhere</strong> unterstützten Cursortypen werden in<br />

"Cursoreigenschaften" auf Seite 26 beschrieben. ADO hat seine eigene<br />

Namenskonvention <strong>für</strong> Cursortypen.<br />

Die verfügbaren Cursortypen, die entsprechenden Cursortypenkonstanten<br />

und die <strong>Adaptive</strong> Server <strong>Anywhere</strong>-Typen, denen sie entsprechen, sind hier<br />

aufgelistet:<br />

ADO-Cursortyp ADO-Konstante <strong>Adaptive</strong> Server<br />

<strong>Anywhere</strong>-Typ<br />

Dynamischer<br />

Cursor<br />

Schlüsselgruppen-<br />

Cursor<br />

adOpenDynamic Dynamisch abrollender<br />

Cursor<br />

adOpenKeyset Abrollender Cursor<br />

Statischer Cursor adOpenStatic Unempfindlicher Cursor<br />

Vorwärts-Cursor adOpenForwardOnly Nicht-abrollender Cursor<br />

$ Weitere Hinweise zur Auswahl eines <strong>für</strong> Ihre Anwendung geeigneten<br />

Cursortyps finden Sie unter "Cursortypen auswählen" auf Seite 26.<br />

Der folgende Code legt den Cursortyp <strong>für</strong> ein ADO Recordset-Objekt fest:<br />

Dim myRS As New ADODB.Recordset<br />

myRS.CursorType = adOpenDynamic<br />

Daten mit einem Cursor aktualisieren<br />

Recordsets<br />

aktualisieren<br />

Mit dem <strong>Adaptive</strong> Server <strong>Anywhere</strong> OLE DB-Provider können Sie eine<br />

Ergebnismenge über einen Cursor aktualisieren. Diese Funktion ist über den<br />

MSDASQL-Provider nicht verfügbar.<br />

Sie können die Datenbank über einen Recordset aktualisieren.<br />

Private Sub Command6_Click()<br />

Dim myConn As New ADODB.Connection<br />

Dim myRS As New ADODB.Recordset<br />

Dim SQLString As String<br />

379


ADO-Programmierung mit <strong>Adaptive</strong> Server <strong>Anywhere</strong><br />

Hinweise<br />

380<br />

’ Verbindung herstellen<br />

myConn.Provider = "ASAProv"<br />

myConn.ConnectionString = _<br />

"Data Source=ASA 8.0 Sample"<br />

myConn.Open<br />

myConn.BeginTrans<br />

SQLString = "Select * from customer"<br />

myRS.Open SQLString, _<br />

myConn, adOpenDynamic, adLockBatchOptimistic<br />

If myRS.BOF And myRS.EOF Then<br />

MsgBox "Recordset ist leer!", _<br />

16, "Leeres Recordset"<br />

Else<br />

MsgBox "Cursor-Typ: " + _<br />

CStr(myRS.CursorType), vbInformation<br />

myRS.MoveFirst<br />

For i = 1 To 3<br />

MsgBox "Zeile: " + CStr(myRS.Fields("id")), _<br />

vbInformation<br />

If i = 2 Then<br />

myRS.Update "City", "Toronto"<br />

myRS.UpdateBatch<br />

End If<br />

myRS.MoveNext<br />

Next i<br />

’ myRS.MovePrevious<br />

myRS.Close<br />

End If<br />

myConn.CommitTrans<br />

myConn.Close<br />

End Sub<br />

Wenn Sie die Einstellung adLockBatchOptimistic <strong>für</strong> das Recordset<br />

verwenden, werden bei der myRS.Update-Methode keine Änderungen an<br />

der Datenbank selbst vorgenommen. Statt dessen wird eine lokale Kopie des<br />

Recordsets aktualisiert.<br />

Die myRS.UpdateBatch-Methode nimmt die Aktualisierung am<br />

Datenbankserver vor, schreibt sie jedoch nicht fest, da sie sich innerhalb<br />

einer Transaktion befindet. Wenn eine UpdateBatch-Methode von<br />

außerhalb einer Transaktion aufgerufen wurde, werden die Änderungen<br />

festgeschrieben.<br />

Die Methode myConn.CommitTrans schreibt die Änderungen fest. Das<br />

Recordset-Objekt wurde zwischenzeitlich geschlossen, sodass das Problem,<br />

ob die lokale Kopie der Daten geändert wurde oder nicht, nicht mehr besteht.


Transaktionen verwenden<br />

Kapitel 9 Die OLE DB- und ADO-Programmierschnittstellen<br />

Standardmäßig werden sämtliche Änderungen, die Sie mit ADO an der<br />

Datenbank vornehmen, festgeschrieben, sobald sie ausgeführt werden.<br />

Hierzu gehören auch explizite Aktualisierungen und die UpdateBatch-<br />

Methode <strong>für</strong> einen Recordset. Im vorherigen Abschnitt wurde jedoch<br />

gezeigt, dass Sie die Methoden BeginTrans und RollbackTrans oder<br />

CommitTrans auf das Connection-Objekt anwenden können, um<br />

Transaktionen zu benutzen.<br />

Die Transaktions-Isolationsstufe wird als eine Eigenschaft des<br />

Verbindungsobjekts festgelegt. Die Eigenschaft IsolationLevel kann einen<br />

der folgenden Werte annehmen:<br />

ADO-Isolationsstufe Konstante ASA-Stufe<br />

Unbekannt (Unspecified) adXactUnspecified Nicht anwendbar. Auf 0<br />

setzen<br />

Chaos adXactChaos Nicht unterstützt. Auf 0<br />

setzen<br />

Durchsuchen (Browse) adXactBrowse 0<br />

Nicht festgeschriebene<br />

Lesevorgänge (Read<br />

uncommitted)<br />

Cursorstabilität (Cursor<br />

stability)<br />

Festgeschriebene<br />

Lesevorgänge (Read<br />

committed)<br />

Wiederholbare<br />

Lesevorgänge (reatable<br />

read)<br />

adXactReadUncommitted 0<br />

adXactCursorStability 1<br />

adXactReadCommitted 1<br />

adXactRepeatableRead 2<br />

Isoliert (Isolated) adXactIsolated 3<br />

Serialisierbar<br />

(Serializable)<br />

adXactSerializable 3<br />

$ Weitere Hinweise zu Isolationsstufen finden Sie unter "Isolationsstufen<br />

und Konsistenz" auf Seite 105 der Dokumentation ASA SQL-<br />

Benutzerhandbuch.<br />

381


Unterstützte OLE DB-Schnittstellen<br />

Unterstützte OLE DB-Schnittstellen<br />

382<br />

Die OLE DB API besteht aus einer Reihe von Schnittstellen. In der<br />

folgenden Tabelle wird die Unterstützung <strong>für</strong> jede Schnittstelle im OLE DB-<br />

Treiber von <strong>Adaptive</strong> Server <strong>Anywhere</strong> beschrieben.<br />

Schnittstelle Verwendung Einschränkungen<br />

IAccessor Bindungen zwischen<br />

Clientspeicher- und<br />

Datenspeicherwerten<br />

definieren<br />

IAlterIndex<br />

IAlterTable<br />

Tabellen, Indizes und<br />

Spalten ändern<br />

IChapteredRowset Mit einer segmentierten<br />

Zeilengruppe kann auf<br />

Zeilen einer Zeilengruppe<br />

in getrennten Kapiteln<br />

zugegriffen werden<br />

IColumnsInfo Einfache Informationen zu<br />

Spalten in einer Zeilengruppe<br />

erhalten<br />

IColumnsRowset Informationen zu<br />

optionalen<br />

Metadatenspalten in einer<br />

Zeilengruppe und eine<br />

Zeilengruppe von Spalten-<br />

Metadaten erhalten<br />

DBACCESSOR_PA<br />

SSBYREF nicht<br />

unterstützt<br />

DBACCESSOR_OP<br />

TIMIZED nicht<br />

unterstützt<br />

Nicht unterstützt<br />

Nicht unterstützt<br />

<strong>Adaptive</strong> Server<br />

<strong>Anywhere</strong> untersützt<br />

segmentierte<br />

Zeilengruppen nicht.<br />

Nicht <strong>für</strong> CE<br />

Nicht <strong>für</strong> CE<br />

ICommand SQL-Befehle ausführen Unterstützt keinen<br />

Aufruf<br />

ICommandPropertie<br />

s<br />

GetProperties mit<br />

DBPROPSET_PRO<br />

PERTIESINERROR<br />

um Eigenschaften zu<br />

finden, die nicht<br />

gesetzt werden<br />

konnten.


Kapitel 9 Die OLE DB- und ADO-Programmierschnittstellen<br />

Schnittstelle Verwendung Einschränkungen<br />

ICommandPersist Zustand eines<br />

Befehlsobjekts (jedoch<br />

nicht jede aktive Zeilengruppe)<br />

aufrechterhalten.<br />

Diese beständigen<br />

Befehlsobjekte können<br />

nachfolgend mit der<br />

Zeilengruppe<br />

PROCEDURES oder<br />

VIEWS nummeriert<br />

werden.<br />

Nicht <strong>für</strong> CE<br />

ICommandPrepare Befehle vorbereiten. Nicht <strong>für</strong> CE<br />

ICommandProperties Zeilengruppeneigenschaften<br />

<strong>für</strong> von einem Befehl<br />

erstellte Zeilengruppen<br />

festlegen. Häufig<br />

verwendet, um die<br />

Schnittstellen anzugeben,<br />

welche die Zeilengruppe<br />

unterstützen sollen<br />

ICommandText SQL-Befehlstext <strong>für</strong><br />

Icommand festlegen<br />

IcommandWithParameters Parameterinformationen <strong>für</strong><br />

einen Befehl festlegen und<br />

beziehen<br />

Unterstützt<br />

Nur der SQL-<br />

Dialekt<br />

DBGUID_DEFAUL<br />

T wird unterstützt<br />

Nicht <strong>für</strong> Parameter<br />

unterstützt, die als<br />

Vektoren skalarer<br />

Werte gespeichert<br />

werden<br />

Keine Unterstützung<br />

<strong>für</strong> BLOB-<br />

Parameter<br />

Nicht <strong>für</strong> CE<br />

IConvertType Unterstützt<br />

Für CE<br />

eingeschränkte<br />

Unterstützung<br />

383


Unterstützte OLE DB-Schnittstellen<br />

384<br />

Schnittstelle Verwendung Einschränkungen<br />

IDBAsynchNotify<br />

IDBAsyncStatus<br />

Asynchrone Verarbeitung<br />

Client über Ereignisse in<br />

der asynchronen<br />

Verarbeitung bei der<br />

Initialisierung von<br />

Datenquellen, dem<br />

Anfüllen von Zeilengruppen,<br />

usw. informieren<br />

IDBCreateCommand Befehle aus einer Sitzung<br />

erstellen<br />

IDBCreateSession Eine Sitzung aus einem<br />

Datenquellenobjekt<br />

erstellen.<br />

IDBDataSourceAdmin Datenquellenobjekte, bei<br />

denen es sich um COM-<br />

Objekte handelt, die von<br />

Clients unterstützt werden,<br />

erstellen/zerstören/ändern.<br />

Diese Schnittstelle wird<br />

nicht <strong>für</strong> die Verwaltung<br />

von Datenspeichern<br />

(Datenbanken) verwendet.<br />

IDBInfo Informationen über<br />

Schlüsselwörter suchen, die<br />

<strong>für</strong> diesen Provider<br />

eindeutig sind (d.h.<br />

Schlüsselwörter die nicht<br />

dem Standard-SQL<br />

entsprechen)<br />

Außerdem Informationen<br />

zu Literalen, d.h. Sonderzeichen,<br />

die in textlich<br />

übereinstimmenden<br />

Abfragen verwendet<br />

werden, und andere Literal-<br />

Informationen suchen<br />

IDBInitialize Datenquellenobjekte und<br />

Aufzähler initialisieren.<br />

IDBProperties Eigenschaften <strong>für</strong> ein<br />

Datenquellenobjekt oder<br />

einen Aufzähler verwalten<br />

Nicht unterstützt<br />

Unterstützt<br />

Unterstützt<br />

Nicht unterstützt<br />

Nicht <strong>für</strong> CE<br />

Nicht <strong>für</strong> CE<br />

Nicht <strong>für</strong> CE


Kapitel 9 Die OLE DB- und ADO-Programmierschnittstellen<br />

Schnittstelle Verwendung Einschränkungen<br />

IDBSchemaRowset Informationen zu<br />

Systemtabellen in einer<br />

Standardmaske (einer<br />

Zeilengruppe) beziehen.<br />

IErrorInfo<br />

IErrorLookup<br />

IErrorRecords<br />

Unterstützung von<br />

ActiveX-Fehler-Objekten<br />

IGetDataSource Gibt einen Schnittstellenzeiger<br />

auf das Datenquellenobjekt<br />

einer Sitzung<br />

zurück<br />

IIndexDefinition Indizes im Datenspeicher<br />

erstellen oder löschen<br />

IMultipleResults Mehrere Ergebnisse<br />

(Zeilengruppen oder<br />

Zeilenzählungen) aus einem<br />

Befehl abrufen<br />

IOpenRowset Auf eine Datenbanktabelle<br />

mit ihrem Namen, nicht mit<br />

SQL zugreifen<br />

IParentRowset Auf<br />

segmentierte/hierarchische<br />

Zeilengruppen zugreifen<br />

IRowset Auf Zeilengruppen<br />

zugreifen<br />

IRowsetChange Änderungen an Zeilengruppendaten<br />

zulassen, die<br />

im Datenspeicher reflektiert<br />

werden<br />

InsertRow/SetData <strong>für</strong><br />

Blobs nocht nicht<br />

implementiert<br />

IRowsetChapterMember Auf<br />

segmentierte/hierarchische<br />

Zeilengruppen zugreifen<br />

IRowsetCurrentIndex Index <strong>für</strong> eine Zeilengruppe<br />

dynamisch ändern<br />

Nicht <strong>für</strong> CE<br />

Nicht <strong>für</strong> CE<br />

Unterstützt<br />

Nicht unterstützt<br />

Unterstützt<br />

Unterstützt<br />

Öffnen einer Tabelle<br />

mit ihrem Namen,<br />

nicht über einen<br />

GUID, wird<br />

unterstützt<br />

Nicht unterstützt<br />

Unterstützt<br />

Nicht <strong>für</strong> CE<br />

Nicht unterstützt<br />

Nicht unterstützt<br />

385


Unterstützte OLE DB-Schnittstellen<br />

386<br />

Schnittstelle Verwendung Einschränkungen<br />

IRowsetFind Eine Zeile innerhalb einer<br />

Zeilengruppe, die mit einem<br />

spezifischen Wert übereinstimmt,<br />

finden<br />

Nicht unterstützt<br />

IRowsetIdentity Zeilen-Handles vergleichen Nicht unterstützt<br />

IRowsetIndex Auf Datenbankindizes<br />

zugreifen<br />

IRowsetInfo Informationen zu einer<br />

Zeilengruppeneigenschaft<br />

suchen oder das Objekt<br />

suchen, das die Zeilengruppe<br />

erstellt hat<br />

IRowsetLocate Position in Zeilen einer<br />

Zeilengruppe, unter<br />

Verwendung von<br />

Bookmarks<br />

IRowsetNotify Bietet eine COM-Callback-<br />

Schnittstelle <strong>für</strong> Zeilengruppen-Ereignisse<br />

IRowsetRefresh Den neuesten Wert <strong>für</strong><br />

Daten beziehen, der <strong>für</strong> eine<br />

Transaktion sichtbar ist<br />

IRowsetResynch Alte OLEDB 1.x-<br />

Schnittstelle, von<br />

IRowsetRefresh abgelöst<br />

IRowsetScroll Durch Zeilengruppe<br />

blättern, um Zeilendaten<br />

abzurufen<br />

IRowsetUpdate Änderungen an<br />

Zeilengruppendaten<br />

verzögern, bis Update<br />

aufgerufen wurde<br />

IRowsetView Ansichten <strong>für</strong> eine<br />

vorhandene Zeilengruppe<br />

verwenden<br />

Nicht unterstützt<br />

Nicht <strong>für</strong> CE<br />

Nicht <strong>für</strong> CE<br />

Unterstützt<br />

Nicht unterstützt<br />

Nicht unterstützt<br />

Nicht unterstützt<br />

Unterstützt<br />

Nicht <strong>für</strong> CE<br />

Nicht unterstützt<br />

ISequentialStream Eine Blob-Spalte abrufen Nur <strong>für</strong> Lesen<br />

unterstützt<br />

Keine Unterstützung<br />

von SetData mit<br />

dieser Schnittstelle<br />

Nicht <strong>für</strong> CE


Kapitel 9 Die OLE DB- und ADO-Programmierschnittstellen<br />

Schnittstelle Verwendung Einschränkungen<br />

ISessionProperties Informationen zu<br />

Sitzungseigenschaften<br />

beziehen<br />

ISourcesRowset Eine Zeilengruppe von<br />

Datenquellenobjekten und<br />

Aufzählern beziehen<br />

ISQLErrorInfo<br />

ISupportErrorInfo<br />

ITableDefinition<br />

ItableDefinitionWithConstraints<br />

Unterstützung von<br />

ActiveX-Fehler-Objekten<br />

Tabellen mit<br />

Integritätsregeln erstellen,<br />

löschen und ändern<br />

ITransaction Transaktionen festschreiben<br />

oder abbrechen<br />

ITransactionJoin Verteilte Transaktionen<br />

werden unterstützt<br />

ITransactionLocal Transaktionen <strong>für</strong> eine<br />

Sitzung werden abgewickelt<br />

Nicht alle Kennzeichnungen<br />

werden<br />

unterstützt<br />

Unterstützt<br />

Nicht <strong>für</strong> CE<br />

Optional <strong>für</strong> CE<br />

Nicht <strong>für</strong> CE<br />

Nicht alle<br />

Kennzeichnungen<br />

werden unterstützt<br />

Nicht <strong>für</strong> CE<br />

Nicht alle<br />

Kennzeichnungen<br />

werden unterstützt<br />

Nicht <strong>für</strong> CE<br />

Nicht <strong>für</strong> CE<br />

387


Unterstützte OLE DB-Schnittstellen<br />

388<br />

Schnittstelle Verwendung Einschränkungen<br />

ITransactionOptions Optionen <strong>für</strong> eine<br />

Transaktion beziehen oder<br />

einstellen<br />

IviewChapter Mit Ansichten <strong>für</strong> eine<br />

vorhandene Zeilengruppe<br />

arbeiten, insbesondere um<br />

Nachbearbeitungsfilter/sortierungen<br />

auf Zeilen<br />

anzuwenden<br />

IviewFilter Inhalte einer Zeilengruppe<br />

werden auf Zeilen, welche<br />

eine Reihe von Bedinungen<br />

erfüllen, beschränkt<br />

IviewRowset Inhalte einer Zeilengruppe<br />

werden beim Öffnen einer<br />

Zeilengruppe auf Zeilen,<br />

welche eine Reihe von<br />

Bedinungen erfüllen,<br />

beschränkt<br />

IviewSort Sortierreihenfolge auf eine<br />

Ansicht anwenden<br />

Nicht <strong>für</strong> CE<br />

Nicht unterstützt<br />

Nicht unterstützt<br />

Nicht unterstützt<br />

Nicht unterstützt.


KAPITEL 10<br />

Die Open Client-Schnittstelle<br />

Über dieses<br />

Kapitel<br />

Inhalt<br />

Dieses Kapitel beschreibt die Open Client-Programmierschnittstelle <strong>für</strong><br />

<strong>Adaptive</strong> Server <strong>Anywhere</strong>.<br />

Die primäre Quelle <strong>für</strong> Informationen zur Open Client-<br />

Anwendungsentwicklung ist die <strong>Sybase</strong> Open Client-Dokumentation. Dieses<br />

Kapitel beschreibt spezifische Funktionen <strong>für</strong> <strong>Adaptive</strong> Server <strong>Anywhere</strong>; es<br />

ist jedoch keine umfassende Anleitung <strong>für</strong> die Anwendungsentwicklung mit<br />

Open Client.<br />

Thema Seite<br />

Was Sie <strong>für</strong> die Entwicklung von Open Client-Anwendungen<br />

brauchen 390<br />

Datentyp-Zuordnungen 391<br />

SQL in Open Client-Anwendungen verwenden<br />

Bekannte Open Client-Einschränkungen von <strong>Adaptive</strong> Server<br />

394<br />

<strong>Anywhere</strong> 398<br />

389


Was Sie <strong>für</strong> die Entwicklung von Open Client-Anwendungen brauchen<br />

Was Sie <strong>für</strong> die Entwicklung von Open Client-<br />

Anwendungen brauchen<br />

390<br />

Um Open Client-Anwendungen auszuführen, müssen Sie Open Client-<br />

Komponenten auf dem Rechner installieren und konfigurieren, auf dem die<br />

Anwendung laufen soll. Diese Komponenten sind eventuell bereits als Teil<br />

Ihrer Installation anderer <strong>Sybase</strong> Produkte vorhanden; andernfalls können<br />

Sie diese Bibliotheken wahlweise mit <strong>Adaptive</strong> Server <strong>Anywhere</strong><br />

entsprechend den Bedingungen Ihres Lizenzvertrags installieren.<br />

Open Client-Anwendungen benötigen keine Open Client-Komponenten auf<br />

dem Rechner, auf dem der Datenbankserver läuft.<br />

Um Open Client-Anwendungen zu erstellen, benötigen Sie die<br />

Entwicklungsversion von Open Client. Diese ist bei <strong>Sybase</strong> erhältlich.<br />

Standardmäßig werden <strong>Adaptive</strong> Server <strong>Anywhere</strong>-Datenbanken ohne<br />

Berücksichtigung von Groß-/Kleinschreibung erstellt, während <strong>Adaptive</strong><br />

Server Enterprise-Datenbanken unter Berücksichtigung von Groß-<br />

/Kleinschreibung erstellt werden.<br />

$ Weitere Hinweise zur Ausführung von Open Client-Anwendungen mit<br />

<strong>Adaptive</strong> Server <strong>Anywhere</strong> finden Sie unter "<strong>Adaptive</strong> Server <strong>Anywhere</strong> als<br />

Open Server" auf Seite 117 der Dokumentation ASA<br />

Datenbankadministration.


Datentyp-Zuordnungen<br />

<strong>Adaptive</strong> Server<br />

<strong>Anywhere</strong>-<br />

Datentypen ohne<br />

direkte<br />

Entsprechung in<br />

Open Client<br />

Kapitel 10 Die Open Client-Schnittstelle<br />

Open Client hat seine eigenen internen Datentypen, die in einigen Details<br />

von den Datentypen abweichen, die in <strong>Adaptive</strong> Server <strong>Anywhere</strong> zur<br />

Verfügung stehen. Aus diesem Grunde ordnet <strong>Adaptive</strong> Server <strong>Anywhere</strong><br />

intern einige Datentypen von Open Client-Anwendungen den in <strong>Adaptive</strong><br />

Server <strong>Anywhere</strong> zur Verfügung stehenden Datentypen zu.<br />

Um Open Client Anwendungen zu erstellen, benötigen Sie die<br />

Entwicklungsversion von Open Client. Um Open Client-Anwendungen zu<br />

verwenden, müssen die Open Client Laufzeitprogramme auf dem Computer<br />

installiert und konfiguriert sein, auf dem die Anwendung laufen soll.<br />

Der <strong>Adaptive</strong> Server <strong>Anywhere</strong> Server benötigt zur Unterstützung von Open<br />

Client-Anwendungen keine externe Kommunikations-Laufzeit.<br />

Jeder Open Client-Datentyp wird dem entsprechenden <strong>Adaptive</strong> Server<br />

<strong>Anywhere</strong>-Datentyp zugeordnet. Es werden alle Open Client-Datentypen<br />

unterstützt.<br />

Die folgende Tabelle zeigt die Zuordnung von Datentypen, die in <strong>Adaptive</strong><br />

Server <strong>Anywhere</strong> unterstützt werden, und die keine direkte Entsprechung in<br />

Open Client haben.<br />

<strong>Adaptive</strong> Server <strong>Anywhere</strong>-<br />

Datentyp<br />

unsigned short int<br />

unsigned int bigint<br />

unsigned bigint bigint<br />

Open Client-Datentyp<br />

date smalldatetime<br />

time smalldatetime<br />

serialization longbinary<br />

java longbinary<br />

string varchar<br />

timestamp struct datetime<br />

391


Datentyp-Zuordnungen<br />

Wertebereichseinschränkungen bei der Zuordnung von Datentypen<br />

Beispiel<br />

Zeitstempel<br />

392<br />

Einige Datentypen haben in <strong>Adaptive</strong> Server <strong>Anywhere</strong> andere<br />

Wertebereiche als in Open Client. In solchen Fällen kann es zu<br />

Überlauffehlern während der Abfrage oder des Einfügens von Daten<br />

kommen.<br />

Die folgende Tabelle zeigt Open Client-Anwendungsdatentypen, die zwar<br />

<strong>Adaptive</strong> Server <strong>Anywhere</strong>-Datentypen zugeordnet werden können, aber nur<br />

mit einigen Einschränkungen im Wertebereich möglicher Werte.<br />

In den meisten Fällen wird der Open Client-Datentyp einem <strong>Adaptive</strong> Server<br />

<strong>Anywhere</strong>-Datentyp zugeordnet, der einen größeren Bereich möglicher<br />

Werte hat. Deshalb ist es möglich, einen Wert an <strong>Adaptive</strong> Server <strong>Anywhere</strong><br />

zu übergeben, der zwar akzeptiert und in einer Datenbank gespeichert wird,<br />

der aber zu groß ist, um von einer Open Client-Anwendung abgerufen zu<br />

werden.<br />

Datentyp Untere Open<br />

Client-Grenze<br />

MONEY –922 377 203 685<br />

477.5808<br />

Obere Open<br />

Client-Grenze<br />

922 377 203 685<br />

477.5807<br />

Untere ASA-<br />

Grenze<br />

Obere ASA-<br />

Grenze<br />

–1e15 + 0.0001 1e15 – 0.0001<br />

SMALLMONEY –214 748.3648 214 748.3647 –214 748.3648 214 748.3647<br />

DATETIME 1. Januar 1753 31. Dezember<br />

9999<br />

1. Januar 0001 31. Dez. 9999<br />

SMALLDATETIME 1. Januar 1900 Juni 2079 1. März 1600 31. Dez. 7910<br />

Die Open Client-Datentypen MONEY und SMALLMONEY umfassen zum<br />

Beispiel nicht den gesamten numerischen Bereich der zu Grunde liegenden<br />

<strong>Adaptive</strong> Server <strong>Anywhere</strong>-Implementierung. Daher kann in einer Spalte in<br />

<strong>Adaptive</strong> Server <strong>Anywhere</strong> ein Wert enthalten sein, der die Grenzwerte des<br />

Open Client Datentyps MONEY überschreitet. Ruft der Client einen solchen<br />

unzulässigen Wert mit <strong>Adaptive</strong> Server <strong>Anywhere</strong> ab, wird eine<br />

Fehlermeldung erzeugt.<br />

Die Implementierung des Open Client-Datentyps TIMESTAMP in <strong>Adaptive</strong><br />

Server <strong>Anywhere</strong> unterscheidet sich von der Implementierung in <strong>Adaptive</strong><br />

Server Enterprise. In <strong>Adaptive</strong> Server <strong>Anywhere</strong> wird der Wert auf dem<br />

<strong>Adaptive</strong> Server <strong>Anywhere</strong>-Datentyp DATETIME zugeordnet. Der<br />

voreingestellte Wert ist NULL in <strong>Adaptive</strong> Server <strong>Anywhere</strong>, der Wert kann<br />

also uneindeutig sein. Im Gegensatz dazu stellt <strong>Adaptive</strong> Server Enterprise<br />

sicher, dass der Wert gleichförmig steigt und somit immer eindeutig ist.


Kapitel 10 Die Open Client-Schnittstelle<br />

Der <strong>Adaptive</strong> Server <strong>Anywhere</strong> Datentyp TIMESTAMP umfasst Jahr,<br />

Monat, Tag, Stunde, Minute, Sekunde und Sekundenbruchteile. Außerdem<br />

hat der Datentyp DATETIME einen größeren Wertebereich als die Open<br />

Client-Datentypen, die von <strong>Adaptive</strong> Server <strong>Anywhere</strong> zugeordnet werden.<br />

393


SQL in Open Client-Anwendungen verwenden<br />

SQL in Open Client-Anwendungen verwenden<br />

SQL Anweisungen ausführen<br />

394<br />

Dieser Abschnitt bietet eine kurze Einführung in die Verwendung von SQL<br />

in Open Client-Anwendungen, mit einem Schwerpunkt auf Themen, die <strong>für</strong><br />

<strong>Adaptive</strong> Server <strong>Anywhere</strong> spezifisch sind.<br />

$ Eine Einführung in die Konzepte finden Sie unter "SQL in<br />

Anwendungen verwenden" auf Seite 9. Eine vollständige Beschreibung<br />

finden Sie in Ihrer Open Client-Dokumentation.<br />

Sie senden SQL Anweisungen an eine Datenbank, indem Sie sie in die Client<br />

Library Funktionsaufrufe einschließen. Die folgenden beiden Aufrufe führen<br />

zum Beispiel eine DELETE-Anweisung aus:<br />

ret = ct_command(cmd, CS_LANG_CMD,<br />

"DELETE FROM employee<br />

WHERE emp_id=105"<br />

CS_NULLTERM,<br />

CS_UNUSED);<br />

ret = ct_send(cmd);<br />

Die Funktion ct_command wird <strong>für</strong> viele verschiedene Zwecke eingesetzt.<br />

Vorbereitete Anweisungen verwenden<br />

Die Funktion ct_dynamic wird <strong>für</strong> die Verwaltung von vorbereiteten<br />

Anweisungen benutzt. Diese Funktion übernimmt den type-Parameter, der<br />

die Aktion beschreibt, die Sie ausführen.<br />

v Eine vorbereitete Anweisung in Open Client benutzen:<br />

1 Bereiten Sie die Anweisung mit der Funktion ct_dynamic mit<br />

CS_PREPARE als type-Parameter vor.<br />

2 Setzen Sie die Anweisungsparameter mit ct_param.<br />

3 Führen Sie die Anweisung mit ct_dynamic mit CS_EXECUTE als<br />

type-Parameter aus.<br />

4 Geben Sie die mit der Anweisung verbundenen Ressourcen frei, indem<br />

Sie ct_dynamic mit einem CS_DEALLOC-type-Parameter<br />

verwenden.


Cursor verwenden<br />

Unterstützte<br />

Cursortypen<br />

Schritte bei der<br />

Verwendung von<br />

Cursorn<br />

Kapitel 10 Die Open Client-Schnittstelle<br />

$ Weitere Informationen über die Verwendung von vorbereiteten<br />

Anweisungen in Open Client finden Sie in der Open Client-Dokumentation.<br />

Die Funktion ct_cursor wird <strong>für</strong> die Verwaltung von Cursorn verwendet.<br />

Diese Funktion übernimmt den type-Parameter, der die Aktion beschreibt,<br />

die Sie ausführen.<br />

Einige der Cursortypen, die <strong>Adaptive</strong> Server <strong>Anywhere</strong> unterstützt, stehen in<br />

der Open Client Schnittstelle nicht zur Verfügung. Sie können über Open<br />

Client weder Scroll-Cursor, noch dynamische Scroll-Cursor, noch<br />

unempfindliche Cursor benutzen.<br />

Eindeutigkeit und Aktualisierbarkeit sind zwei Eigenschaften von Cursorn.<br />

Cursor können eindeutig sein (unabhängig davon, ob sie von der Anwendung<br />

benutzt wird oder nicht, hat jede Zeile einen Primärschlüssel oder eine<br />

Eindeutigkeitsinformation) oder nicht eindeutig sein. Cursor können<br />

schreibgeschützt oder aktualisierbar sein. Ist ein Cursor aktualisierbar und<br />

nicht eindeutig, kann die Performance leiden, da in diesem Fall keine Zeilen<br />

vorab abgerufen werden können. Dies ist unabhängig von der<br />

CS_CURSOR_ROWS-Belegung (siehe unten).<br />

Im Gegensatz zu anderen Schnittstellen wie Embedded SQL ordnet Open<br />

Client einem Cursor eine SQL Anweisung als Zeichenfolge zu. Embedded<br />

SQL bereitet zuerst eine Anweisung vor, dann wird der Cursor mit Hilfe des<br />

Statement-Handles deklariert.<br />

v Cursor in Open Client verwenden:<br />

1 Um einen Cursor in Open Client zu deklarieren, verwenden Sie<br />

ct_cursor mit CS_CURSOR_DECLARE als type-Parameter.<br />

2 Nachdem Sie einen Cursor deklariert haben, können Sie steuern, wie<br />

viele Zeilen vorab vom Client abgerufen werden, und zwar jedesmal<br />

wenn eine Zeile mit ct_cursor mit CS_CURSOR_ROWS als type-<br />

Parameter vom Server abgerufen wird.<br />

Vorab abgerufene Zeilen clientseitig zu speichern, reduziert die Anzahl<br />

der Serveraufrufe. Dies verbessert sowohl den Gesamtdurchsatz als auch<br />

die Fertigstellungszeit. Vorab abgerufene Zeilen werden nicht sofort an<br />

die Anwendung übergeben, sondern werden verwendungsbereit in einem<br />

clientseitigen Puffer zwischengespeichert.<br />

395


SQL in Open Client-Anwendungen verwenden<br />

Zeilen mit einen Cursor ändern<br />

396<br />

Die Einstellung der Datenbankoption PREFETCH steuert den Prefetch-<br />

Vorgang <strong>für</strong> andere Schnittstellen. Sie wird von Open Client<br />

Verbindungen nicht beachtet. Die Einstellung CS_CURSOR_ROWS<br />

wird bei nicht eindeutigen, aktualisierbaren Cursorn nicht beachtet.<br />

3 Um einen Cursor in Open Client zu öffnen, verwenden Sie ct_cursor<br />

mit CS_CURSOR_OPEN als type-Parameter.<br />

4 Um eine Zeile in der Anwendung abzurufen, verwenden Sie jeweils<br />

ct_fetch.<br />

5 Um einen Cursor zu schließen, verwenden Sie ct_cursor mit<br />

CS_CURSOR_CLOSE.<br />

6 In Open Client müssen Sie außerdem die Ressourcen freigeben, die an<br />

den Cursor gebunden waren. Verwenden Sie da<strong>für</strong> ct_cursor mit<br />

CS_CURSOR_DEALLOC. Sie können auch CS_CURSOR_CLOSE mit<br />

dem zusätzlichen Parameter CS_DEALLOC benutzen, um diese<br />

Vorgänge in einem Schritt auszuführen.<br />

Mit Open Client können Sie Zeilen in einem Cursor löschen oder<br />

aktualisieren, sofern der Cursor <strong>für</strong> eine einzelne Tabelle gilt. Der Benutzer<br />

muss die Berechtigung zur Aktualisierung der Tabelle haben und der Cursor<br />

muss <strong>für</strong> Aktualisierung markiert sein.<br />

v Zeilen durch einen Cursor verändern:<br />

♦ Statt einen Abruf durchzuführen, können Sie die aktuelle Zeile im<br />

Cursor mit ct_cursor und CS_CURSOR_DELETE löschen oder mit<br />

ct_cursor und CS_CURSOR_UPDATE aktualisieren.<br />

Sie können in Open Client-Anwendungen mit einem Cursor keine Zeilen<br />

einfügen.<br />

Abfrageergebnisse in Open Client beschreiben<br />

Open Client geht mit Ergebnismengen anders um als andere <strong>Adaptive</strong> Server<br />

<strong>Anywhere</strong>-Schnittstellen.<br />

In Embedded SQL und ODBC beschreiben Sie eine Abfrage oder eine<br />

gespeicherte Prozedur, um die richtige Anzahl und Typen der Variablen zu<br />

setzen, die die Ergebnisse aufnehmen sollen. Die Beschreibung wird in der<br />

Anweisung selbst gegeben.


Kapitel 10 Die Open Client-Schnittstelle<br />

In Open Client brauchen Sie eine Anweisung nicht zu beschreiben. Statt<br />

dessen kann jede Zeile, die vom Server zurückgegeben wird, eine<br />

Beschreibung Ihrer Inhalte enthalten. Falls Sie ct_command und<br />

ct_send verwenden, um Anweisungen auszuführen, können Sie die<br />

Funktion ct_results benutzen, um mit allen Aspekten der<br />

zurückgegebenen Zeilen umzugehen.<br />

Falls Sie nicht nach dieser Zeile-<strong>für</strong>-Zeile-Methode vorgehen wollen, können<br />

Sie ct_dynamic verwenden, um eine SQL Anweisung vorzubereiten und<br />

ct_describe, um die Ergebnismenge zu beschreiben. Dies entspricht<br />

mehr dem Beschreiben von SQL Anweisungen bei anderen Schnittstellen.<br />

397


Bekannte Open Client-Einschränkungen von <strong>Adaptive</strong> Server <strong>Anywhere</strong><br />

Bekannte Open Client-Einschränkungen von<br />

<strong>Adaptive</strong> Server <strong>Anywhere</strong><br />

398<br />

Mit der Open Client-Schnittstelle können Sie eine <strong>Adaptive</strong> Server<br />

<strong>Anywhere</strong>-Datenbank weitgehend wie eine <strong>Adaptive</strong> Server Enterprise-<br />

Datenbank verwenden. Es gibt allerdings einige Einschränkungen, unter<br />

anderem folgende:<br />

♦ Commit Service <strong>Adaptive</strong> Server <strong>Anywhere</strong> unterstützt <strong>Adaptive</strong><br />

Server Enterprise Commit Service nicht.<br />

♦ Funktionen Die Funktionen einer Client/Server-Verbindung bestimmen,<br />

welche Clientanforderungen und Serverantworten <strong>für</strong> diese Verbindung<br />

zulässig sind. Folgende Funktionen werden nicht unterstützt:<br />

♦ CS_REG_NOTIF<br />

♦ CS_CSR_ABS<br />

♦ CS_CSR_FIRST<br />

♦ CS_CSR_LAST<br />

♦ CS_CSR_PREV<br />

♦ CS_CSR_REL<br />

♦ CS_DATA_BOUNDARY<br />

♦ CS_DATA_SENSITIVITY<br />

♦ CS_PROTO_DYNPROC<br />

♦ CS_REQ_BCP<br />

♦ Sicherheitsoptionen, wie SSL und verschlüsselte Kennwörter, werden<br />

nicht unterstützt.<br />

♦ Open Client-Anwendungen können über TCP/IP oder, wenn verfügbar,<br />

über das Named Pipes-Protokoll des lokalen Systems eine Verbindung<br />

zu <strong>Adaptive</strong> Server <strong>Anywhere</strong> herstellen.<br />

$ Weitere Hinweise zu Funktionen finden Sie in der Dokumentation<br />

Open Server Server-Library C Reference Manual (in englischer<br />

Sprache).


KAPITEL 11<br />

Dreischichtige Datenverarbeitung und<br />

verteilte Transaktionen<br />

Über dieses<br />

Kapitel<br />

Inhalt<br />

In diesem Kapitel wird beschrieben, wie <strong>Adaptive</strong> Server <strong>Anywhere</strong> in einer<br />

dreischichtigen Umgebung mit einem Anwendungsserver verwendet wird.<br />

Der Schwerpunkt ist, wie <strong>Adaptive</strong> Server <strong>Anywhere</strong> in verteilte<br />

Transaktionen einbezogen werden kann.<br />

Thema Seite<br />

Einleitung 400<br />

Dreischichtige Datenverarbeitungsarchitektur 401<br />

Verteilte Transaktionen verwenden 405<br />

EAServer mit <strong>Adaptive</strong> Server <strong>Anywhere</strong> verwenden 407<br />

399


Einleitung<br />

Einleitung<br />

400<br />

Sie können <strong>Adaptive</strong> Server <strong>Anywhere</strong> als Datenbankserver oder als<br />

Ressourcen-Manager einsetzen, der an verteilten Transaktionen teilnimmt,<br />

die von einem Transaktionsserver koordiniert werden.<br />

Eine dreischichtige Umgebung, in der ein Anwendungsserver zwischen<br />

Clientanwendung und einer Reihe von Ressourcen-Managern sitzt, ist eine<br />

übliche Umgebung <strong>für</strong> verteilte Transaktionen. <strong>Sybase</strong> EAServer und einige<br />

andere Anwendungsserver sind ebenfalls Transaktionsserver.<br />

<strong>Sybase</strong> EAServer und Microsoft Transaction Server verwenden beide den<br />

Microsoft Distributed Transaction Coordinator (DTC) zum Koordinieren der<br />

Transaktionen. <strong>Adaptive</strong> Server <strong>Anywhere</strong> bietet Unterstützung <strong>für</strong> verteilte<br />

Transaktionen, die vom DTC-Service kontrolliert werden, sodass Sie<br />

<strong>Adaptive</strong> Server <strong>Anywhere</strong> mit einem dieser Anwendungsserver oder einem<br />

anderen DTC-basierten Produkt verwenden können.<br />

Wenn Sie <strong>Adaptive</strong> Server <strong>Anywhere</strong> in eine dreischichtige Umgebung<br />

integrieren, muss der Großteil der Arbeit vom Anwendungsserver erledigt<br />

werden. Dieses Kapitel ist eine Einführung in die Konzepte und die<br />

Architektur der dreischichtigen Datenverarbeitung sowie ein Überblick über<br />

die relevanten <strong>Adaptive</strong> Server <strong>Anywhere</strong>-Funktionen. Es beschreibt nicht,<br />

wie Ihr Anwendungsserver <strong>für</strong> die Arbeit mit <strong>Adaptive</strong> Server <strong>Anywhere</strong><br />

konfiguriert werden muss. Weitere Hinweise finden Sie in der<br />

Anwendungsserver-Dokumentation.


Kapitel 11 Dreischichtige Datenverarbeitung und verteilte Transaktionen<br />

Dreischichtige Datenverarbeitungsarchitektur<br />

Bei der dreistufigen Datenverarbeitung wird die Anwendungslogik auf einem<br />

Anwendungsserver wie einem <strong>Sybase</strong> EAServer gespeichert, der sich<br />

zwischen dem Ressourcen-Manager und der Clientanwendung befindet. In<br />

vielen Situationen kann ein einziger Anwendungsserver auf mehrere<br />

Ressourcen-Manager zugreifen. Bei Internetanwendungen ist die Clientseite<br />

browserbasiert, und der Anwendungsserver ist im Allgemeinen eine<br />

Webserver-Erweiterung.<br />

Anwendungs-<br />

Server<br />

<strong>Sybase</strong> EAServer speichert die Anwendungslogik in Form von<br />

Komponenten und stellt diese den Clientanwendungen zur Verfügung. Bei<br />

den Komponenten kann es sich um PowerBuilder-Komponenten, JavaBeans<br />

oder COM-Komponenten handeln.<br />

$ Weitere Hinweise finden Sie in der Dokumentation zum <strong>Sybase</strong><br />

EAServer.<br />

401


Dreischichtige Datenverarbeitungsarchitektur<br />

Verteilte Transaktionen in dreischichtiger Datenverarbeitung<br />

402<br />

Wenn Clientanwendungen oder Anwendungsserver mit einer einfachen<br />

Transaktionsverarbeitungs-Datenbank arbeiten, wie etwa <strong>Adaptive</strong> Server<br />

<strong>Anywhere</strong>, wird außerhalb der Datenbank selbst keine Transaktionslogik<br />

benötigt. Wenn jedoch mit mehreren Ressourcen-Managern gearbeitet wird,<br />

muss die Transaktionssteuerung die in die Transaktion einbezogenen<br />

Ressourcen abdecken. Anwendungsserver bieten ihren Clientanwendungen<br />

Transaktionslogik, sodass Gruppen von Vorgängen in kleinsten Einheiten<br />

ausgeführt werden.<br />

Viele Transaktionsserver, einschließlich <strong>Sybase</strong> EAServer, verwenden den<br />

Microsoft Distributed Transaction Coordinator (DTC), um den<br />

Clientanwendungen Transaktionsdienste anzubieten. DTC verwendet OLE-<br />

Transaktionen, die ihrerseits das Protokoll Zwei-Phasen-Commit <strong>für</strong> die<br />

Koordinierung von Transaktionen mit mehreren Ressourcen-Managern<br />

verwenden. Um die in diesem Kapitel beschriebenen Funktionen verwenden<br />

zu können, müssen Sie DTC installiert haben.<br />

<strong>Adaptive</strong> Server <strong>Anywhere</strong> in verteilten Transaktionen<br />

<strong>Adaptive</strong> Server <strong>Anywhere</strong> kann an von DTC koordinierten Transaktionen<br />

teilnehmen. Das bedeutet, dass Sie <strong>Adaptive</strong> Server <strong>Anywhere</strong>-Datenbanken<br />

in verteilten Transaktionen mit einem Transaktionsserver wie etwa <strong>Sybase</strong><br />

EAServer oder Microsoft Transaction Server verwenden können. Außerdem<br />

können Sie DTC direkt in Ihren Anwendungen zur Koordinierung von<br />

Transaktionen über mehrere Ressourcen-Manager einsetzen.<br />

Begriffe im Zusammenhang mit verteilten Transaktionen<br />

In diesem Kapitel wird eine gewisse Vertrautheit mit verteilten<br />

Transaktionen vorausgesetzt. Hinweise finden Sie in der Dokumentation zum<br />

Transaktionsserver. In diesem Abschnitt werden allgemein übliche Begriffe<br />

beschrieben.<br />

♦ Ressourcen-Manager sind Dienste, die in eine Transaktion<br />

einbezogene Daten verwalten.<br />

Der <strong>Adaptive</strong> Server <strong>Anywhere</strong>-Datenbankserver kann in einer<br />

verteilten Transaktion als Ressourcen-Manager agieren, wenn über OLE<br />

DB oder ODBC darauf zugegriffen wird. Der ODBC-Treiber und der<br />

OLE DB-Provider agieren auf dem Client-System als Ressourcen-<br />

Manager-Proxys.


Zwei-Phasen-<br />

Commit<br />

Kapitel 11 Dreischichtige Datenverarbeitung und verteilte Transaktionen<br />

♦ Anstatt direkt mit dem Ressourcen-Manager, können<br />

Anwendungskomponenten mit Ressourcen-Verteilern kommunizieren,<br />

die ihrerseits Verbindungen oder Verbindungs-Pools zu den Ressourcen-<br />

Managern verwalten.<br />

<strong>Adaptive</strong> Server <strong>Anywhere</strong> unterstützt zwei Ressourcen-Verteiler: den<br />

ODBC-Treibermanager und OLE DB.<br />

♦ Wenn eine Transaktionskomponente eine Datenbankverbindung<br />

anfordert (über einen Ressourcen-Manager), bezieht der<br />

Anwendungsserver alle Datenbankverbindungen ein, die an der<br />

Transaktion teilnehmen. DTC und der Ressourcen-Verteiler führen den<br />

Einbeziehungsvorgang aus.<br />

Verteilte Transaktionen werden mit Zwei-Phasen-Commit verwaltet. Wenn<br />

die Arbeit der Transaktion abgeschlossen ist, fragt der Transaktions-Manager<br />

(DTC) alle in die Transaktion einbezogenen Ressourcen-Manager, ob sie<br />

bereit sind, die Transaktion festzuschreiben. Diese Phase wird Vorbereiten<br />

zum Festschreiben genannt.<br />

Wenn alle Ressourcen-Manager antworten, dass sie zum Festschreiben bereit<br />

sind, sendet DTC eine Anforderung zum Festschreiben an jeden einzelnen<br />

Ressourcen-Manager und antwortet seinem Client, dass die Transaktion<br />

abgeschlossen ist. Wenn einer oder mehrere Ressourcen-Manager nicht<br />

antworten oder antworten, dass sie die Transaktion nicht festschreiben<br />

können, wird die gesamte Arbeit der Transaktion über alle Ressourcen-<br />

Manager zurückgesetzt.<br />

So verwenden Anwendungsserver DTC<br />

<strong>Sybase</strong> EAServer und Microsoft Transaction Server sind beides<br />

Komponentenserver. Die Anwendungslogik wird in Form von Komponenten<br />

gespeichert und den Clientanwendungen zur Verfügung gestellt.<br />

Jede Komponente hat ein Transaktionsattribut, das darauf hinweist, wie die<br />

Komponente an Transaktionen teilnimmt. Der Anwendungsentwickler, der<br />

die Komponente aufbaut, muss die Arbeit der Transaktion in die<br />

Komponente einprogrammieren: Die Ressourcen-Manager-Verbindungen,<br />

die Vorgänge mit den Daten, <strong>für</strong> die jeder einzelne Ressourcen-Manager<br />

verantwortlich ist. Der Anwendungsentwickler braucht jedoch nicht die<br />

Transaktionsverwaltungslogik in die Komponente einzubauen. Wenn das<br />

Transaktionsattribut so gesetzt ist, dass darauf hingewiesen wird, dass die<br />

Komponente eine Transaktionsverwaltung benötigt, verwendet EAServer<br />

DTC, um die Transaktion einzubeziehen und den Zwei-Phasen-Commit-<br />

Vorgang zu verwalten.<br />

403


Dreischichtige Datenverarbeitungsarchitektur<br />

Verteilte Transaktionsarchitektur<br />

404<br />

Das folgende Diagramm veranschaulicht die Architektur von verteilten<br />

Transaktionen. In diesem Fall ist der Ressourcen-Manager-Proxy entweder<br />

ODBC oder OLE DB.<br />

Client-<br />

System<br />

Ressourcen-<br />

Manager-<br />

Proxy<br />

DTC<br />

Serversystem<br />

1<br />

Anwendungs-<br />

Server<br />

DTC<br />

DTC<br />

Serversystem<br />

2<br />

Ressourcen-<br />

Manager-<br />

Proxy<br />

In diesem Fall wird ein einzelner Ressourcen-Verteiler verwendet. Der<br />

Anwendungsserver fordert DTC auf, die Transaktion vorzubereiten. DTC<br />

und der Ressourcen-Verteiler beziehen jede einzelne Verbindung in die<br />

Transaktion ein. Jeder einzelne Ressourcen-Manager muss sowohl mit DTC<br />

als auch mit der Datenbank in Kontakt stehen, damit die Arbeit ausgeführt<br />

werden kann, und um DTC ggf. auf seinen Transaktionsstatus hinzuweisen.<br />

Auf jedem System muss ein DTC-Dienst laufen, damit die verteilten<br />

Transaktionen ausgeführt werden können. DTC-Dienste können vom<br />

Symbol "Dienste" in der Windows-Systemsteuerung aus kontrolliert werden.<br />

Der DTC-Dienst heißt MSDTC.<br />

$ Weitere Hinweise finden Sie in der Dokumentation zu DTC bzw.<br />

EAServer.


Kapitel 11 Dreischichtige Datenverarbeitung und verteilte Transaktionen<br />

Verteilte Transaktionen verwenden<br />

DTC-Isolationsstufen<br />

Wenn <strong>Adaptive</strong> Server <strong>Anywhere</strong> in eine verteilte Transaktion einbezogen<br />

ist, gibt er die Kontrolle an den Transaktionsserver weiter und <strong>Adaptive</strong><br />

Server <strong>Anywhere</strong> gewährleistet, dass keine implizite Transaktionsverwaltung<br />

ausgeführt wird. Die folgenden Bedingungen werden automatisch von<br />

<strong>Adaptive</strong> Server <strong>Anywhere</strong> auferlegt, wenn er an verteilten Transaktionen<br />

teilnimmt:<br />

♦ Autocommit wird automatisch deaktiviert, wenn es verwendet wurde.<br />

♦ Datendefinitions-Anweisungen (als Nebenwirkung festgeschrieben)<br />

werden während der verteilten Transaktionen deaktiviert.<br />

♦ Ein explizites COMMIT oder ROLLBACK von der Anwendung direkt<br />

an <strong>Adaptive</strong> Server <strong>Anywhere</strong> anstatt über den Transaktionskoordinator<br />

führt zu einer Fehlermeldung. Die Transaktion wird jedoch nicht<br />

abgebrochen.<br />

♦ Eine Verbindung kann jeweils nur an einer verteilten Transaktion<br />

teilnehmen.<br />

♦ Zu dem Zeitpunkt, wenn die Verbindung in eine verteilte Transaktion<br />

einbezogen wird, darf es keine nicht festgeschriebenen Vorgänge geben.<br />

DTC weist eine Reihe von Isolationsstufen auf, die der Anwendungsserver<br />

angibt. Diese Isolationsstufen entsprechen folgendermaßen den<br />

Isolationsstufen von <strong>Adaptive</strong> Server <strong>Anywhere</strong>:<br />

DTC-Isolationsstufe <strong>Adaptive</strong> Server<br />

<strong>Anywhere</strong>-Isolationsstufe<br />

ISOLATIONLEVEL_UNSPECIFIED 0<br />

ISOLATIONLEVEL_CHAOS 0<br />

ISOLATIONLEVEL_READUNCOMMITTED 0<br />

ISOLATIONLEVEL_BROWSE 0<br />

ISOLATIONLEVEL_CURSORSTABILITY 1<br />

ISOLATIONLEVEL_READCOMMITTED 1<br />

ISOLATIONLEVEL_REPEATABLEREAD 2<br />

ISOLATIONLEVEL_SERIALIZABLE 3<br />

ISOLATIONLEVEL_ISOLATED 3<br />

405


Verteilte Transaktionen verwenden<br />

Wiederherstellung nach verteilten Transaktionen<br />

406<br />

Wenn der Datenbankserver einen Fehler aufweist, während nicht<br />

festgeschriebene Vorgänge auf Ausführung warten, müssen diese Vorgänge<br />

beim Neustart entweder zurückgesetzt oder festgeschrieben werden, damit<br />

die atomare Natur der Transaktion geschützt wird.<br />

Wenn während der Wiederherstellung nicht festgeschriebene Vorgänge einer<br />

verteilten Transaktion gefunden werden, versucht der Datenbankserver eine<br />

Verbindung mit DTC herzustellen und fordert, wieder in die auf Ausführung<br />

wartenden bzw. in die zweifelhaften Transaktionen einbezogen zu werden.<br />

Wenn die Wiedereinbeziehung abgeschlossen ist, weist DTC den<br />

Datenbankserver an, die ausstehenden Vorgänge zurückzusetzen oder<br />

festzuschreiben.<br />

Wenn der Wiedereinbeziehungsvorgang fehlschlägt, kann <strong>Adaptive</strong> Server<br />

<strong>Anywhere</strong> nicht wissen, ob die zweifelhaften Vorgänge festgeschrieben oder<br />

zurückgesetzt werden sollten, und die Wiederherstellung schlägt fehl. Wenn<br />

Sie wollen, dass die Datenbank wieder in solch einem Status hergestellt wird,<br />

unabhängig vom unsicheren Status der Daten, können Sie die<br />

Wiederherstellung mit den folgenden Datenbankserveroptionen erzwingen:<br />

♦ -tmf Wenn DTC nicht geladen werden kann, werden die ausstehenden<br />

Vorgänge zurückgesetzt und die Wiederherstellung wird fortgesetzt.<br />

$ Weitere Hinweise finden Sie unter "–tmf-Serveroption" auf<br />

Seite 169 der Dokumentation ASA Datenbankadministration.<br />

♦ -tmt Wenn die Wiedereinbeziehung vor der angegebenen Zeit nicht<br />

gelingt, werden die ausstehenden Vorgänge zurückgesetzt und die<br />

Wiederherstellung wird fortgesetzt.<br />

$ Weitere Hinweise finden Sie unter "–tmt-Serveroption" auf<br />

Seite 169 der Dokumentation ASA Datenbankadministration.


Kapitel 11 Dreischichtige Datenverarbeitung und verteilte Transaktionen<br />

EAServer mit <strong>Adaptive</strong> Server <strong>Anywhere</strong><br />

verwenden<br />

EA Server konfigurieren<br />

Dieser Abschnitt bietet einen Überblick über die in EAServer 3.0 oder später<br />

<strong>für</strong> die Arbeit mit <strong>Adaptive</strong> Server <strong>Anywhere</strong> zu ergreifenden Maßnahmen.<br />

Weitere Hinweise finden Sie in der Dokumentation zum <strong>Sybase</strong> EAServer.<br />

Alle in einem <strong>Sybase</strong> EAServer installierten Komponenten nutzen<br />

gemeinsam denselben Transaktionskoordinator.<br />

EAServer 3.0 und später bieten eine Auswahl von<br />

Transaktionskoordinatoren. Sie müssen DTC als Transaktionskoordinator<br />

verwenden, wenn Sie <strong>Adaptive</strong> Server <strong>Anywhere</strong> in die Transaktionen<br />

einbeziehen. In diesem Abschnitt wird beschrieben, wie EAServer 3.0 <strong>für</strong> die<br />

Benutzung von DTC als Transaktionskoordinator konfiguriert wird.<br />

Der Komponentenserver in EAServer trägt den Namen Jaguar.<br />

v So wird ein EAServer <strong>für</strong> die Verwendung des Microsoft DTC<br />

Transaktionsmodells konfiguriert:<br />

1 Vergewissern Sie sich, dass Ihr Jaguar-Server läuft.<br />

Unter Windows läuft der Jaguar-Server normalerweise als Dienst. Wenn<br />

der mit EAServer 3.0 installierte Jaguar-Server manuell gestartet werden<br />

soll, wählen Sie Start➤Programme➤<strong>Sybase</strong>➤EAServer➤EAServer.<br />

2 Starten Sie den Jaguar Manager.<br />

Wählen Sie vom Windows Desktop<br />

Start➤Programme➤<strong>Sybase</strong>➤EAServer➤Jaguar Manager.<br />

3 Stellen Sie vom Jaguar Manager aus eine Verbindung mit dem Jaguar-<br />

Server her.<br />

Wählen Sie im <strong>Sybase</strong> Central-Menü Extras➤Verbinden➤Jaguar<br />

Manager. Geben Sie im Verbindungsdialog jagadmin als<br />

Benutzernamen ein, lassen Sie das Kennwortfeld leer und geben Sie den<br />

Hostnamen localhost ein. Klicken Sie auf OK, damit eine Verbindung<br />

hergestellt wird.<br />

4 Legen Sie das Transaktionsmodell <strong>für</strong> den Jaguar-Server fest.<br />

407


EAServer mit <strong>Adaptive</strong> Server <strong>Anywhere</strong> verwenden<br />

408<br />

Öffnen Sie im linken Fensterausschnitt den Ordner "Server".<br />

Rechtsklicken Sie im rechten Fensterausschnitt auf den Server, den Sie<br />

konfigurieren wollen und wählen Sie "Servereigenschaften" aus dem<br />

Menü. Öffnen Sie das Register "Transaktionen" und wählen Sie<br />

Microsoft DTC als Transaktionsmodell. Klicken Sie auf OK, damit der<br />

Vorgang abgeschlossen wird.<br />

Komponenten-Transaktionsattribut festlegen<br />

Im EAServer können Sie eine Komponente implementieren, die Vorgänge<br />

mit mehr als einer Datenbank ausführt. Sie weisen dieser Komponente ein<br />

Transaktionsattribut zu, das festlegt, wie sie an Transaktionen teilnimmt.<br />

Das Transaktionsattribut kann die folgenden Werte annehmen:<br />

♦ Nicht unterstützt Die Methoden der Komponente werden nie als Teil<br />

einer Transaktion ausgeführt. Wird die Komponente von einer anderen<br />

Komponente aktiviert, die innerhalb einer Transaktion ausgeführt wird,<br />

dann wird die Arbeit der neuen Instanz außerhalb der vorhandenen<br />

Transaktion ausgeführt. Dies ist die Standardeinstellung.<br />

♦ Unterstützt Transaktion Die Komponente kann im Kontext einer<br />

Transaktion ausgeführt werden, eine Verbindung ist jedoch nicht<br />

erforderlich, um die Methoden der Komponente auszuführen. Wenn die<br />

Komponente direkt von einem Basis-Clienten instanziert wird, beginnt<br />

EAServer keine Transaktion. Wenn Komponente A von Komponente B<br />

instanziert und Komponente B innerhalb einer Transaktion ausgeführt<br />

wird, führt das System die Komponente A in derselben Transaktion aus.<br />

♦ Erfordert Transaktion Die Komponente wird immer in einer<br />

Transaktion ausgeführt. Wenn die Komponente direkt von einem Basis-<br />

Client instanziert wird, beginnt eine neue Transaktion. Wenn<br />

Komponente A von Komponente B aktiviert wird und B innerhalb einer<br />

Transaktion ausgeführt wird, führt das System A innerhalb derselben<br />

Transaktion aus, wenn B nicht in einer Transaktion ausgeführt wird,<br />

führt das System A in einer neuen Transaktion aus.<br />

♦ Erfordert neue Transaktion Wenn die Komponente instanziert wird,<br />

beginnt eine neue Transaktion. Wenn Komponente A von Komponente<br />

B aktiviert wird und B innerhalb einer Transaktion ausgeführt wird,<br />

beginnt A einen neue Transaktion, die unabhängig ist vom Ergebnis der<br />

Transaktion B, wenn B nicht in einer Transaktion ausgeführt wird, führt<br />

das System A in einer neuen Transaktion aus.


Kapitel 11 Dreischichtige Datenverarbeitung und verteilte Transaktionen<br />

In der Beispielanwendung <strong>Sybase</strong> Virtual University, die mit EAServer als<br />

SVU-Paket geliefert wird, führt die Methode enroll() der Komponente<br />

SVUEnrollment zwei separate Vorgänge aus (reserviert einen Platz in<br />

einem Kurs, fakturiert den Studenten <strong>für</strong> den Kurs). Diese beiden Vorgänge<br />

müssen als Einzel-Transaktionen behandelt werden.<br />

Microsoft Transaction Server bietet dieselbe Gruppe von Attributwerten.<br />

v So wird das Transaktionsattribut einer Komponente festgelegt:<br />

1 Ermitteln Sie die Position der Komponente im Jaguar Manager.<br />

Wenn Sie die Komponente SVUEnrollment in der Jaguar-<br />

Beispielanwendung suchen wollen, stellen Sie eine Verbindung mit dem<br />

Jaguar-Server her, öffnen Sie den Ordner "Pakete" und öffnen Sie das<br />

SVU-Paket. Die Komponenten im Paket werden im rechten<br />

Fensterausschnitt aufgeführt.<br />

2 Legen Sie das Transaktionsattribut <strong>für</strong> die gewünschte Komponente fest.<br />

Rechtsklicken Sie auf die Komponente und klicken Sie auf<br />

"Komponenten-Eigenschaften" im Einblendmenü. Öffnen Sie das<br />

Register "Transaktion" und wählen Sie den Wert <strong>für</strong> das<br />

Transaktionsattribut aus der Liste. Klicken Sie auf OK, damit der<br />

Vorgang abgeschlossen wird.<br />

Die Komponente SVUEnrollment ist bereits als "Erfordert Transaktion"<br />

markiert.<br />

Wenn das Komponenten-Transaktionsattribut festgelegt ist, können Sie<br />

<strong>Adaptive</strong> Server <strong>Anywhere</strong>-Vorgänge von der Komponente aus ausführen<br />

und sicher sein, dass die Transaktion auf der Ebene ausgeführt wird, die Sie<br />

angegeben haben.<br />

409


EAServer mit <strong>Adaptive</strong> Server <strong>Anywhere</strong> verwenden<br />

410


KAPITEL 12<br />

Deployment: Datenbanken und<br />

Anwendungen im System bereitstellen<br />

Über dieses<br />

Kapitel<br />

Inhalt<br />

In diesem Kapitel wird beschrieben, wie Komponenten von <strong>Adaptive</strong> Server<br />

<strong>Anywhere</strong> <strong>für</strong> die allgemeine Nutzung im System bereitgestellt werden<br />

können. Beschrieben werden die erforderlichen Dateien <strong>für</strong> die<br />

Bereitstellung sowie Fragen im Zusammenhang mit der Adressierung und<br />

der Einstellung von Verbindungsparametern.<br />

Prüfen Sie Ihre Lizenzvereinbarung<br />

Die Weitergabe von Dateien wird durch die Lizenzvereinbarung geregelt.<br />

In diesem Kapitel enthaltene Ausführungen können die Bestimmungen<br />

Ihrer Lizenzvereinbarung weder aufheben noch ändern. Bevor Sie daher<br />

Anwendungen im System bereitstellen, prüfen Sie bitte Ihre<br />

Lizenzvereinbarung.<br />

Thema Seite<br />

Systemeinführung - Überblick 412<br />

Installationsverzeichnisse und Dateinamen 415<br />

InstallShield-Objekte und Vorlagen zum Bereitstellen verwenden 420<br />

Dialogfreie Installation <strong>für</strong> die Systemeinführung 422<br />

Clientanwendungen im System bereitstellen 426<br />

Tools zur Verwaltung bereitstellen 437<br />

Datenbankserver im System bereitstellen 438<br />

Eingebettete Datenbankanwendungen im System bereitstellen 441<br />

411


Systemeinführung - Überblick<br />

Systemeinführung - Überblick<br />

412<br />

Wenn Sie eine Datenbankanwendung fertig gestellt haben, müssen Sie die<br />

Anwendung <strong>für</strong> Ihre Endbenutzer bereitstellen. Je nach der Art, wie Ihre<br />

Anwendung <strong>Adaptive</strong> Server <strong>Anywhere</strong> verwendet (als eingebettete<br />

Datenbank, im Client-/Servermodus usw.), müssen Sie Komponenten von<br />

<strong>Adaptive</strong> Server <strong>Anywhere</strong> zusammen mit Ihrer Anwendung bereitstellen. Es<br />

kann außerdem erforderlich sein, Konfigurationsdaten bereitzustellen, wie<br />

etwa Datenquellennamen, damit die Anwendung mit <strong>Adaptive</strong> Server<br />

<strong>Anywhere</strong> kommunizieren kann.<br />

Prüfen Sie Ihre Lizenzvereinbarung<br />

Die Weitergabe von Dateien wird durch die Lizenzvereinbarung mit<br />

<strong>Sybase</strong> geregelt. In diesem Kapitel enthaltene Ausführungen können die<br />

Bestimmungen Ihrer Lizenzvereinbarung weder aufheben noch ändern.<br />

Bevor Sie daher Anwendungen im System bereitstellen, prüfen Sie bitte<br />

Ihre Lizenzvereinbarung.<br />

Folgende Bereiche der Systemeinführung werden in diesem Kapitel<br />

besprochen:<br />

♦ Ermittlung der erforderlichen Dateien je nach Anwendungsplattform<br />

und Plattformarchitektur<br />

♦ Konfiguration der Clientanwendungen<br />

Modelle <strong>für</strong> die Systemeinführung<br />

Eine großer Teil des Kapitels befasst sich mit einzelnen Dateien und wo sie<br />

platziert werden müssen. Es wird jedoch empfohlen, <strong>Adaptive</strong> Server<br />

<strong>Anywhere</strong>-Komponenten unter Verwendung der Installshield-Objekte oder<br />

dialogfrei zu installieren. Hinweise finden Sie unter "InstallShield-Objekte<br />

und Vorlagen zum Bereitstellen verwenden" auf Seite 420 und "Dialogfreie<br />

Installation <strong>für</strong> die Systemeinführung" auf Seite 422.<br />

Welche Dateien Sie bei der Systemeinführung bereitstellen müssen, hängt<br />

vom gewählten Modell ab. Nachstehend werden einige denkbare Modelle<br />

beschrieben:<br />

♦ Clientbereitstellung Sie können nur die Clientkomponenten von<br />

<strong>Adaptive</strong> Server <strong>Anywhere</strong> <strong>für</strong> die Endbenutzer bereitstellen, sodass<br />

diese sich mit einem zentral untergebrachten Netzwerk-Datenbankserver<br />

verbinden können.


Kapitel 12 Deployment: Datenbanken und Anwendungen im System bereitstellen<br />

♦ Netzwerkserver bereitstellen Sie können Netzwerkserver in<br />

Zweigstellen einrichten und dann Clients <strong>für</strong> alle Benutzer in diesen<br />

Büros bereitstellen.<br />

♦ Eingebettete Datenbanken bereitstellen Sie können eine Datenbank<br />

bereitstellen, die mit einem Personal Datenbankserver läuft. In diesem<br />

Fall müssen der Client und der Personal Server auf dem Rechner des<br />

Endbenutzers installiert werden.<br />

♦ Bereitstellung über SQL Remote Die Bereitstellung einer SQL<br />

Remote-Anwendung ist eine Erweiterung des Modells der Bereitstellung<br />

einer eingebetteten Datenbank.<br />

♦ DBTools-Bereitstellung Sie können Interactive SQL, <strong>Sybase</strong> Central<br />

und andere Tools zur Verwaltung bereitstellen.<br />

Möglichkeiten zur Weitergabe von Dateien<br />

Es gibt zwei Möglichkeiten, <strong>Adaptive</strong> Server <strong>Anywhere</strong> <strong>für</strong> den allgemeinen<br />

Gebrauch verfügbar zu machen:<br />

♦ Sie benutzen das Installationsprogramm von <strong>Adaptive</strong> Server<br />

<strong>Anywhere</strong> Sie können das Setup-Programm den Endbenutzern zur<br />

Verfügung stellen. Wenn der Endbenutzer die richtigen<br />

Installationsoptionen wählt, verfügt er garantiert über alle erforderlichen<br />

Dateien.<br />

Dies ist die einfachste Lösung <strong>für</strong> viele Fälle der Systemeinführung. In<br />

diesem Fall müssen Sie den Endbenutzern nur noch eine Methode zur<br />

Verbindungsaufnahme mit dem Datenbankserver übergeben (z.B. eine<br />

ODBC-Datenquelle).<br />

$ Weitere Hinweise finden Sie unter "Dialogfreie Installation <strong>für</strong> die<br />

Systemeinführung" auf Seite 422.<br />

♦ Entwicklung Ihrer eigenen Installation Es kann Gründe da<strong>für</strong> geben,<br />

dass Sie ein eigenes Installationsprogramm entwickeln wollen, das<br />

Dateien von <strong>Adaptive</strong> Server <strong>Anywhere</strong> enthält. Diese Option ist viel<br />

komplizierter, und daher richtet sich der größte Teil dieses Kapitels an<br />

jene, die eigene Installationen entwickeln müssen.<br />

Wenn <strong>Adaptive</strong> Server <strong>Anywhere</strong> bereits passend <strong>für</strong> den Servertyp und<br />

das Betriebssystem der Clientanwendung installiert wurde, stehen die<br />

erforderlichen Dateien in dem entsprechend benannten Unterverzeichnis<br />

bereit, das im Installationsverzeichnis von <strong>Adaptive</strong> Server <strong>Anywhere</strong><br />

angelegt wurde.<br />

413


Systemeinführung - Überblick<br />

414<br />

Wenn beispielsweise das Standard-Installationsverzeichnis gewählt<br />

wurde, enthält das Unterverzeichnis win32 im Installationsverzeichnis<br />

die Dateien, die benötigt werden, um den Server unter Windows-<br />

Betriebssystemen zu betreiben.<br />

Ebenso können Anwender von InstallShield Professional 5.5 und höher<br />

die InstallShield-Vorlagenprojekte <strong>für</strong> SQL <strong>Anywhere</strong> Studio<br />

verwenden, um ihre eigenen Anwendungen bereitzustellen. Mit dieser<br />

Funktion erstellen Sie das Installationsprogramm <strong>für</strong> Ihre Anwendung,<br />

indem Sie das gesamte Vorlagenprojekt oder nur die <strong>für</strong> Ihre Installation<br />

relevanten Teile verwenden.<br />

Gleichgültig welche Option Sie wählen: Sie müssen sich dabei immer an die<br />

Bestimmungen Ihrer Lizenz halten.


Kapitel 12 Deployment: Datenbanken und Anwendungen im System bereitstellen<br />

Installationsverzeichnisse und Dateinamen<br />

Damit eine im System bereitgestellte Anwendung richtig funktioniert,<br />

müssen die Clientbibliotheken ermitteln können, wo die erforderlichen<br />

Dateien untergebracht sind. Die bereitgestellten Dateien müssen in derselben<br />

Struktur gespeichert werden wie in der Installation von <strong>Adaptive</strong> Server<br />

<strong>Anywhere</strong>.<br />

In der Praxis bedeutet das, dass auf einem PC die meisten Dateien in ein<br />

einziges Verzeichnis gehören. Unter Windows z.B. werden Dateien <strong>für</strong> den<br />

Datenbankserver und <strong>für</strong> den Client in nur einem Verzeichnis installiert,<br />

nämlich dem Unterverzeichnis win32 des Installationsverzeichnisses von<br />

<strong>Adaptive</strong> Server <strong>Anywhere</strong>.<br />

$ Eine vollständige Beschreibung der Standorte, an denen die Software<br />

nach Dateien sucht, finden Sie unter "Ermittlung des Dateienstandorts durch<br />

<strong>Adaptive</strong> Server <strong>Anywhere</strong>" auf Seite 228 der Dokumentation ASA<br />

Datenbankadministration.<br />

Anwendungen unter UNIX bereitstellen<br />

Die Bereitstellung von Anwendungen unter UNIX unterscheidet sich von der<br />

auf PC üblichen in folgender Weise:<br />

♦ Verzeichnisstruktur Bei UNIX-Installationen lautet die<br />

Verzeichnisstruktur wie folgt:<br />

Verzeichnis Inhalt<br />

/opt/sybase/SYBSsa8/bin Programmdateien<br />

/opt/sybase/SYBSsa8/lib Gemeinsame Objekte und Bibliotheken<br />

/opt/sybase/SYBSsa8/res Textdateien<br />

Auf AIX lautet das standardmäßige Stammverzeichnis<br />

/usr/lpp/sybase/SYBSsa8 an Stelle von /opt/sybase/SYBSsa8.<br />

♦ Dateierweiterungen In den Tabellen dieses Kapitels werden die<br />

gemeinsamen Objekte mit der Erweiterung .so angeführt. Unter HP-UX<br />

lautet diese Erweiterung .sl.<br />

Im Betriebssystem AIX haben gemeinsam genutzte Dateien, mit denen<br />

sich Anwendungen verknüpfen müssen, die Erweiterung .a.<br />

415


Installationsverzeichnisse und Dateinamen<br />

Namenskonventionen <strong>für</strong> Dateien<br />

416<br />

♦ Symbolische Verknüpfungen Jedes gemeinsam genutzte Objekt ist als<br />

symbolische Verknüpfung zu einer Datei gleichen Namens mit der<br />

zusätzlichen Erweiterung .1 (eins) installiert. Beispiel: Die Datei<br />

libdblib8.so ist eine symbolische Verknüpfung zur Datei libdblib8.so.1 in<br />

demselben Verzeichnis.<br />

Wenn Korrekturprogramme <strong>für</strong> die Installation von <strong>Adaptive</strong> Server<br />

<strong>Anywhere</strong> erforderlich sind, werden sie mit der Erweiterung .2 geliefert<br />

und die symbolische Verknüpfung muss umgeleitet werden.<br />

♦ Anwendungen mit und ohne Threads Die meisten gemeinsam<br />

genutzten Objekte werden in zwei Formen geliefert, von denen eine mit<br />

den zusätzlichen Zeichen _r vor der Dateierweiterung versehen ist.<br />

Beispiel: Zusätzlich zu libdblib8.so gibt es eine Datei mit der<br />

Bezeichnung libdblib8_r.so. In diesem Fall müssen Anwendungen mit<br />

Thread mit dem gemeinsam genutzten Objekt _r verknüpft werden,<br />

Anwendungen ohne Thread hingegen mit dem gemeinsam genutzten<br />

Objekt ohne den Zusatz _r.<br />

♦ Zeichensatzkonvertierung Wenn Sie die Zeichensatzkonvertierung<br />

des Datenbankservers (Serveroption -ct) benutzen möchten, müssen die<br />

folgenden Dateien hinzugefügt werden:<br />

♦ libunic.so<br />

♦ Verzeichnisstruktur charsets/<br />

♦ asa.cvf<br />

$ Eine Beschreibung der Standorte, an denen die Software nach Dateien<br />

sucht, finden Sie unter "Ermittlung des Dateienstandorts durch <strong>Adaptive</strong><br />

Server <strong>Anywhere</strong>" auf Seite 228 der Dokumentation ASA<br />

Datenbankadministration.<br />

<strong>Adaptive</strong> Server <strong>Anywhere</strong> benutzt einheitliche Konventionen, damit Sie die<br />

Systemkomponenten leichter erkennen und zu Gruppen zusammenfassen<br />

können.<br />

Diese Konventionen sind wie folgt aufgebaut:<br />

♦ Versionsnummer Die Versionsnummer von <strong>Adaptive</strong> Server <strong>Anywhere</strong><br />

wird im Dateinamen der Haupt-Serverkomponenten (.exe and .dll<br />

Dateien) dargestellt.<br />

Beispiel: Die Datei dbeng8.exe ist eine Programmdatei <strong>für</strong> Version 7.


Andere Dateitypen<br />

erkennen<br />

Kapitel 12 Deployment: Datenbanken und Anwendungen im System bereitstellen<br />

♦ Sprache Die in einer Sprachen-Ressourcebibliothek verwendete<br />

Sprache wird durch einen Sprachcode im Dateinamen angezeigt. Die<br />

zwei Zeichen vor der Versionsnummer weisen auf die in der Bibliothek<br />

verwendete Sprache hin. Zum Beispiel ist dblgen8.dll die Sprachen-<br />

Ressourcebibliothek <strong>für</strong> Englisch. Diese Codes aus zwei Buchstaben<br />

sind im ISO-Standard 639 festgelegt.<br />

$ Weitere Hinweise zur Sprachenkennzeichnung finden Sie unter<br />

"Näheres zur Sprache der Sprachumgebung" auf Seite 288 der<br />

Dokumentation ASA Datenbankadministration.<br />

Sie können das International Resources Deployment Kit, das DLLs <strong>für</strong> die<br />

Bereitstellung von Sprachressourcen enthält, gratis von der <strong>Sybase</strong>-Website<br />

herunterladen.<br />

v So laden Sie das International Resources Deployment Kit von der<br />

<strong>Sybase</strong>-Website herunter:<br />

1 Öffnen Sie im Webbrowser den folgenden URL:<br />

http://www.sybase.com/products/mobilewireless/anywhe<br />

re/<br />

2 Klicken Sie unterhalb der Überschrift "SQL <strong>Anywhere</strong> Studio" links auf<br />

der Seite auf "Downloads".<br />

3 Klicken Sie unterhalb der Überschrift "Emergency Bug Fix/Updates"<br />

auf "Emergency Bug Fixes and Updates for SQL <strong>Anywhere</strong> Studio".<br />

4 Melden Sie sich bei Ihrem <strong>Sybase</strong>-Netzkonto an.<br />

Klicken Sie auf "Create a New Account", um ein <strong>Sybase</strong>-Netzkonto zu<br />

erstellen, falls Sie noch keines haben.<br />

5 Aus der Liste der verfügbaren Downloads wählen Sie das International<br />

Resources Deployment Kit aus, das der verwendeten Plattform und<br />

Version von <strong>Adaptive</strong> Server <strong>Anywhere</strong> entspricht.<br />

$ Eine Liste der in <strong>Adaptive</strong> Server <strong>Anywhere</strong> verfügbaren Sprachen<br />

finden Sie unter "Mitgelieferte Kollatierungen" auf Seite 295 der<br />

Dokumentation ASA Datenbankadministration.<br />

Die folgende Tabelle zeigt die Plattform und die Funktion der <strong>Adaptive</strong><br />

Server <strong>Anywhere</strong>-Dateien entsprechend ihrer Dateierweiterung. In <strong>Adaptive</strong><br />

Server <strong>Anywhere</strong> wurden, wo immer möglich, die Standard-<br />

Dateierweiterungen verwendet.<br />

417


Installationsverzeichnisse und Dateinamen<br />

Datenbankdateinamen<br />

418<br />

Dateierweiterung<br />

Plattform Dateityp<br />

.nlm Novell Netware Mit NetWare ladbares<br />

Modul<br />

.cnt, .ftg, .fts,<br />

.gid, .hlp, .chm,<br />

.chw<br />

.lib Ändert sich je nach<br />

Entwicklungstool<br />

.cfg, .cpr, .dat,<br />

.loc, .spr, .srt,<br />

.xlt<br />

Windows NT Datei des Hilfesystems<br />

Statische Laufzeitbibliotheken<br />

<strong>für</strong> die<br />

Erstellung von Embedded<br />

SQL Programmdateien<br />

Windows Komponenten von <strong>Sybase</strong><br />

<strong>Adaptive</strong> Server Enterprise<br />

.cmd .bat Windows Befehlsdateien<br />

.res NetWare, UNIX Sprachen-Ressourcedatei<br />

<strong>für</strong> Umgebungen außer<br />

Windows<br />

.dll Windows Dynamische<br />

Verknüpfungsbibliothek<br />

(Dynamic Link Library)<br />

.so .sl .a UNIX Gemeinsam genutztes<br />

Objekt (Sun Solaris und<br />

IBM AIX) oder gemeinsam<br />

genutzte Bibliothek (HP-<br />

UX). Dies ist das<br />

Gegenstück zu einer DLL<br />

auf PC-Plattformen.<br />

Die <strong>Adaptive</strong> Server <strong>Anywhere</strong> Datenbanken bestehen aus zwei Elementen:<br />

♦ Datenbankdatei Sie wird verwendet, um Informationen in organisierter<br />

Form zu speichern. Dieser Datei ist die Dateierweiterung .db<br />

zugeordnet.<br />

♦ Transaktionslogdatei Sie wird benutzt, um alle Änderungen<br />

aufzuzeichnen, die an den Daten in der Datenbankdatei vorgenommen<br />

werden. Für diese Datei wird die Dateierweiterung .log verwendet. Sie<br />

wird vom <strong>Adaptive</strong> Server <strong>Anywhere</strong> erzeugt, wenn keine solche Datei<br />

vorhanden ist und die Verwendung einer Logdatei definiert wurde. Ein<br />

gespiegeltes Transaktionslog hat die standardmäßige Erweiterung .mlg.<br />

♦ Write-Datei Wenn Ihre Anwendung eine Write-Datei verwendet, verfügt<br />

sie in der Regel über die Dateierweiterung .wrt.


Kapitel 12 Deployment: Datenbanken und Anwendungen im System bereitstellen<br />

♦ Komprimierte Datenbankdatei Wenn Sie eine schreibgeschützte<br />

komprimierte Datenbankdatei verwenden, hat sie normalerweise die<br />

Dateierweiterung .cdb.<br />

Diese Dateien werden vom Datenbank-Managementsystem von <strong>Adaptive</strong><br />

Server <strong>Anywhere</strong> aktualisiert, gepflegt und verwaltet.<br />

419


InstallShield-Objekte und Vorlagen zum Bereitstellen verwenden<br />

InstallShield-Objekte und Vorlagen zum<br />

Bereitstellen verwenden<br />

420<br />

Wenn Sie InstallShield 6 oder höher verwenden, können Sie SQL <strong>Anywhere</strong><br />

Studio InstallShield-Objekte in Ihr Installationsprogramm einbeziehen. Die<br />

Objekte zur Bereitstellung von Clients, Personal Datenbankservern,<br />

Netzwerkservern und Verwaltungstools finden Sie im Verzeichnis<br />

deployment\Objects in Ihrem SQL <strong>Anywhere</strong>-Verzeichnis.<br />

Anwender von InstallShield Professional 5.5 und höher können InstallShield-<br />

Vorlagenprojekte <strong>für</strong> SQL <strong>Anywhere</strong> Studio verwenden, um sich die Arbeit<br />

<strong>für</strong> die Bereitstellung ihrer eigenen Anwendungen zu erleichtern. Vorlagen<br />

zum Bereitstellen eines Netzwerkservers, eines Personal Servers, Client-<br />

Schnittstellen und Verwaltungstools finden Sie im Verzeichnis<br />

SQL <strong>Anywhere</strong> 8\deployment\Templates.<br />

Wenn Sie InstallShield 6 oder höher haben, sind die Objekte den Vorlagen<br />

vorzuziehen, weil sie einfacher zusammen mit anderen Komponenten in die<br />

Installation zu integrieren sind.<br />

v So fügen Sie ein Vorlagenprojekt zu Ihrer InstallShield-IDE hinzu:<br />

1 Starten Sie die InstallShield-IDE.<br />

2 Wählen Sie Datei➤Öffnen.<br />

3 Wechseln Sie zu Ihrer SQL <strong>Anywhere</strong> 7-Installation und ins<br />

Bereitstellungsverzeichnis.<br />

Wechseln Sie zum Beispiel zu folgendem Verzeichnis:<br />

C:\Programme\<strong>Sybase</strong>\SQL <strong>Anywhere</strong> 8\deployment.<br />

4 Öffnen Sie die Vorlage, die dem Typ des Objekts entspricht, das Sie<br />

bereitstellen wollen.<br />

Sie können zwischen NetworkServer, PersonalServer, Client und<br />

JavaTools wählen.<br />

5 Wählen Sie die Datei mit der Erweiterung .ipr.<br />

Das Projekt wird in der InstallShield-IDE geöffnet. Im Projektbereich<br />

wird ein Symbol <strong>für</strong> die Vorlage angezeigt.<br />

Die Vorlagen werden während der Installation geändert, sodass die<br />

Suchpfade der einzelnen Dateien, die in allen .fgl-Dateien aufgelistet<br />

sind, auf die aktuelle Installation von ASA zeigen. Laden Sie einfach die<br />

Vorlage in die InstallShield-IDE, generieren Sie die Medien und die<br />

Vorlage wird unmittelbar ausgeführt.


Hinweise:<br />

Kapitel 12 Deployment: Datenbanken und Anwendungen im System bereitstellen<br />

Wenn Sie die Medien generieren, sehen Sie Warnmeldungen über leere<br />

Dateigruppen. Diese Warnungen werden durch leere Dateigruppen<br />

verursacht, die als Platzhalter <strong>für</strong> die Dateien Ihrer Anwendung in die<br />

Vorlage eingefügt wurden. Um diese Warnungen zu entfernen, können<br />

Sie entweder die Dateien Ihrer Anwendung in die Dateigruppen<br />

einfügen oder die Dateigruppen löschen oder umbenennen.<br />

421


Dialogfreie Installation <strong>für</strong> die Systemeinführung<br />

Dialogfreie Installation <strong>für</strong> die Systemeinführung<br />

422<br />

Dialogfreie Installationen laufen ohne Eingriff von Seiten des Benutzers und<br />

ohne dass der Benutzer erfährt, dass eine Installation ausgeführt wird. Bei<br />

Windows-Betriebssystemen können Sie das InstallShield-Setup-Programm<br />

von <strong>Adaptive</strong> Server <strong>Anywhere</strong> so aufrufen, dass die <strong>Adaptive</strong> Server<br />

<strong>Anywhere</strong> Installation dialogfrei verläuft. Dialogfreie Installationen werden<br />

ebenfalls vom Microsoft Systems Management Server verwendet (siehe<br />

"SMS-Installation" auf Seite 424).<br />

Sie können eine dialogfreie Installation <strong>für</strong> alle Systemeinführungsmodelle<br />

verwenden, die in "Modelle <strong>für</strong> die Systemeinführung" auf Seite 412<br />

beschrieben wurden. Sie können zur Bereitstellung von MobiLink-<br />

Synchronisationsservern auch eine dialogfreie Installation verwenden.<br />

So wird eine dialogfreie Installation eingerichtet<br />

Die bei einer dialogfreien Installation verwendeten Installationsoptionen<br />

stammen aus einer Antwortdatei. Die Antwortdatei wird erstellt, indem das<br />

Setup-Programm von <strong>Adaptive</strong> Server <strong>Anywhere</strong> mit der Option –r<br />

ausgeführt wird. Eine dialogfreie Installation wird durch Ausführen von<br />

Setup mit der Option –s ausgeführt.<br />

Verwenden Sie keine Durchsuchungsfunktionen<br />

Wenn Sie eine dialogfreie Installation erstellen, dürfen Sie die<br />

Schaltflächen "Durchsuchen" nicht verwenden. Die Ergebnisse von<br />

Durchsuchungsfunktionen können fehlerhaft sein.<br />

v So wird eine dialogfreie Installation eingerichtet:<br />

1 (Fakultativ) Entfernen Sie vorhandene Installationen von <strong>Adaptive</strong><br />

Server <strong>Anywhere</strong>.<br />

2 Öffnen Sie eine Systembefehlszeile und wechseln Sie in das Verzeichnis<br />

mit den Installations-Dateien (die setup.exe, setup.ins usw. enthalten).<br />

3 Installieren Sie die Software im Modus "Record" (Aufzeichnen).<br />

Geben Sie folgenden Befehl ein:<br />

setup –r


Kapitel 12 Deployment: Datenbanken und Anwendungen im System bereitstellen<br />

Dialogfreie Installation ausführen<br />

Mit diesem Befehl wird das Setup-Programm von <strong>Adaptive</strong> Server<br />

<strong>Anywhere</strong> ausgeführt und aus Ihrer Auswahl bei den Optionen eine<br />

Antwortdatei erstellt. Die Antwortdatei erhält den Namen setup.iss und<br />

befindet sich im Windows-Verzeichnis. Diese Datei enthält die<br />

Antworten, die Sie während der Installation in den Dialogfeldern<br />

gegeben haben.<br />

Wenn das Programm im Modus "Record" (Aufzeichnen) ausgeführt<br />

wird, schlägt es nicht vor, das Betriebssystem neu zu starten, auch wenn<br />

ein Neustart erforderlich ist.<br />

4 Installieren Sie <strong>Adaptive</strong> Server <strong>Anywhere</strong> mit den Optionen und<br />

Einstellungen, die beim Bereitstellen von <strong>Adaptive</strong> Server <strong>Anywhere</strong><br />

auf dem Computer des Endbenutzers <strong>für</strong> die Benutzung mit Ihrer<br />

Anwendung eingerichtet werden sollen. Während der dialogfreien<br />

Installation können Pfade aufgehoben werden.<br />

Ihr eigenes Installationsprogramm muss die dialogfreie Installation von<br />

<strong>Adaptive</strong> Server <strong>Anywhere</strong> mit der Option –s aufrufen. In diesem Abschnitt<br />

wird beschrieben, wie eine dialogfreie Installation verwendet wird.<br />

v So wird eine dialogfreie Installation verwendet:<br />

1 Fügen Sie den entsprechenden Befehl in Ihre Installationsprozedur ein,<br />

damit die dialogfreie Installation von <strong>Adaptive</strong> Server <strong>Anywhere</strong><br />

ausgeführt wird.<br />

Wenn die Antwortdatei sich im Installations-Verzeichnis befindet,<br />

können Sie die dialogfreie Installation ausführen, indem Sie im<br />

Verzeichnis mit dem Installationsabbilds folgenden Befehl ausführen:<br />

setup –s<br />

Wenn sich die Antwortdatei anderswo befindet, müssen Sie den Pfad<br />

mit der Option –f1 angeben. In der folgenden Befehlszeile darf es keine<br />

Leerstelle zwischen f1 und dem Anführungszeichen geben.<br />

setup –s –f1"c:\winnt\setup.iss"<br />

Wenn die Installation von einem anderen InstallShield-Skript ausgeführt<br />

werden soll, können Sie folgenden Befehl benutzen:<br />

DoInstall(<br />

"Pfad_des_ASA_Installationsabbilds\SETUP.INS",<br />

"-s", WAIT );<br />

423


Dialogfreie Installation <strong>für</strong> die Systemeinführung<br />

SMS-Installation<br />

424<br />

Zum Aufheben der Pfade <strong>für</strong> das <strong>Adaptive</strong> Server <strong>Anywhere</strong>-<br />

Verzeichnis und <strong>für</strong> das gemeinsam genutzte Verzeichnis können Sie<br />

Optionen benutzen:<br />

setup TARGET_DIR=Verzeichnisname<br />

SHARED_DIR=Gem_Verzeichnis –s<br />

Die Argumente TARGET_DIR und SHARED_DIR müssen allen<br />

anderen Optionen vorangestellt werden.<br />

2 Prüfen Sie, ob der Zielcomputer neu gestartet werden muss.<br />

Setup erstellt eine Datei namens silent.log im Zielverzeichnis. Diese<br />

Datei enthält nur einen Abschnitt mit der Bezeichnung ResponseResult<br />

und der folgenden Zeile:<br />

Reboot=Wert<br />

Diese Zeile gibt an, ob der Zielcomputer neu gestartet werden muss,<br />

damit die Installation abgeschlossen wird. Mögliche Werte sind 0 bzw.<br />

1, mit folgender Bedeutung:<br />

♦ Reboot=0 Neustart nicht erforderlich.<br />

♦ Reboot=1 Die Option BATCH_INSTALL war während der<br />

Installation aktiviert und der Zielcomputer muss neu gestartet<br />

werden. Die Installationsprozedur, die die dialogfreie Installation<br />

aufgerufen hat, ist verantwortlich <strong>für</strong> die Prüfung des Eintrags<br />

"Reboot" und ggf. <strong>für</strong> den Neustart des Zielcomputers.<br />

3 Prüfen Sie, ob das Setup ordnungsgemäß abgeschlossen wurde.<br />

Setup erstellt eine Datei namens setup.log im Verzeichnis mit der<br />

Antwortdatei. Die Logdatei enthält einen Bericht über die dialogfreie<br />

Installation. Der letzte Abschnitt dieser Datei heißt ResponseResult und<br />

enthält die folgende Zeile:<br />

ResultCode=Wert<br />

Diese Zeile gibt an, ob die Installation erforderlich war. Ein Nicht-Null-<br />

ResultCode gibt an, dass während der Installation ein Fehler aufgetreten<br />

ist. Eine Beschreibung der Fehlercodes finden Sie in der Dokumentation<br />

zu InstallShield.<br />

Microsoft System Management Server (SMS) erfordert eine dialogfreie<br />

Installation, die den Zielcomputer nicht neu startet. Die dialogfreie<br />

Installation von <strong>Adaptive</strong> Server <strong>Anywhere</strong> startet den Computer nicht neu.


Kapitel 12 Deployment: Datenbanken und Anwendungen im System bereitstellen<br />

Ihr SMS-Distributionspaket müsste eine Antwortdatei, das<br />

Installationsabbild und die Paket-Definitionsdatei asa8.pdf enthalten (auf<br />

der <strong>Adaptive</strong> Server <strong>Anywhere</strong>-CD-ROM im Ordner \Extras). Die Setup-<br />

Befehlszeile in der PDF-Datei enthält die folgenden Optionen:<br />

♦ Die Option –s <strong>für</strong> eine dialogfreie Installation<br />

♦ Die Option –SMS zur Angabe, dass die Installation von SMS ausgelöst<br />

wird<br />

♦ Die Option –m, damit eine MIF-Datei erzeugt wird. Die MIF-Datei wird<br />

von SMS verwendet um festzustellen, ob die Installation erfolgreich<br />

war.<br />

425


Clientanwendungen im System bereitstellen<br />

Clientanwendungen im System bereitstellen<br />

426<br />

Um eine Clientanwendung im System bereitzustellen, die mit einem<br />

Netzwerk-Datenbankserver betrieben wird, müssen Sie jedem Endbenutzer<br />

folgende Elemente zur Verfügung stellen:<br />

♦ Clientanwendung Die Anwendungssoftware selbst ist von der<br />

Datenbanksoftware unabhängig und wird hier nicht beschrieben.<br />

♦ Datenbank-Interface-Dateien Die Clientanwendung benötigt die<br />

Dateien <strong>für</strong> die Datenbank-Schnittstelle, die sie benutzt (ODBC, JDBC,<br />

Embedded SQL oder Open Client).<br />

♦ Verbindungsinformationen Jede Clientanwendung benötigt<br />

Verbindungsinformationen <strong>für</strong> die Datenbank.<br />

Die erforderlichen Interface-Dateien und Verbindungsinformationen richten<br />

sich nach der Schnittstelle, die von Ihrer Anwendung benutzt wird. Jede<br />

Schnittstelle wird in den folgenden Abschnitten im Einzelnen beschrieben.<br />

Die einfachste Methode zur Bereitstellung von Clients ist es, die<br />

mitgelieferten InstallShield-Objekte zu verwenden. Weitere Hinweise finden<br />

Sie unter "InstallShield-Objekte und Vorlagen zum Bereitstellen verwenden"<br />

auf Seite 420.<br />

OLE DB- und ADO-Clients bereitstellen<br />

Die einfachste Art, OLE DB-Clientbibliotheken bereitzustellen, ist es, die<br />

InstallShield-Objekte und Vorlagen zu verwenden. Hinweise dazu finden Sie<br />

unter "InstallShield-Objekte und Vorlagen zum Bereitstellen verwenden" auf<br />

Seite 420. Dieser Abschnitt beschreibt die Dateien, die Sie den Endbenutzern<br />

bereitstellen müssen, wenn Sie vorhaben, Ihre eigene Installation zu<br />

erstellen.<br />

Jeder OLE DB-Clientrechner muss folgende Elemente aufweisen:<br />

♦ Eine funktionierende OLE DB-Installation OLE DB-Dateien und<br />

Anweisungen <strong>für</strong> ihre Verteilung können bei der Microsoft Corporation<br />

bezogen werden. Sie werden hier nicht im Einzelnen beschrieben.<br />

♦ Der <strong>Adaptive</strong> Server <strong>Anywhere</strong> OLE DB-Provider Die folgende<br />

Tabelle enthält die Dateien, die <strong>für</strong> den <strong>Adaptive</strong> Server <strong>Anywhere</strong> OLE<br />

DB-Provider erforderlich sind. Diese Dateien sollten in nur einem<br />

Verzeichnis abgelegt werden. Die <strong>Adaptive</strong> Server <strong>Anywhere</strong>-<br />

Installation platziert sie alle in das Betriebssystem-Unterverzeichnis des<br />

SQL <strong>Anywhere</strong>-Installationsverzeichnisses (zum Beispiel: win32).


Kapitel 12 Deployment: Datenbanken und Anwendungen im System bereitstellen<br />

Beschreibung Windows Windows CE<br />

OLE DB-Treiberdatei dboledb8.dll dboledb8.dll<br />

OLE DB-Treiberdatei dboledba8.dll dboledba8.dll<br />

Sprachen-<br />

Ressourcebibliothek<br />

ODBC-Clients im System bereitstellen<br />

dblgen8.dll dblgen8.dll<br />

Dialogfeld "Verbinden" dbcon8.dll Nicht zutreffend<br />

OLE DB-Provider benötigen viele Registrierungseinträge. Sie können<br />

diese erstellen, indem Sie die DLLs mit dem Dienstprogramm regsvr32<br />

unter Windows oder dem Dienstprogramm regsvrce unter Windows CE<br />

selbst registrieren.<br />

$ Weitere Hinweise finden Sie unter "Datenbanken <strong>für</strong> Windows CE<br />

erstellen" auf Seite 300 der Dokumentation ASA<br />

Datenbankadministration und "ODBC-Anwendungen unter Windows<br />

CE verknüpfen" auf Seite 281.<br />

Die einfachste Art, ODBC-Clients bereitzustellen, ist es, die InstallShield-<br />

Objekte und Vorlagen zu verwenden. Hinweise dazu finden Sie unter<br />

"InstallShield-Objekte und Vorlagen zum Bereitstellen verwenden" auf<br />

Seite 420.<br />

Jeder ODBC-Clientrechner muss folgende Elemente aufweisen:<br />

♦ Eine funktionierende ODBC-Installation ODBC-Dateien und<br />

Anweisungen <strong>für</strong> ihre Verteilung können bei der Microsoft Corporation<br />

bezogen werden. Sie werden hier nicht im Einzelnen beschrieben.<br />

Microsoft liefert den ODBC-Treibermanager <strong>für</strong> Windows-<br />

Betriebssysteme. SQL <strong>Anywhere</strong> Studio enthält einen ODBC Driver<br />

Manager <strong>für</strong> UNIX. Es gibt keinen ODBC-Treibermanager <strong>für</strong> Windows<br />

CE.<br />

ODBC-Anwendungen können ohne den Treibermanager laufen. Auf<br />

Plattformen, <strong>für</strong> die ein ODBC-Treibermanager verfügbar ist, ist das<br />

nicht zu empfehlen.<br />

427


Clientanwendungen im System bereitstellen<br />

428<br />

Falls erforderlich ODBC aktualisieren<br />

Das SQL <strong>Anywhere</strong> Setup-Programm aktualisiert alte Installationen<br />

der Microsoft Data Access-Komponenten, einschließlich ODBC.<br />

Wenn Sie Ihre eigene Anwendung bereitstellen, müssen Sie<br />

sichergehen, dass die ODBC-Installation den Anforderungen Ihrer<br />

Anwendung entspricht.<br />

♦ Der ODBC-Treiber <strong>für</strong> <strong>Adaptive</strong> Server <strong>Anywhere</strong> Dies ist die Datei<br />

dbodbc8.dll mit ihren Zusatzdateien.<br />

$ Weitere Hinweise finden Sie unter "Erforderliche Dateien <strong>für</strong> den<br />

ODBC-Treiber" auf Seite 428.<br />

♦ Verbindungsinformation Die Clientanwendung muss Zugriff auf die<br />

Daten haben, aus denen sie die Informationen <strong>für</strong> die Verbindung mit<br />

dem Server bezieht. Diese Informationen sind normalerweise in der<br />

ODBC-Datenquelle enthalten.<br />

Erforderliche Dateien <strong>für</strong> den ODBC-Treiber<br />

Hinweise<br />

Die folgende Tabelle zeigt die Dateien, die <strong>für</strong> einen funktionierenden<br />

ODBC-Treiber von <strong>Adaptive</strong> Server <strong>Anywhere</strong> erforderlich sind. Diese<br />

Dateien sollten in nur einem Verzeichnis abgelegt werden. Die <strong>Adaptive</strong><br />

Server <strong>Anywhere</strong>-Installation platziert sie alle in das Betriebssystem-<br />

Unterverzeichnis des SQL <strong>Anywhere</strong>-Installationsverzeichnisses (zum<br />

Beispiel: win32).<br />

Beschreibung Windows Windows CE UNIX<br />

ODBC-Treiber dbodbc8.dll dbodbc8.dll libdbodbc8.so<br />

libdbtasks8.so<br />

Sprachen-<br />

Ressourcebibliothek<br />

dblgen8.dll dblgen8.dll dblgen8.res<br />

Dialogfeld<br />

"Verbinden"<br />

dbcon8.dll Nicht zutreffend Nicht zutreffend<br />

♦ Der Endbenutzer muss über eine funktionierende ODBC-Installation mit<br />

einem Treibermanager verfügen. Anweisungen <strong>für</strong> die Bereitstellung<br />

von ODBC finden Sie im Microsoft ODBC SDK.<br />

♦ Das Dialogfeld "Verbinden" ist erforderlich, wenn die Endbenutzer<br />

eigene Datenquellen erstellen sollen, bei der Verbindungsaufnahme<br />

Benutzer-IDs und Kennwörter eingeben müssen oder wenn Das<br />

Dialogfeld aus anderen Gründen angezeigt werden muss.


Kapitel 12 Deployment: Datenbanken und Anwendungen im System bereitstellen<br />

ODBC-Treiber konfigurieren<br />

Windows<br />

♦ Der ODBC-Übersetzer ist nur erforderlich, wenn Ihre Anwendung eine<br />

Umwandlung von OEM in ANSI durchführt.<br />

$ Weitere Hinweise finden Sie unter "Datenbanken <strong>für</strong> Windows CE<br />

erstellen" auf Seite 300 der Dokumentation ASA<br />

Datenbankadministration, und "ODBC-Anwendungen unter Windows<br />

CE verknüpfen" auf Seite 281.<br />

♦ Bei Anwendungen mit mehrfachen Threads unter UNIX benutzen Sie<br />

libdbodbc8_r.so und libdbtasks8_r.so.<br />

Das Setup-Programm muss nicht nur die Dateien des ODBC-Treibers auf die<br />

Festplatte kopieren, sondern auch eine Reihe von Einträgen in der<br />

Registrierung vornehmen, damit der ODBC-Treiber richtig installiert wird.<br />

Das Setup-Programm von <strong>Adaptive</strong> Server <strong>Anywhere</strong> führt Änderungen in<br />

der Systemregistrierung durch, um den ODBC-Treiber anzumelden und zu<br />

konfigurieren. Wenn Sie ein Setup-Programm <strong>für</strong> die Endbenutzer erstellen,<br />

müssen Sie dieselben Einstellungen vornehmen.<br />

Sie können das Dienstprogramm regedit verwenden, um die<br />

Registrierungseinträge anzuzeigen.<br />

Der ODBC-Treiber von <strong>Adaptive</strong> Server <strong>Anywhere</strong> wird im System durch<br />

eine Gruppe von Registrierungseinträgen im folgenden<br />

Registrierungsschlüssel angemeldet:<br />

HKEY_LOCAL_MACHINE\<br />

SOFTWARE\<br />

ODBC\<br />

ODBCINST.INI\<br />

<strong>Adaptive</strong> Server <strong>Anywhere</strong> 8.0<br />

Folgende Werte werden gesetzt:<br />

Name des Wertes Typ des Wertes Daten des Wertes<br />

Driver Zeichenfolge Pfad\dbodbc8.dll<br />

Setup Zeichenfolge Pfad\dbodbc8.dll<br />

Es gibt auch einen Registrierungseintrag im folgenden Schlüssel:<br />

HKEY_LOCAL_MACHINE\<br />

SOFTWARE\<br />

ODBC\<br />

ODBCINST.INI\<br />

ODBC Drivers<br />

429


Clientanwendungen im System bereitstellen<br />

ODBC-Treiber von<br />

Drittanbietern<br />

430<br />

Der Wert ist wie folgt:<br />

Name des Wertes Typ des<br />

Wertes<br />

Verbindungsinformationen bereitstellen<br />

Arten von<br />

Datenquellen<br />

<strong>Adaptive</strong> Server <strong>Anywhere</strong> 8.0 Zeichenfolge Installed<br />

Daten des Wertes<br />

Wenn Sie einen ODBC-Treiber eines Drittanbieters auf einem anderen<br />

Betriebssystem als Windows verwenden, finden Sie in der Dokumentation<br />

dieses ODBC-Treibers Hinweise dazu, wie der ODBC-Treiber zu<br />

konfigurieren ist.<br />

Die Verbindungsinformationen <strong>für</strong> den ODBC-Client werden im<br />

Allgemeinen in Form einer ODBC-Datenquelle im System bereitgestellt. Die<br />

Bereitstellung einer ODBC-Datenquelle erfolgt auf folgende Weise:<br />

♦ Programmgesteuert Fügen Sie die Beschreibung <strong>für</strong> eine Datenquelle<br />

in die Registrierung des Endbenutzers oder in die ODBC-<br />

Initialisierungsdateien ein.<br />

♦ Manuell Übergeben Sie den Endbenutzern Anweisungen, damit sie auf<br />

ihrem Rechner eine geeignete Datenquelle einrichten können.<br />

Sie können eine Datenquelle manuell mit dem ODBC Administrator<br />

erstellen, indem Sie das Register Benutzer-DSN oder System-DSN<br />

verwenden. Der ODBC-Treiber von <strong>Adaptive</strong> Server <strong>Anywhere</strong> zeigt<br />

den Konfigurationsdialog <strong>für</strong> die Eingabe der Einstellungen an.<br />

Einstellungen <strong>für</strong> die Datenquelle enthalten den Standort der<br />

Datenbankdatei, den Namen des Datenbankservers sowie Startparameter<br />

und andere Optionen.<br />

In diesem Abschnitt finden Sie die Informationen, die Sie <strong>für</strong> beide Ansätze<br />

benötigen.<br />

Es gibt drei Arten von Datenquellen: Benutzerdatenquellen,<br />

Systemdatenquellen und Dateidatenquellen.<br />

Die Definitionen der Benutzerdatenquellen werden in der Registrierung im<br />

Abschnitt <strong>für</strong> den aktuell im System angemeldeten Benutzer gespeichert.<br />

Systemdatenquellen hingegen stehen allen Benutzern und Diensten von<br />

Windows zur Verfügung, wobei die Dienste auch aktiv sind, wenn kein<br />

Benutzer angemeldet ist. Bei einer richtig konfigurierten Systemdatenquelle<br />

"MeineAnwendung" kann jeder Benutzer diese ODBC-Verbindung<br />

verwenden, indem er "DSN=MeineAnwendung" in der ODBC-<br />

Verbindungszeichenfolge eingibt.


Registrierungseinträge<br />

<strong>für</strong> die<br />

Datenquelle<br />

Kapitel 12 Deployment: Datenbanken und Anwendungen im System bereitstellen<br />

Dateidatenquellen werden nicht in der Registrierung gespeichert, sondern in<br />

einem speziellen Verzeichnis. Eine Verbindungszeichenfolge muss einen<br />

FileDSN-Verbindungsparameter liefern, um eine Dateidatenquelle benutzen<br />

zu können.<br />

Jede Benutzerdatenquelle ist im System über Registrierungseinträge<br />

angemeldet.<br />

Sie müssen eine Gruppe von Registrierungswerten in einem bestimmten<br />

Registrierungsschlüssel angeben. Für Benutzerdatenquellen ist der Schlüssel<br />

wie folgt:<br />

HKEY_CURRENT_USER\<br />

SOFTWARE\<br />

ODBC\<br />

ODBC.INI\<br />

Benutzerdatenquellenname<br />

Für Systemdatenquellen ist der Schlüssel wie folgt:<br />

HKEY_LOCAL_MACHINE\<br />

SOFTWARE\<br />

ODBC\<br />

ODBC.INI\<br />

Systemdatenquellenname<br />

Der Schlüssel enthält eine Gruppe von Registrierungswerten, die jeweils<br />

einem Verbindungsparameter entsprechen. Zum Beispiel enthält der<br />

Schlüssel "ASA 8.0 Sample", der der Datenquelle der Beispieldatenbank von<br />

ASA 8.0 entspricht, folgende Einstellungen:<br />

Name des Wertes Typ des<br />

Wertes<br />

Autostop Zeichenfolge yes<br />

Daten des Wertes<br />

DatabaseFile Zeichenfolge Pfad\asademo.db<br />

Description Zeichenfolge <strong>Adaptive</strong> Server <strong>Anywhere</strong> Beispieldatenbank<br />

Driver String Pfad\win32\dbodbc8.dll<br />

PWD String sql<br />

Start String Pfad\win32\dbeng8.exe -c 8m<br />

UID String dba<br />

In diesen Einträgen steht Pfad <strong>für</strong> das Installationsverzeichnis von <strong>Adaptive</strong><br />

Server <strong>Anywhere</strong>.<br />

Außerdem müssen Sie die Datenquelle der Liste von Datenquellen in der<br />

Registrierung hinzufügen. Für Benutzerdatenquellen benutzen Sie folgenden<br />

Schlüssel:<br />

431


Clientanwendungen im System bereitstellen<br />

Erforderliche und<br />

fakultative<br />

Verbindungsparameter<br />

432<br />

HKEY_CURRENT_USER\<br />

SOFTWARE\<br />

ODBC\<br />

ODBC.INI\<br />

ODBC Data Sources<br />

Für Systemdatenquellen benutzen Sie folgenden Schlüssel:<br />

HKEY_LOCAL_MACHINE\<br />

SOFTWARE\<br />

ODBC\<br />

ODBC.INI\<br />

ODBC Data Sources<br />

Der Wert verknüpft jede Datenquelle mit einem ODBC-Treiber. Der Name<br />

des Wertes ist der Datenquellenname, und die Daten des Wertes sind der<br />

Name des ODBC-Treibers. Beispiel: Die Benutzerdatenquelle, die von<br />

<strong>Adaptive</strong> Server <strong>Anywhere</strong> installiert wird, heißt "ASA 8.0 Sample" und hat<br />

folgenden Wert:<br />

Name des Wertes Typ des<br />

Wertes<br />

Daten des Wertes<br />

ASA 8.0 Sample Zeichenfolge <strong>Adaptive</strong> Server <strong>Anywhere</strong> 8.0<br />

Vorsicht: ODBC-Einstellungen können leicht angezeigt werden<br />

Die Konfiguration von Benutzerdatenquellen kann vertrauliche<br />

Datenbankeinstellungen enthalten, wie z.B. Benutzerkennungen und<br />

Kennwörter. Diese Einstellungen werden in der Registrierung in reiner<br />

Textform gespeichert und können mit Registrierungseditoren von<br />

Windows regedit.exe oder regedt32.exe angezeigt werden. Diese Editoren<br />

sind in jedem Windows-System automatisch installiert. Sie können<br />

Kennwörter verschlüsseln oder von Benutzern verlangen, sie bei der<br />

Aufnahme der Verbindung einzugeben.<br />

Sie können den Datenquellennamen in einem ODBC-Konfigurationseintrag<br />

in folgender Weise definieren:<br />

DSN=Benutzerdatenquellenname<br />

Wenn ein DSN-Parameter in der Verbindungszeichenfolge geliefert wird,<br />

werden erst die aktuellen Definitionen von Benutzerdatenquellen in der<br />

Registrierung durchsucht, dann die Systemdatenquellen. Dateidatenquellen<br />

werden nur durchsucht, wenn "FileDSN" in der Zeichenfolge <strong>für</strong> die ODBC-<br />

Verbindung geliefert wird.<br />

Die folgende Tabelle zeigt die Auswirkungen auf Benutzer und Entwickler,<br />

wenn eine Datenquelle vorhanden ist und in die Verbindungszeichenfolge<br />

der Anwendung als Parameter DSN oder FileDSN einbezogen ist.


Kapitel 12 Deployment: Datenbanken und Anwendungen im System bereitstellen<br />

Datenquelle Eingabe in der<br />

Verbindungszeichenfolge<br />

Enthält den ODBC-<br />

Treibernamen und –<br />

Speicherort, den Namen<br />

der Datenbankdatei, des<br />

Datenbankservers, die<br />

Startparameter sowie<br />

Benutzer-ID und<br />

Kennwort<br />

Enthält nur Namen und<br />

Speicherort des ODBC-<br />

Treibers<br />

Keine zusätzlichen<br />

Informationen<br />

Name der Datenbankdatei<br />

oder des Datenbankservers;<br />

fakultativ die<br />

Benutzerkennung und das<br />

Kennwort<br />

Nicht vorhanden Der Name des zu<br />

verwendenden ODBC-<br />

Treibers in folgendem<br />

Format:<br />

Driver={ODBC<br />

Treibername}<br />

Ebenfalls: Name der<br />

Datenbank, Datenbankdatei<br />

oder Datenbankserver;<br />

fakultativ andere<br />

Verbindungsparameter<br />

wie Benutzerkennung und<br />

Kennwort<br />

Eingabe durch den<br />

Benutzer<br />

Keine zusätzlichen<br />

Informationen<br />

Benutzer-ID und<br />

Kennwort, wenn nicht<br />

im DSN oder in der<br />

Zeichenfolge <strong>für</strong> die<br />

ODBC-Verbindung<br />

angegeben.<br />

Benutzerkennung und<br />

Kennwort, wenn nicht<br />

in der Zeichenfolge <strong>für</strong><br />

die ODBC-Verbindung<br />

geliefert<br />

$ Weitere Hinweise zu ODBC-Verbindungen und Konfigurationen finden<br />

Sie unter<br />

♦ "Verbindung mit einer Datenbank herstellen" auf Seite 41 der<br />

Dokumentation ASA Datenbankadministration.<br />

♦ Open Database Connectivity (ODBC) SDK von Microsoft<br />

Bereitstellen von Embedded SQL-Clients<br />

Die einfachste Art, Embedded SQL-Clients bereitzustellen, ist es, die<br />

InstallShield-Objekte und Vorlagen zu verwenden. Hinweise dazu finden Sie<br />

unter "InstallShield-Objekte und Vorlagen zum Bereitstellen verwenden" auf<br />

Seite 420.<br />

433


Clientanwendungen im System bereitstellen<br />

434<br />

Die Bereitstellung von Embedded SQL-Clients im System umfasst folgende<br />

Aufgaben:<br />

♦ Installierte Dateien Jeder Clientrechner muss die erforderlichen Dateien<br />

<strong>für</strong> eine <strong>Adaptive</strong> Server <strong>Anywhere</strong> Embedded SQL-Clientanwendung<br />

enthalten.<br />

♦ Verbindungsinformation Die Clientanwendung muss Zugriff auf die<br />

Daten haben, aus denen sie die Informationen <strong>für</strong> die Verbindung mit<br />

dem Server bezieht. Diese Informationen können in die ODBC-<br />

Datenquelle aufgenommen werden.<br />

Dateien <strong>für</strong> Embedded SQL-Clients installieren<br />

Hinweise<br />

Die folgende Tabelle zeigt, welche Dateien <strong>für</strong> Embedded SQL Clients<br />

benötigt werden.<br />

Beschreibung Windows UNIX<br />

Schnittstellenbibliothek dblib8.dll libdblib8.so,<br />

libdbtasks8.so<br />

Sprachen-<br />

Ressourcebibliothek<br />

IPX<br />

Netzwerkkommunikation<br />

dblgen8.dll dblgen8.res<br />

dbipx8.dll Nicht zutreffend<br />

Dialogfeld "Verbinden" dbcon8.dll Nicht zutreffend<br />

♦ Die Netzwerkport-DLL ist nicht erforderlich, wenn der Client nur mit<br />

dem Personal Datenbankserver arbeitet.<br />

♦ Wenn die Clientanwendung eine ODBC-Datenquelle benutzt, um die<br />

Verbindungsparameter zu speichern, muss der Endbenutzer über eine<br />

funktionierende ODBC-Installation verfügen. Anweisungen <strong>für</strong> die<br />

Bereitstellung von ODBC finden Sie im Microsoft ODBC SDK.<br />

$ Weitere Hinweise zur Bereitstellung von ODBC-Informationen im<br />

System finden Sie unter "ODBC-Clients im System bereitstellen" auf<br />

Seite 427.<br />

♦ Das Dialogfeld "Verbindung" ist erforderlich, wenn die Endbenutzer<br />

eigene Datenquellen erstellen, bei der Verbindungsaufnahme Benutzer-<br />

IDs und Kennwörter eingeben müssen oder wenn das Dialogfeld aus<br />

anderen Gründen angezeigt werden muss.<br />

♦ Bei Anwendungen mit mehrfachen Threads unter UNIX benutzen Sie<br />

libdbodbc8_r.so und libdbtasks8_r.so.


Kapitel 12 Deployment: Datenbanken und Anwendungen im System bereitstellen<br />

Verbindungsinformationen<br />

Verbindungsinformation Die Bereitstellung von Embedded SQL-<br />

Verbindungsinformationen erfolgt auf folgende Weise:<br />

♦ Manuell Übergeben Sie den Endbenutzern Anweisungen, damit sie auf<br />

ihrem Rechner eine geeignete Datenquelle einrichten können.<br />

♦ Datei Übergeben Sie den Endbenutzern eine Datei, die<br />

Verbindungsinformationen in einem Format enthält, das Ihre<br />

Anwendung lesen kann.<br />

♦ ODBC-Datenquelle Sie können die ODBC-Datenquelle verwenden, um<br />

darin die Verbindungsinformationen zu speichern. In diesem Fall<br />

benötigen Sie eine Teilgruppe der ODBC-Dateien von Microsoft.<br />

Hinweise finden Sie unter "ODBC-Clients im System bereitstellen" auf<br />

Seite 427.<br />

♦ Hartcodiert Sie können Verbindungsinformationen in der Anwendung<br />

programmieren. Dies ist eine unflexible Methode, die beispielsweise bei<br />

einem Upgrade von Datenbanken umfassende Neuprogrammierungen<br />

erforderlich macht.<br />

JDBC-Clients im System bereitstellen<br />

Zusätzlich zur Java-Laufzeitumgebung (Java Runtime Environment) muss<br />

jeder JDBC-Client auch über den JDBC-Treiber jConnect von <strong>Sybase</strong> oder<br />

die JDBC-ODBC-Brücke verfügen.<br />

$ Hinweise zur Bereitstellung von jConnect finden Sie unter<br />

http://manuals.sybase.com/onlinebooks/group-jc/jcg0420e/ auf der <strong>Sybase</strong>-<br />

Website.<br />

Zur Bereitstellung der JDBC-ODBC-Brücke müssen die folgenden Dateien<br />

mitgeliefert werden:<br />

♦ jodbc.jar Diese muss sich im Classpath der Anwendung befinden.<br />

♦ dbjodbc8.dll Diese muss sich im Systempfad befinden. In UNIX- oder<br />

Linux-Umgebungen ist die Datei eine gemeinsam genutzte Bibliothek<br />

(dbjodbc8.so).<br />

♦ Die ODBC-Treiberdateien. Weitere Hinweise finden Sie unter<br />

"Erforderliche Dateien <strong>für</strong> den ODBC-Treiber" auf Seite 428.<br />

Ihre Java-Anwendung benötigt einen URL, um sich mit der Datenbank zu<br />

verbinden. Dieser URL gibt den Treiber, den zu verwendenden Rechner und<br />

den Port an, auf dem der Datenbankserver auf Daten wartet.<br />

435


Clientanwendungen im System bereitstellen<br />

436<br />

$ Weitere Hinweise zu URL finden Sie unter "Einem Server einen URL<br />

liefern" auf Seite 152.<br />

Open Client-Anwendungen im System bereitstellen<br />

Um Open Client-Anwendungen bereitzustellen, muss auf jedem Rechner<br />

<strong>Sybase</strong> Open Client installiert sein. Sie müssen die Open Client-Software<br />

getrennt bei <strong>Sybase</strong> erwerben. Sie enthält eigene Installationsanweisungen.<br />

$ Verbindungsinformationen <strong>für</strong> Open Client-Clients sind in der Interface-<br />

Datei zu finden. Hinweise zur Interface-Datei finden Sie in der Open Client-<br />

Dokumentation und unter "Open Server konfigurieren" auf Seite 122 der<br />

Dokumentation ASA Datenbankadministration.


Kapitel 12 Deployment: Datenbanken und Anwendungen im System bereitstellen<br />

Tools zur Verwaltung bereitstellen<br />

Interactive SQL<br />

bereitstellen<br />

Abhängig von Ihrer Lizenzvereinbarung können Sie eine Reihe von<br />

Verwaltungstools wie Interactive SQL, <strong>Sybase</strong> Central und das<br />

Überwachungsdienstprogramm dbconsole bereitstellen.<br />

Die einfachste Methode zur Bereitstellung von Verwaltungstools ist es, die<br />

mitgelieferten InstallShield-Objekte zu verwenden. Weitere Hinweise finden<br />

Sie unter "InstallShield-Objekte und Vorlagen zum Bereitstellen verwenden"<br />

auf Seite 420.<br />

Wenn Ihre Kundenanwendung auf Rechnern mit begrenzten Ressourcen<br />

läuft, sollten Sie die C-Version von Interactive SQL (dbisqlc.exe) an Stelle<br />

der Standardversion bereitstellen (dbisql.exe und die dazugehörigen Java-<br />

Klassen).<br />

Das dbisqlc-Programm erfordert die clientseitigen Embedded SQL-<br />

Standardbibliotheken.<br />

$ Hinweise über die Systemanforderungen von Verwaltungstools finden<br />

Sie unter "Systemvoraussetzungen <strong>für</strong> das Administrationstool" auf<br />

Seite 153 der Dokumentation SQL <strong>Anywhere</strong> Studio Erste Orientierung.<br />

437


Datenbankserver im System bereitstellen<br />

Datenbankserver im System bereitstellen<br />

438<br />

Sie können einen Datenbankserver im System bereitstellen, indem Sie das<br />

Setup-Programm <strong>für</strong> das SQL <strong>Anywhere</strong> Studio den Endbenutzern<br />

übergeben. Wenn der Endbenutzer die richtigen Installationsoptionen wählt,<br />

verfügt er garantiert über alle erforderlichen Dateien.<br />

Die einfachste Methode zur Bereitstellung eines Personal Datenbankservers<br />

oder eines Netzwerk-Datenbankserver ist es, die mitgelieferten InstallShield-<br />

Objekte zu verwenden. Weitere Hinweise finden Sie unter "InstallShield-<br />

Objekte und Vorlagen zum Bereitstellen verwenden" auf Seite 420.<br />

Um einen Datenbankserver zu betreiben, müssen Sie eine Gruppe von<br />

Dateien installieren. Die Dateien werden in der folgenden Tabelle angeführt.<br />

Die Weitergabe dieser Dateien unterliegt den Bestimmungen der<br />

Lizenzvereinbarung. Sie müssen vorher feststellen, ob Sie das Recht haben,<br />

die Dateien des Datenbankservers weiterzugeben.<br />

Windows UNIX NetWare<br />

dbeng8.exe dbeng8 Nicht zutreffend<br />

dbsrv8.exe dbsrv8 dbsrv8.nlm<br />

dbserv8.dll libdbserv8.so,<br />

libdbtasks8_r.so<br />

dbserv8.dll dbserv8.so,<br />

libdbtasks8.so<br />

dblgen8.dll oder<br />

dblgde8.dll<br />

dbjava8.dll (1)<br />

Nicht zutreffend<br />

Nicht zutreffend<br />

dblgen8.res dblgen8.res<br />

libdbjava8.so (1)<br />

dbjava8.nlm (1)<br />

dbctrs8.dll Nicht zutreffend Nicht zutreffend<br />

dbextf.dll (2)<br />

asajdbc.zip (1,3)<br />

asajrt12.zip (1,3)<br />

classes.zip (1,3)<br />

dbmem.vxd (4)<br />

libdbextf.so (2)<br />

asajdbc.zip (1,3)<br />

asajrt12.zip (1,3)<br />

classes.zip (1,3)<br />

N/A N/A<br />

libunic.dll libunic.so N/A<br />

dbextf.nlm (2)<br />

asajdbc.zip (1,3)<br />

asajrt12.zip (1,3)<br />

classes.zip (1,3)<br />

asa.cvf asa.cvf asa.cvf<br />

Verzeichnis charsets\ charsets/ directory N/A<br />

1. Nur erforderlich, wenn Sie Java in der Datenbank verwenden. Bei Datenbanken, die mit JDK<br />

1.1 initialisiert wurden, stellen Sie asajdbc.zip bereit. Bei Datenbanken, die mit JDK 1.2 oder<br />

JDK 1.3 initialisiert wurden, stellen Sie asajrt13.zip bereit.


Hinweise<br />

Kapitel 12 Deployment: Datenbanken und Anwendungen im System bereitstellen<br />

2. Nur erforderlich, wenn Sie erweiterte Systemprozeduren und Funktionen benutzen (xp_).<br />

3. So installieren, dass die Klassen in dieser Datei über die Umgebungsvariable CLASSPATH<br />

gefunden werden.<br />

4. Erforderlich auf Windows 95/98/Me, wenn die dynamische Cachebelegung verwendet wird.<br />

♦ Je nach Konfiguration müssen Sie den Personal Datenbankserver<br />

(dbeng8) oder den Netzwerk-Datenbankserver (dbsrv8) im System<br />

bereitstellen.<br />

♦ Die Java DLL (dbjava8.dll) ist nur erforderlich, wenn der<br />

Datenbankserver die Funktionalität von Java in der Datenbank<br />

verwenden soll.<br />

♦ Die Tabelle enthält keine Dateien, die <strong>für</strong> das Ausführung von<br />

Dienstprogrammen wie dbbackup erforderlich sind.<br />

$ Hinweise zur Bereitstellung von Datenbank-Dienstprogrammen im<br />

System finden Sie unter "Tools zur Verwaltung bereitstellen" auf<br />

Seite 437.<br />

♦ Die zip-Dateien sind nur <strong>für</strong> Anwendungen erforderlich, die Java in der<br />

Datenbank verwenden und werden an einem Standort in der<br />

Umgebungsvariable CLASSPATH auf dem Rechner des Benutzers<br />

installiert.<br />

Datenbanken im System bereitstellen<br />

Eine Datenbankdatei wird im System bereitgestellt, indem Sie die<br />

Datenbankdatei auf der Festplatte des Endbenutzers installieren.<br />

Wenn der Datenbankserver sauber herunterfährt, brauchen Sie mit der<br />

Datenbankdatei kein Transaktionslog bereitzustellen. Wenn der Endbenutzer<br />

die Datenbank startet, wird ein neues Transaktionslog erstellt.<br />

Für Anwendungen mit SQL Remote muss die Datenbank in einem ordentlich<br />

synchronisierten Zustand erstellt werden und daher wird kein<br />

Transaktionslog benötigt. Sie können da<strong>für</strong> das Extraktionsdienstprogramm<br />

verwenden.<br />

Datenbanken auf schreibgeschützten Datenträgern bereitstellen<br />

Sie können Datenbanken auf schreibgeschützten Datenträgern verteilen, wie<br />

etwa CD-ROM, sofern Sie sie im schreibgeschützten Modus oder mit einer<br />

Write-Datei ausführen.<br />

$ Weitere Hinweise zum Ausführen von Datenbanken im<br />

schreibgeschützten Modus finden Sie unter "–r-Serveroption" auf Seite 166<br />

der Dokumentation ASA Datenbankadministration.<br />

439


Datenbankserver im System bereitstellen<br />

440<br />

Damit Änderungen an <strong>Adaptive</strong> Server <strong>Anywhere</strong>-Datenbanken<br />

vorgenommen werden können, die auf schreibgeschützten Datenträgern<br />

geliefert werden, wie etwa CD-ROM, können Sie eine Write-Datei<br />

verwenden. In der Write-Datei werden Änderungen gespeichert, die in einer<br />

schreibgeschützten Datenbank durchgeführt werden. Sie befindet sich auf<br />

einem Datenträger, der Schreiben und Lesen zulässt, z.B. einer Festplatte.<br />

In diesem Fall wird die Datenbankdatei auf der CD-ROM gespeichert, die<br />

Write-Datei hingegen auf der Festplatte. Die Verbindung wird mit der Write-<br />

Datei aufgenommen, die auf der Festplatte ein Transaktionslog führt.<br />

$ Weitere Hinweise zu Write-Dateien finden Sie unter "Mit Write-<br />

Dateien arbeiten" auf Seite 247 der Dokumentation ASA<br />

Datenbankadministration.


Kapitel 12 Deployment: Datenbanken und Anwendungen im System bereitstellen<br />

Eingebettete Datenbankanwendungen im<br />

System bereitstellen<br />

In diesem Abschnitt finden Sie Informationen über die Bereitstellung von<br />

eingebetteten Datenbanken, bei denen die Anwendung und die Datenbank<br />

auf demselben Rechner untergebracht sind.<br />

Eine eingebettete Datenbankanwendung enthält folgende Komponenten:<br />

♦ Datenbankserver Der <strong>Adaptive</strong> Server <strong>Anywhere</strong> Personal<br />

Datenbankserver.<br />

$ Hinweise zur Bereitstellung von Datenbankservern finden Sie<br />

unter "Datenbankserver im System bereitstellen" auf Seite 438.<br />

♦ SQL Remote Wenn Ihre Anwendung die Replikation mit SQL Remote<br />

benutzt, müssen Sie das Deployment von SQL Remote Message Agent<br />

vornehmen.<br />

♦ Die Datenbank Sie müssen eine Datenbankdatei im System<br />

bereitstellen, die die von der Anwendung benutzten Daten aufnimmt.<br />

Personal Server im System bereitstellen<br />

Wenn Sie eine Anwendung im System bereitstellen, die den Personal Server<br />

benutzt, müssen Sie sowohl die Komponenten der Clientanwendung<br />

bereitstellen, als auch die Komponenten des Datenbankservers.<br />

Die Sprachen-Ressourcebibliothek (dblgen8.dll) wird vom Client und vom<br />

Server gemeinsam genutzt. Sie brauchen nur ein Exemplar dieser Datei.<br />

Es wird empfohlen, dass Sie die Installationsvorgaben von <strong>Adaptive</strong> Server<br />

<strong>Anywhere</strong> einhalten und die Dateien <strong>für</strong> Client und Server in demselben<br />

Verzeichnis installieren.<br />

Beachten Sie, dass Sie die Java zip-Dateien und die Java-DLL bereitstellen<br />

müssen, wenn Ihre Anwendung Java in der Datenbank benutzt.<br />

Datenbank-Dienstprogramme bereitstellen<br />

Wenn Sie Datenbank-Dienstprogramme (wie z.B. dbbackup.exe) gemeinsam<br />

mit Ihrer Anwendung im System bereitstellen müssen, brauchen Sie die<br />

Programmdatei des Dienstprogramms mit folgenden zusätzlichen Dateien:<br />

441


Eingebettete Datenbankanwendungen im System bereitstellen<br />

Hinweise<br />

442<br />

Beschreibung Windows UNIX<br />

Bibliothek der Datenbanktools Dbtool8.dll libdbtools8.so,<br />

libdbtasks8.so<br />

Zusätzliche Bibliothek dbwtsp8.dll Libdbwtsp8.so<br />

Sprachen-Ressourcebibliothek dblgen8.dll dblgen8.res<br />

Verbindungsdialog (nur dbisqlc) dbcon8.dll<br />

♦ Die Datenbanktools sind Embedded SQL-Anwendungen. Sie müssen die<br />

<strong>für</strong> diese Anwendungen erforderlichen Dateien bereitstellen. Siehe dazu<br />

die Liste in "Bereitstellen von Embedded SQL-Clients" auf Seite 433.<br />

♦ Bei Anwendungen mit mehrfachen Threads unter UNIX benutzen Sie<br />

libdbodbc8_r.so und libdbtasks8_r.so.<br />

SQL Remote im System bereitstellen<br />

Wenn Sie den Nachrichtenagenten von SQL Remote im System bereitstellen,<br />

müssen folgende Dateien installiert werden:<br />

Beschreibung Windows UNIX<br />

Nachrichtenagent dbremote.exe dbremote<br />

Bibliothek der Datenbanktools dbtool8.dll libdbtools8.so,<br />

libdbtasks8.so<br />

Zusätzliche Bibliothek dbwtsp8.dll libdbwtsp8.so<br />

Sprachen-Ressourcebibliothek dblgen8.dll dblgen8.res<br />

Bibliothek <strong>für</strong> VIM-<br />

Nachrichtenverbindungen 1<br />

Bibliothek <strong>für</strong> SMTP-<br />

Nachrichtenverbindungen 1<br />

Bibliothek <strong>für</strong> FILE-<br />

Nachrichtenverbindungen 1<br />

Bibliothek <strong>für</strong> FTP-<br />

Nachrichtenverbindungen 1<br />

Bibliothek <strong>für</strong> MAPI-<br />

Nachrichtenverbindungen 1<br />

dbvim8.dll<br />

dbsmtp8.dll<br />

dbfile8.dll libdbfile8.so<br />

dbftp8.dll<br />

dbmapi8.dll<br />

Schnittstellenbibliothek dblib8.dll<br />

1<br />

Stellen Sie nur die Bibliothek <strong>für</strong> die Nachrichtenverbindung bereit, die die Anwendung<br />

benutzen wird.


Kapitel 12 Deployment: Datenbanken und Anwendungen im System bereitstellen<br />

Es wird empfohlen, dass Sie die Installationsvorgaben von <strong>Adaptive</strong> Server<br />

<strong>Anywhere</strong> einhalten und die Dateien <strong>für</strong> SQL Remote in demselben<br />

Verzeichnis installieren wie <strong>Adaptive</strong> Server <strong>Anywhere</strong>.<br />

Bei Anwendungen mit mehrfachen Threads unter UNIX benutzen Sie<br />

libdbodbc8_r.so und libdbtasks8_r.so.<br />

443


Eingebettete Datenbankanwendungen im System bereitstellen<br />

444


KAPITEL 13<br />

Fehlermeldungen des SQL-Präprozessors<br />

Über dieses<br />

Kapitel<br />

Inhalt<br />

In diesem Kapitel finden Sie eine Liste aller Fehler- und Warnmeldungen des<br />

SQL-Präprozessors.<br />

Thema Seite<br />

Fehlermeldungen des SQL-Präprozessors, sortiert nach<br />

Fehlernummern 446<br />

SQLPP-Fehler 450<br />

445


Fehlermeldungen des SQL-Präprozessors, sortiert nach Fehlernummern<br />

Fehlermeldungen des SQL-Präprozessors,<br />

sortiert nach Fehlernummern<br />

446<br />

Fehlernummer Meldung<br />

2601 "Subskriptionswert %1 zu groß" auf<br />

Seite 464<br />

2602 "Kombinierter Zeiger und Arrays <strong>für</strong><br />

Hosttypen nicht zulässig" auf<br />

Seite 455<br />

2603 "Nur eindimensionale Arrays werden<br />

<strong>für</strong> den 'char'-Typ unterstützt" auf<br />

Seite 463<br />

2604 "VARCHAR-Typ muss eine Länge<br />

haben" auf Seite 454<br />

2605 "Arrays von VARCHAR nicht<br />

unterstützt" auf Seite 454<br />

2606 "VARCHAR-Hostvariable können<br />

keine Zeiger sein" auf Seite 453<br />

2607 "Initialisieren bei der VARCHAR-<br />

Hostvariablen nicht zulässig" auf<br />

Seite 459<br />

2608 "FIXCHAR-Typ muss eine Länge<br />

haben" auf Seite 451<br />

2609 "Arrays werden <strong>für</strong> FIXCHAR nicht<br />

unterstützt" auf Seite 454<br />

2610 "Arrays dieses Typs werden nicht<br />

unterstützt" auf Seite 455<br />

2611 "Beim Dezimaltyp muss die Anzahl<br />

der Dezimalstellen angegeben<br />

werden" auf Seite 463<br />

2612 "Dezimalzahlen-Arrays sind nicht<br />

zulässig" auf Seite 454<br />

2613 "Unbekannter Hostvariablen-Typ"<br />

auf Seite 453<br />

2614 "Ungültige Ganzzahl" auf Seite 460<br />

2615 "'%1' Hostvariable muss ein C-<br />

Zeichenfolgentyp sein" auf Seite 450


Kapitel 13 Fehlermeldungen des SQL-Präprozessors<br />

Fehlernummer Meldung<br />

2617 "Das Symbol ’%1’ ist bereits<br />

definiert" auf Seite 450<br />

2618 "Ungültiger Typ <strong>für</strong> SQL-<br />

Anweisungsvariable" auf Seite 461<br />

2619 "Include-Datei '%1' kann nicht<br />

gefunden werden" auf Seite 451<br />

2620 "Hostvariable '%1' ist unbekannt" auf<br />

Seite 457<br />

2621 "Indikatorvariable '%1' ist<br />

unbekannt" auf Seite 459<br />

2622 "Ungültiger Typ <strong>für</strong> Indikatorvariable<br />

'%1'" auf Seite 460<br />

2623 "Ungültiger Hostvariablen-Typ auf<br />

'%1'" auf Seite 460<br />

2625 "Hostvariable '%1' hat zwei<br />

verschiedene Definitionen" auf<br />

Seite 457<br />

2626 "Anweisung '%1' wurde vorher noch<br />

nicht vorbereitet" auf Seite 463<br />

2627 "Cursor '%1' wurde vorher noch nicht<br />

deklariert" auf Seite 455<br />

2628 "Unbekannte Anweisung '%1'" auf<br />

Seite 465<br />

2629 "Hostvariable <strong>für</strong> diesen Cursor nicht<br />

zulässig" auf Seite 457<br />

2630 "Hostvariable zweimal angegeben -<br />

bei 'Declare' und bei 'Open'" auf<br />

Seite 458<br />

2631 "Host-Liste oder Using-Klausel <strong>für</strong><br />

%1 muss angegeben werden" auf<br />

Seite 461<br />

2633 "Keine INTO-Klausel in SELECT-<br />

Anweisung" auf Seite 462<br />

2634 "Fehlerhafte SQL-Sprachensyntax -<br />

Dies ist eine '%1' Erweiterung" auf<br />

Seite 458<br />

2635 "Fehlerhafte Embedded-SQL-<br />

Sprachensyntax - Dies ist eine '%1'<br />

Erweiterung" auf Seite 458<br />

447


Fehlermeldungen des SQL-Präprozessors, sortiert nach Fehlernummern<br />

448<br />

Fehlernummer Meldung<br />

2636 "Fehlerhafte Embedded-SQL-Syntax"<br />

auf Seite 458<br />

2637 "Fehlendes schließendes<br />

Anführungszeichen <strong>für</strong> die<br />

Zeichenfolge" auf Seite 461<br />

2639 "Token zu lang" auf Seite 464<br />

2640 "'%1' Hostvariable muss ein<br />

Ganzzahltyp sein" auf Seite 450<br />

2641 "SQLDA muss <strong>für</strong> DESCRIBE<br />

angegeben werden" auf Seite 462<br />

2642 "Zwei SQLDAs <strong>für</strong> denselben Typ<br />

angegeben (INTO oder USING)" auf<br />

Seite 453<br />

2646 "Statische Cursor können nicht<br />

beschrieben werden" auf Seite 455<br />

2647 "Makros können nicht neu definiert<br />

werden" auf Seite 453<br />

2648 "Ungültige Arraydimension" auf<br />

Seite 453<br />

2649 "Ungültiger Deskriptor-Index" auf<br />

Seite 459<br />

2650 "Ungültiges Feld <strong>für</strong> SET<br />

DESCRIPTOR" auf Seite 460<br />

2651 "Feld in SET DESCRIPTOR<br />

Anweisung mehr als einmal<br />

verwendet" auf Seite 456<br />

2652 "Datenwert muss eine Hostvariable<br />

sein" auf Seite 456<br />

2660 "Into-Klausel in 'declare cursor' nicht<br />

zulässig - ignoriert" auf Seite 452<br />

2661 "Nicht erkannte SQL-Syntax" auf<br />

Seite 465<br />

2662 "Unbekannte SQL-Funktion '%1'" auf<br />

Seite 465<br />

2663 "Falsche Anzahl von Parametern <strong>für</strong><br />

SQL-Funktion '%1'" auf Seite 466<br />

2664 "Statische Anweisungsnamen<br />

funktionieren nicht richtig, wenn von<br />

2 Threads benutzt" auf Seite 463


Kapitel 13 Fehlermeldungen des SQL-Präprozessors<br />

Fehlernummer Meldung<br />

2665 "Hostvariable ’%1!’ wurde neu<br />

definiert" auf Seite 457<br />

2666 "Erweiterung des Herstellers" auf<br />

Seite 466<br />

2667 "Intermediate-SQL-Merkmal" auf<br />

Seite 459<br />

2668 "Volles SQL-Merkmal" auf Seite 456<br />

2669 "Transact-SQL-Erweiterung" auf<br />

Seite 464<br />

2680 "Kein ’Declare’-Abschnitt und keine<br />

INCLUDE SQLCA Anweisung" auf<br />

Seite 462<br />

2681 "Temporäre Datei kann nicht geöffnet<br />

werden" auf Seite 465<br />

2682 "Fehler beim Lesen der temporären<br />

Datei" auf Seite 456<br />

2683 "Fehler beim Schreiben der<br />

Ausgabedatei" auf Seite 456<br />

2690 "Inkonsistente Zahl von Hostvariable<br />

<strong>für</strong> diesen Cursor" auf Seite 452<br />

2691 "Inkonsistente Hostvariablentypen <strong>für</strong><br />

diesen Cursor" auf Seite 452<br />

2692 "Inkonsistente Indikatorvariable <strong>für</strong><br />

diesen Cursor" auf Seite 452<br />

2693 "Merkmal steht bei UltraLite nicht<br />

zur Verfügung" auf Seite 451<br />

2694 "Kein OPEN-Befehl <strong>für</strong> Cursor '%1'"<br />

auf Seite 462<br />

2695 "Kein FETCH- oder PUT-Befehl <strong>für</strong><br />

Cursor '%1'" auf Seite 462<br />

2696 "Hostvariable '%1' wird mit<br />

unterschiedlichen Indikatoren mehr<br />

als einmal verwendet" auf Seite 451<br />

2697 "Größenlimit <strong>für</strong> long binary/long<br />

varchar ist 65535 <strong>für</strong> UltraLite" auf<br />

Seite 461<br />

449


SQLPP-Fehler<br />

SQLPP-Fehler<br />

450<br />

In diesem Abschnitt finden Sie die Meldungen, die vom SQL-Präprozessor<br />

generiert werden. Die Meldungen können je nach Einstellung durch die<br />

Befehlszeilenparameter Fehler-, Warnmeldungen oder beides sein.<br />

$ Weitere Hinweise zum SQL-Präprozessor und zu seinen<br />

Befehlszeilenparametern finden Sie unter "SQL-Präprozessor" auf Seite 249.<br />

’%1’ Hostvariable muss ein C-Zeichenfolgentyp sein<br />

Mögliche Ursache<br />

Fehlernummer Fehlertyp<br />

2615 Fehler<br />

Eine C-Zeichenfolge war in einer Embedded SQL-Anweisung erforderlich<br />

(<strong>für</strong> einen Cursornamen, Optionsnamen etc.), und der übergebene Wert war<br />

keine C-Zeichenfolge.<br />

’%1’ Hostvariable muss ein Ganzzahltyp sein<br />

Mögliche Ursache<br />

Fehlernummer Fehlertyp<br />

2640 Fehler<br />

Sie haben eine Hostvariable, die kein Ganzzahltyp ist, in einer Anweisung<br />

verwendet, in der nur Hostvariablen vom Ganzzahltyp zulässig sind.<br />

Das Symbol ’%1’ ist bereits definiert<br />

Mögliche Ursache<br />

Fehlernummer Fehlertyp<br />

2617 Fehler<br />

Sie haben eine Hostvariable zweimal definiert.


Include-Datei ’%1’ kann nicht gefunden werden<br />

Mögliche Ursache<br />

Kapitel 13 Fehlermeldungen des SQL-Präprozessors<br />

Fehlernummer Fehlertyp<br />

2619 Fehler<br />

Die angegebene Include-Datei wurde nicht gefunden. Beachten Sie, dass der<br />

Präprozessor die INCLUDE-Umgebungsvariable zur Suche nach Include-<br />

Dateien verwendet.<br />

FIXCHAR-Typ muss eine Länge haben<br />

Mögliche Ursache<br />

Fehlernummer Fehlertyp<br />

2608 Fehler<br />

Sie haben den Makro DECL_FIXCHAR benutzt, um eine Hostvariable des<br />

Typs FIXCHAR zu deklarieren, aber keine Länge angegeben.<br />

Merkmal steht bei UltraLite nicht zur Verfügung<br />

Mögliche Ursache<br />

Fehlernummer Fehlertyp<br />

2693 Markierung (Warnung oder Fehler)<br />

Sie haben eine Funktion benutzt, die von UltraLite nicht unterstützt wird.<br />

Hostvariable ’%1’ wird mit unterschiedlichen Indikatoren mehr als<br />

einmal verwendet<br />

Mögliche Ursache<br />

Fehlernummer Fehlertyp<br />

2696 Fehler<br />

Sie haben dieselbe Hostvariable mehrere Male mit unterschiedlichen<br />

Indikatorvariablen in derselben Anweisung verwendet. Dies wird nicht<br />

unterstützt.<br />

451


SQLPP-Fehler<br />

Inkonsistente Hostvariablentypen <strong>für</strong> diesen Cursor<br />

Mögliche Ursache<br />

452<br />

Fehlernummer Fehlertyp<br />

2691 Fehler<br />

Sie haben eine Hostvariable mit einem anderen Typ oder einer anderen<br />

Länge verwendet als vorher mit diesem Cursor. Hostvariablentypen müssen<br />

<strong>für</strong> den Cursor konsistent sein.<br />

Inkonsistente Indikatorvariable <strong>für</strong> diesen Cursor<br />

Mögliche Ursache<br />

Fehlernummer Fehlertyp<br />

2692 Fehler<br />

Sie haben eine Indikatorvariable benutzt, obwohl vorher mit dem Cursor<br />

keine verwendet wurde, oder Sie haben keine Indikatorvariable benutzt,<br />

obwohl vorher mit dem Cursor eine benutzt wurde. Indikatorvariablen<br />

müssen bei Cursorn konsistent verwendet werden.<br />

Inkonsistente Zahl von Hostvariable <strong>für</strong> diesen Cursor<br />

Mögliche Ursache<br />

Fehlernummer Fehlertyp<br />

2690 Fehler<br />

Sie haben eine andere Anzahl von Hostvariablen benutzt als vorher mit dem<br />

Cursor benutzt wurde. Die Anzahl von Hostvariablentypen muss <strong>für</strong> den<br />

Cursor konsistent sein.<br />

Into-Klausel in 'declare cursor' nicht zulässig - ignoriert<br />

Mögliche Ursache<br />

Fehlernummer Fehlertyp<br />

2660 Warnung<br />

Sie haben eine INTO-Klausel mit einer DECLARE CURSOR-Anweisung<br />

verwendet. Die INTO-Klausel wird ignoriert.


Ungültige Arraydimension<br />

Mögliche Ursache<br />

Kapitel 13 Fehlermeldungen des SQL-Präprozessors<br />

Fehlernummer Fehlertyp<br />

2648 Fehler<br />

Die Arraydimension der Variablen ist negativ.<br />

Makros können nicht neu definiert werden<br />

Mögliche Ursache<br />

Fehlernummer Fehlertyp<br />

2647 Fehler<br />

Ein Präprozessor-Makro wurde zweimal definiert, möglicherweise in einer<br />

Header-Datei.<br />

Zwei SQLDAs <strong>für</strong> denselben Typ angegeben (INTO oder USING)<br />

Mögliche Ursache<br />

Unbekannter Hostvariablen-Typ<br />

Mögliche Ursache<br />

Fehlernummer Fehlertyp<br />

2642 Fehler<br />

Sie haben zwei INTO DESCRIPTOR- oder zwei USING DESCRIPTOR-<br />

Klauseln <strong>für</strong> diese Anweisung angegeben.<br />

Fehlernummer Fehlertyp<br />

2613 Fehler<br />

Sie haben eine Hostvariable eines Typs angegeben, der vom SQL-<br />

Präprozessor nicht verstanden wird.<br />

VARCHAR-Hostvariable können keine Zeiger sein<br />

Fehlernummer Fehlertyp<br />

2606 Fehler<br />

453


SQLPP-Fehler<br />

Mögliche Ursache<br />

454<br />

Sie haben versucht, eine Hostvariable als Zeiger auf einen VARCHAR- oder<br />

BINARY-Typ zu deklarieren. Dies ist kein zulässiger Hostvariablentyp.<br />

VARCHAR-Typ muss eine Länge haben<br />

Mögliche Ursache<br />

Fehlernummer Fehlertyp<br />

2604 Fehler<br />

Sie haben versucht, eine VARCHAR- oder BINARY-Hostvariable mit dem<br />

DECL_VARCHAR- oder DECL_BINARY-Makro zu deklarieren, aber<br />

keine Größe <strong>für</strong> das Array angegeben.<br />

Arrays werden <strong>für</strong> FIXCHAR nicht unterstützt<br />

Mögliche Ursache<br />

Fehlernummer Fehlertyp<br />

2609 Fehler<br />

Sie haben versucht, eine Hostvariable als Array von FIXCHAR-Arrays zu<br />

deklarieren. Dies ist kein zulässiger Hostvariablentyp.<br />

Arrays von VARCHAR nicht unterstützt<br />

Mögliche Ursache<br />

Fehlernummer Fehlertyp<br />

2605 Fehler<br />

Sie haben versucht, eine Hostvariable als Array von VARCHAR- oder<br />

BINARY-Arrays zu deklarieren. Dies ist kein zulässiger Hostvariablentyp.<br />

Dezimalzahlen-Arrays sind nicht zulässig<br />

Fehlernummer Fehlertyp<br />

2612 Fehler


Mögliche Ursache<br />

Kapitel 13 Fehlermeldungen des SQL-Präprozessors<br />

Sie haben versucht, eine Hostvariable als Array von DECIMAL-Arrays zu<br />

deklarieren. Ein dezimales Array ist kein zulässiger Hostvariablentyp.<br />

Arrays dieses Typs werden nicht unterstützt<br />

Mögliche Ursache<br />

Fehlernummer Fehlertyp<br />

2610 Fehler<br />

Sie haben versucht, ein Hostvariablen-Array eines Typs zu deklarieren, der<br />

nicht unterstützt wird.<br />

Statische Cursor können nicht beschrieben werden<br />

Mögliche Ursache<br />

Fehlernummer Fehlertyp<br />

2646 Fehler<br />

Sie haben einen statischen Cursor beschrieben. Beim Beschreiben eines<br />

Cursors muss der Cursorname in einer Hostvariablen angegeben sein.<br />

Kombinierter Zeiger und Arrays <strong>für</strong> Hosttypen nicht zulässig<br />

Mögliche Ursache<br />

Fehlernummer Fehlertyp<br />

2602 Fehler<br />

Sie haben ein Array von Zeigern als Hostvariable benutzt. Dies ist nicht<br />

zulässig.<br />

Cursor ’%1’ wurde vorher noch nicht deklariert<br />

Mögliche Ursache<br />

Fehlernummer Fehlertyp<br />

2627 Fehler<br />

Ein Embedded SQL-Cursorname wurde benutzt (in FETCH, OPEN, CLOSE<br />

etc.), ohne vorher deklariert worden zu sein.<br />

455


SQLPP-Fehler<br />

Datenwert muss eine Hostvariable sein<br />

Mögliche Ursache<br />

456<br />

Fehlernummer Fehlertyp<br />

2652 Fehler<br />

Die in der SET DESCRIPTOR-Anweisung benutzte Variable wurde nicht als<br />

Hostvariable deklariert.<br />

Fehler beim Lesen der temporären Datei<br />

Mögliche Ursache<br />

Fehlernummer Fehlertyp<br />

2682 Fehler<br />

Beim Lesen aus einer temporären Datei ist ein Fehler aufgetreten.<br />

Fehler beim Schreiben der Ausgabedatei<br />

Mögliche Ursache<br />

Fehlernummer Fehlertyp<br />

2683 Fehler<br />

Beim Schreiben in die Ausgabedatei ist ein Fehler aufgetreten.<br />

Feld in SET DESCRIPTOR Anweisung mehr als einmal verwendet<br />

Mögliche Ursache<br />

Volles SQL-Merkmal<br />

Fehlernummer Fehlertyp<br />

2651 Fehler<br />

Dasselbe Schlüsselwort wurde mehr als einmal in einer einzigen SET<br />

DESCRIPTOR-Anweisung verwendet.<br />

Fehlernummer Fehlertyp<br />

2668 Markierung (Warnung oder Fehler)


Mögliche Ursache<br />

Kapitel 13 Fehlermeldungen des SQL-Präprozessors<br />

Sie haben eine volle SQL/92-Funktion verwendet und mit den Optionen -ee,<br />

-ei, -we oder -wi im Präprozessor verarbeitet.<br />

Hostvariable ’%1!’ wurde neu definiert<br />

Mögliche Ursache<br />

Fehlernummer Fehlertyp<br />

2665 Warnung<br />

Sie haben dieselbe Hostvariable mit einem anderen Hosttyp neu definiert.<br />

Für den SQL-Präprozessor sind Hostvariable globale Variable: zwei<br />

Hostvariable mit unterschiedlichen Typen können niemals den gleichen<br />

Namen haben.<br />

Hostvariable ’%1’ hat zwei verschiedene Definitionen<br />

Mögliche Ursache<br />

Hostvariable ’%1’ ist unbekannt<br />

Mögliche Ursache<br />

Fehlernummer Fehlertyp<br />

2625 Fehler<br />

Dieselbe Hostvariable wurden in demselben Modul mit zwei verschiedenen<br />

Typen definiert. Beachten Sie, dass die Hostvariablen in einem C-Modul<br />

global sind.<br />

Fehlernummer Fehlertyp<br />

2620 Fehler<br />

Sie haben eine Hostvariable in einer Anweisung benutzt, und diese<br />

Hostvariable wurde nicht in einem Declare-Abschnitt deklariert.<br />

Hostvariable <strong>für</strong> diesen Cursor nicht zulässig<br />

Fehlernummer Fehlertyp<br />

2629 Fehler<br />

457


SQLPP-Fehler<br />

Mögliche Ursache<br />

458<br />

Hostvariable sind in der Declare-Anweisung <strong>für</strong> den angegebenen Cursor<br />

nicht zulässig. Wenn der Cursorname über eine Hostvariable übergeben<br />

wird, müssen Sie volle dynamische SQL verwenden und die Anweisung<br />

vorbereiten. Eine vorbereitete Anweisung kann Hostvariable aufweisen.<br />

Hostvariable zweimal angegeben - bei ’Declare’ und bei ’Open’<br />

Mögliche Ursache<br />

Fehlernummer Fehlertyp<br />

2630 Fehler<br />

Sie haben Hostvariablen <strong>für</strong> einen Cursor in den Declare- und Open-<br />

Anweisungen angegeben. Im statischen Fall müssen Sie Hostvariable in der<br />

Declare-Anweisung angeben. Im dynamischen Fall geben Sie sie in der<br />

Open-Anweisung an.<br />

Fehlerhafte Embedded-SQL-Sprachensyntax - Dies ist eine ’%1’<br />

Erweiterung<br />

Fehlernummer Fehlertyp<br />

2635 Fehler<br />

Fehlerhafte Embedded-SQL-Syntax<br />

Mögliche Ursache<br />

Fehlernummer Fehlertyp<br />

2636 Fehler<br />

Eine Embedded SQL-spezifische Anweisung (OPEN, DECLARE, FETCH<br />

etc.) hat einen Syntaxfehler.<br />

Fehlerhafte SQL-Sprachensyntax - Dies ist eine ’%1’ Erweiterung<br />

Fehlernummer Fehlertyp<br />

2634 Fehler


Indikatorvariable ’%1’ ist unbekannt<br />

Mögliche Ursache<br />

Kapitel 13 Fehlermeldungen des SQL-Präprozessors<br />

Fehlernummer Fehlertyp<br />

2621 Fehler<br />

Sie haben eine Indikatorvariable in einer Anweisung benutzt, und diese<br />

Indikatorvariable wurde nicht in einem Declare-Abschnitt deklariert.<br />

Initialisieren bei der VARCHAR-Hostvariablen nicht zulässig<br />

Mögliche Ursache<br />

Intermediate-SQL-Merkmal<br />

Mögliche Ursache<br />

Ungültiger Deskriptor-Index<br />

Mögliche Ursache<br />

Fehlernummer Fehlertyp<br />

2607 Fehler<br />

Sie können keinen C-Variablen-Initialisierer <strong>für</strong> eine Hostvariable des Typs<br />

VARCHAR oder BINARY angeben. Sie müssen diese Variable in regulätem<br />

ausführbarem C-Code initialisieren.<br />

Fehlernummer Fehlertyp<br />

2667 Markierung (Warnung oder Fehler)<br />

Sie haben eine Intermediate-SQL/92-Funktion verwendet und mit den<br />

Optionen -ee oder -we im Präprozessor verarbeitet.<br />

Fehlernummer Fehlertyp<br />

2649 Fehler<br />

Sie haben weniger als eine Variable mit der Anweisung ALLOCATE<br />

DESCRIPTOR zugewiesen.<br />

459


SQLPP-Fehler<br />

Ungültiges Feld <strong>für</strong> SET DESCRIPTOR<br />

Mögliche Ursache<br />

460<br />

Fehlernummer Fehlertyp<br />

2650 Fehler<br />

Ein ungültiges oder unbekanntes Schlüsselwort ist in einer SET<br />

DESCRIPTOR-Anweisung vorhanden. Schlüsselwörter können nur sein:<br />

TYPE, PRECISION, SCALE, LENGTH, INDICATOR oder DATA.<br />

Ungültiger Hostvariablen-Typ auf '%1'<br />

Mögliche Ursache<br />

Ungültige Ganzzahl<br />

Mögliche Ursache<br />

Fehlernummer Fehlertyp<br />

2623 Fehler<br />

Sie haben an einer Stelle, an der der Präprozessor eine Hostvariable vom<br />

Zeichenfolgentyp erwartete, eine Hostvariable verwendet, die kein<br />

Zeichenfolgentyp ist.<br />

Fehlernummer Fehlertyp<br />

2614 Fehler<br />

Eine Ganzzahl wurde in einer Embedded SQL-Anweisung (<strong>für</strong> einen Fetch-<br />

Offset oder einen Hostvariablen-Arrayindex, etc.) erwartet, und der<br />

Präprozessor konnte das übergebene Element nicht in eine Ganzzahl<br />

konvertieren.<br />

Ungültiger Typ <strong>für</strong> Indikatorvariable '%1'<br />

Mögliche Ursache<br />

Fehlernummer Fehlertyp<br />

2622 Fehler<br />

Indikatorvariable müssen den Typ "short int" haben. Sie haben eine Variable<br />

eines anderen Typs als Indikatorvariable verwendet.


Ungültiger Typ <strong>für</strong> SQL-Anweisungsvariable<br />

Mögliche Ursache<br />

Kapitel 13 Fehlermeldungen des SQL-Präprozessors<br />

Fehlernummer Fehlertyp<br />

2618 Fehler<br />

Eine Hostvariable, die als Anweisungsbezeichner benutzt wird, muss vom<br />

Typ a_sql_statement_number sein. Sie haben versucht, eine Hostvariable<br />

eines anderen Typs als Anweisungsbezeichner zu benutzen.<br />

Größenlimit <strong>für</strong> long binary/long varchar ist 65535 <strong>für</strong> UltraLite<br />

Mögliche Ursache<br />

Fehlernummer Fehlertyp<br />

2697 Fehler<br />

Bei der Verwendung von DECL_LONGBINARY oder<br />

DECL_LONGVARCHAR mit UltraLite ist die Obergrenze <strong>für</strong> das Array 64<br />

KByte.<br />

Fehlendes schließendes Anführungszeichen <strong>für</strong> die Zeichenfolge<br />

Mögliche Ursache<br />

Fehlernummer Fehlertyp<br />

2637 Fehler<br />

Sie haben eine Zeichenfolgenkonstante in einer Embedded SQL-Anweisung<br />

eingegeben, aber es ist kein schließendes Anführungszeichen <strong>für</strong> das<br />

Zeilenende oder das Dateiende vorhanden.<br />

Host-Liste oder Using-Klausel <strong>für</strong> %1 muss angegeben werden<br />

Mögliche Ursache<br />

Fehlernummer Fehlertyp<br />

2631 Fehler<br />

Die angegebene Anweisung benötigt die Angabe von Hostvariablen in einer<br />

Hostvariablenliste oder aus einer SQLDA.<br />

461


SQLPP-Fehler<br />

SQLDA muss <strong>für</strong> DESCRIBE angegeben werden<br />

462<br />

Fehlernummer Fehlertyp<br />

2641 Fehler<br />

Kein FETCH- oder PUT-Befehl <strong>für</strong> Cursor '%1'<br />

Mögliche Ursache<br />

Fehlernummer Fehlertyp<br />

2695 Fehler<br />

Ein Cursor ist deklariert und geöffnet, wird aber nie verwendet.<br />

Keine INTO-Klausel in SELECT-Anweisung<br />

Mögliche Ursache<br />

Fehlernummer Fehlertyp<br />

2633 Fehler<br />

Kein OPEN-Befehl <strong>für</strong> Cursor '%1'<br />

Mögliche Ursache<br />

Sie haben eine statische Embedded-SQL-SELECT-Anweisung angegeben,<br />

aber keine INTO-Klausel <strong>für</strong> die Ergebnisse festgelegt.<br />

Fehlernummer Fehlertyp<br />

2694 Fehler<br />

Ein Cursor ist deklariert und möglicherweise benutzt, wird aber nie geöffnet.<br />

Kein ’Declare’-Abschnitt und keine INCLUDE SQLCA Anweisung<br />

Mögliche Ursache<br />

Fehlernummer Fehlertyp<br />

2680 Fehler<br />

Die EXEC SQL INCLUDE SQLCA-Anweisung fehlt in der Quelldatei.


Kapitel 13 Fehlermeldungen des SQL-Präprozessors<br />

Nur eindimensionale Arrays werden <strong>für</strong> den 'char'-Typ unterstützt<br />

Mögliche Ursache<br />

Fehlernummer Fehlertyp<br />

2603 Fehler<br />

Sie haben versucht, eine Hostvariable als Array von Zeichen-Arrays zu<br />

deklarieren. Dies ist kein zulässiger Hostvariablentyp.<br />

Beim Dezimaltyp muss die Anzahl der Dezimalstellen angegeben<br />

werden<br />

Mögliche Ursache<br />

Fehlernummer Fehlertyp<br />

2611 Fehler<br />

Sie müssen die Dezimalstellen angeben, wenn Sie eine gepackte dezimale<br />

Hostvariable mit dem Makro DECL_DECIMAL deklarieren. Die<br />

Gesamtstellenanzahl ist fakultativ.<br />

Anweisung ’%1’ wurde vorher noch nicht vorbereitet<br />

Mögliche Ursache<br />

Fehlernummer Fehlertyp<br />

2626 Fehler<br />

Ein Embedded SQL-Anweisungsname wurde benutzt (EXECUTE), ohne<br />

vorher vorbereitet worden zu sein.<br />

Statische Anweisungsnamen funktionieren nicht richtig, wenn von<br />

2 Threads benutzt<br />

Fehlernummer Fehlertyp<br />

2664 Warnung<br />

463


SQLPP-Fehler<br />

Mögliche Ursache<br />

Subskriptionswert %1 zu groß<br />

Mögliche Ursache<br />

Token zu lang<br />

Mögliche Ursache<br />

Transact-SQL-Erweiterung<br />

Mögliche Ursache<br />

464<br />

Sie haben einen statischen Anweisungsnamen benutzt und mit dem<br />

Wiedereintrittsparameter -r im Präprozessor verarbeitet. Statische<br />

Anweisungsnamen bewirken, dass statische Variable generiert werden, die<br />

aus der Datenbank einfließen. Wenn zwei Threads dieselbe Anweisung<br />

verwenden, kommt es wegen dieser Variablen zum Engpass. Benutzen Sie<br />

eine lokale Hostvariable als Anweisungsbezeichner, und nicht einen<br />

statischen Namen.<br />

Fehlernummer Fehlertyp<br />

2601 Fehler<br />

Sie haben versucht, eine Hostvariable zu indizieren, die in einem Array mit<br />

einem zu großen Wert <strong>für</strong> das Array liegt.<br />

Fehlernummer Fehlertyp<br />

2639 Fehler<br />

Der SQL-Präprozessor hat eine maximale Tokenlänge von 2 KByte. Alle<br />

Token über 2 KByte ergeben diesen Fehler. Für Konstantenzeichenfolgen in<br />

Embedded SQL-Befehlen (Hauptursache <strong>für</strong> diesen Fehler) benutzen Sie<br />

eine Zeichenfolgenverkettung, um eine längere Zeichenfolge zu<br />

ermöglichen.<br />

Fehlernummer Fehlertyp<br />

2669 Markierung (Warnung oder Fehler)<br />

Sie haben eine <strong>Sybase</strong> Transact-SQL-Funktion verwendet, die von SQL/92<br />

nicht definiert wurde, und mit den Parametern -ee, -ei, -ef, -we, -wi oder -wf<br />

im Präprozessor verarbeitet.


Temporäre Datei kann nicht geöffnet werden<br />

Mögliche Ursache<br />

Unbekannte SQL-Funktion ’%1’<br />

Mögliche Ursache<br />

Unbekannte Anweisung ’%1’<br />

Mögliche Ursache<br />

Nicht erkannte SQL-Syntax<br />

Mögliche Ursache<br />

Kapitel 13 Fehlermeldungen des SQL-Präprozessors<br />

Fehlernummer Fehlertyp<br />

2681 Fehler<br />

Beim Öffnen einer temporären Datei ist ein Fehler aufgetreten.<br />

Fehlernummer Fehlertyp<br />

2662 Warnung<br />

Sie haben eine SQL-Funktion benutzt, die dem Präprozessor nicht bekannt<br />

ist und die wahrscheinlich einen Fehler generieren wird, sobald die<br />

Anweisung an die Datenbankengine geschickt wurde.<br />

Fehlernummer Fehlertyp<br />

2628 Fehler<br />

Sie haben versucht, eine Embedded SQL-Anweisung zu löschen, die nicht<br />

existiert.<br />

Fehlernummer Fehlertyp<br />

2661 Warnung<br />

Sie haben eine SQL-Anweisung benutzt, die wahrscheinlich einen<br />

Syntaxfehler generieren wird, sobald sie an die Datenbankengine geschickt<br />

wurde.<br />

465


SQLPP-Fehler<br />

Erweiterung des Herstellers<br />

Mögliche Ursache<br />

466<br />

Fehlernummer Fehlertyp<br />

2666 Markierung (Warnung oder Fehler)<br />

Sie haben eine <strong>Adaptive</strong> Server <strong>Anywhere</strong>-Funktion verwendet, die von<br />

SQL/92 nicht definiert wurde, und mit den Parametern -ee, -ei, -ef, -we, -wi<br />

oder -wf im Präprozessor verarbeitet.<br />

Falsche Anzahl von Parametern <strong>für</strong> SQL-Funktion '%1'<br />

Mögliche Ursache<br />

Fehlernummer Fehlertyp<br />

2663 Warnung<br />

Sie haben eine SQL-Funktion mit der falschen Anzahl von Parametern<br />

verwendet. Dies wird wahrscheinlich einen Fehler generieren, sobald die<br />

Anweisung an die Datenbankengine gesendet wurde.


Index<br />

><br />

>><br />

Java in der Datenbank-Methoden, 77<br />

A<br />

a_backup_db, Struktur, 335<br />

a_change_log, Struktur, 337<br />

a_compress_db, Struktur, 339<br />

a_compress_stats, Struktur, 340<br />

a_create_db, Struktur, 341<br />

a_crypt_db, Struktur, 343<br />

a_db_collation, Struktur, 344<br />

a_db_info, Struktur, 345<br />

a_dblic_info, Struktur, 348<br />

a_dbtools_info, Struktur, 349<br />

a_name, Struktur, 351<br />

a_stats_line, Struktur, 352<br />

a_sync_db, Struktur, 352<br />

a_syncpub, Struktur, 355<br />

a_sysinfo, Struktur, 356<br />

a_table_info, Struktur, 356<br />

a_translate_log, Struktur, 357<br />

a_truncate_log, Struktur, 358<br />

a_validate_db, Struktur, 363<br />

a_validate_type, Aufzählungstyp, 369<br />

a_writefile, Struktur, 364<br />

Abfragen<br />

ADO-Recordset-Objekt, 377, 379<br />

einzelne Zeilen, 214<br />

Java in der Datenbank, 117<br />

JDBC, 169<br />

Abrollbare Cursor<br />

JDBC-Unterstützung, 145<br />

Abrollender Cursor, 23<br />

Abrufen<br />

Objekte, 174<br />

ODBC, 300<br />

SQLDA, 235<br />

ActiveX-Datenobjekte<br />

Info, 374<br />

ADO<br />

Abfragen, 377, 379<br />

Aktualisierungen, 379<br />

Befehle, 376<br />

Befehlsobjekt, 376<br />

Cursor, 28, 379<br />

Cursortypen, 26<br />

Einführung in die Programmierung, 3<br />

Info, 374<br />

Recordset-Objekt, 377, 379<br />

SQL-Anweisungen in Anwendungen verwenden,<br />

10<br />

Verbindungen, 374<br />

Verbindungsobjekt, 374<br />

Aggregatfunktionen<br />

Java in der Datenbank, Spalten, 120<br />

467


A–A<br />

Aktualisierungen<br />

Cursor, 379<br />

alloc_sqlda, Funktion, 253<br />

alloc_sqlda_noind, Funktion, 253<br />

ALTER DATABASE, Anweisung<br />

Java in der Datenbank, 99, 100<br />

an_erase_db, Struktur, 349<br />

an_expand_db, Struktur, 350<br />

an_unload_db, Struktur, 359<br />

an_upgrade_db, Struktur, 361<br />

Anforderungen<br />

abbrechen, 257<br />

Open Client-Anwendungen, 390<br />

Anforderungen abbrechen<br />

Embedded SQL, 247<br />

Anforderungsverarbeitung<br />

Embedded SQL, 247<br />

Anführungszeichen<br />

Java in der Datenbank, 78<br />

Angeführte Bezeichner<br />

SQL_needs_quotes-Funktion, 270<br />

Anregungen<br />

Dokumentation, xv<br />

Antwortdatei<br />

Definition, 422<br />

Anweisungen<br />

COMMIT, 52<br />

DELETE, positionsbasiert, 24<br />

INSERT, 12<br />

PUT, 24<br />

ROLLBACK, 52<br />

ROLLBACK TO SAVEPOINT, 52<br />

UPDATE, positionsbasiert, 24<br />

Anweisungs-Handle<br />

ODBC, 287<br />

Anwendungen<br />

bereitstellen, 426<br />

Bereitstellung, 411<br />

SQL, 10<br />

Anwendungen bereitstellen<br />

Embedded SQL, 433<br />

468<br />

Anwendungen mit mehreren Threads<br />

ODBC, 278, 293<br />

UNIX, 282<br />

Anwendungen mit Threadverarbeitung<br />

UNIX, 416<br />

Arbeitstabellen<br />

Cursor-Performance, 43<br />

Array, Abrufe<br />

Info, 218<br />

ARRAY, Klausel<br />

FETCH-Anweisung, 218<br />

asademo.db, Datei<br />

Info, xiv<br />

asajdbc.zip<br />

Datenbankserver bereitstellen, 438<br />

Laufzeitklassen, 97<br />

ASAJDBCDRV, JAR-Datei<br />

Info, 98<br />

ASAJRT, JAR-Datei<br />

Info, 98<br />

asajrt12.zip<br />

Laufzeitklassen, 97<br />

ASAJSystem, JAR-Datei<br />

Info, 98<br />

ASAProv<br />

OLE DB-Provider, 372<br />

Assistenten<br />

JAR- und ZIP-Datei erstellen, 105<br />

Java-Klasse hinzufügen, 104<br />

Neue Java-Klasse erstellen, 85, 161<br />

Upgrade einer Datenbank, Assistent, 101<br />

Attribute<br />

Java in der Datenbank, 133<br />

Auffüllen mit Leerzeichen, 367<br />

Aufzählungstypen<br />

DBTools-Schnittstelle, 367<br />

Ausführlichkeit, 367<br />

Auslagerbar<br />

Definition, 140<br />

Ausnahmen<br />

Java, 73


autocommit<br />

ODBC, 289<br />

steuern, 50<br />

AutoCommit<br />

JDBC, 164<br />

Autocommit, Modus<br />

Implementierung, 51<br />

Transaktionen, 49<br />

B<br />

Befehle<br />

ADO-Befehlsobjekt, 376<br />

Befehlsobjekt<br />

ADO, 376<br />

Beispieldatenbank<br />

Info über asademo.db, xiv<br />

Java in der Datenbank, 94<br />

Beispiele<br />

DBTools-Programm, 319<br />

Embedded SQL, 191<br />

Embedded SQL-Anwendungen, 190<br />

esqldll.c, 188<br />

ODBC, 285<br />

statische Cursor in Embedded SQL, 193<br />

Windows-Dienste, 286<br />

Benutzerdefinierte Klassen<br />

Java in der Datenbank, 76<br />

Berechnete Spalten<br />

Begrenzungen, 139<br />

erstellen, 137<br />

INSERT-Anweisung, 138<br />

Java in der Datenbank, 137<br />

Neuberechnungen, 139<br />

Trigger, 138<br />

UPDATE-Anweisung, 138<br />

Berechtigungen<br />

JDBC, 173<br />

Bereich<br />

Java, 72<br />

Bereitstellen<br />

Anwendungen, 426<br />

Datenbanken, 439<br />

Datenbanken auf CD-ROM, 439<br />

Datenbankserver, 438<br />

dbconsole, Dienstprogramm, 437<br />

eingebettete Datenbanken, 441<br />

Embedded SQL, 433<br />

Interactive SQL, 437<br />

Java in der Datenbank, 438<br />

jConnect, 435<br />

JDBC-Clients, 435<br />

JDBC-ODBC-Brücke, 435<br />

ODBC, 427<br />

ODBC-Treiber, 428<br />

OLE DB-Provider, 426<br />

Open Client, 436<br />

Personal Datenbankserver, 441<br />

schreibgeschützte Datenbanken, 439<br />

SQL Remote, 442<br />

<strong>Sybase</strong> Central, 437<br />

Verwaltungstools, 437<br />

Bereitstellung<br />

Dateistandorte, 415<br />

Datenbanken und Anwendungen, 411<br />

Info, 411<br />

InstallShield, 420<br />

Methoden, 412<br />

MobiLink-Synchronisationsserver, 422<br />

ohne Dialog, 422<br />

siehe auch Bereitstellung, Überblick, 412<br />

Write-Dateien, 418<br />

Beschreiben<br />

Ergebnismengen, 47<br />

Beständigkeit<br />

Java in den Datenbankklassen, 80<br />

Betriebssystem<br />

Dateinamen, 417<br />

Bezeichner<br />

Anführungszeichen nötig, 270<br />

Bibliotheken<br />

Embedded SQL, 185<br />

Bibliotheksfunktionen<br />

Embedded SQL, 253<br />

BINARY, Datentypen<br />

Embedded SQL, 201<br />

Bindevariable<br />

Info, 223<br />

B–B<br />

469


C–C<br />

Bindungsparameter<br />

vorbereitete Anweisungen, 13<br />

Bit-Felder<br />

Verwendung, 319<br />

BLOBs<br />

Embedded SQL, 237<br />

in Embedded SQL abrufen, 238<br />

in Embedded SQL senden, 240<br />

Block-Cursor, 22<br />

ODBC, 29<br />

Bookmarks<br />

ODBC-Cursor, 303<br />

Borland C++<br />

Unterstützung, 184<br />

Breite Ablagen, 218<br />

Bytecode<br />

Java-Klassen, 58<br />

C<br />

C, Programmiersprache<br />

Datentypen, 201<br />

Cache<br />

Java in der Datenbank, 140<br />

CALL, Anweisung<br />

embedded SQL, 243<br />

Callback, Funktionen<br />

Embedded SQL, 247<br />

registrieren, 261<br />

Callbacks<br />

DB_CALLBACK_DEBUG_MESSAGE, 262<br />

Catch, Block<br />

Java, 73<br />

CD-ROM<br />

Datenbanken bereitstellen, 439<br />

Chained, Modus<br />

Implementierung, 51<br />

steuern, 50<br />

Transaktionen, 49<br />

CHAINED, Option<br />

JDBC, 164<br />

470<br />

Class.forName, Methode<br />

jConnect laden, 152<br />

classes.zip<br />

Datenbankserver bereitstellen, 438<br />

Laufzeitklassen, 97<br />

CLASSPATH, Umgebungsvariable<br />

einrichten, 160<br />

Info, 82<br />

Java in der Datenbank, 82<br />

jConnect, 150<br />

Clientseitiges autocommit<br />

Info, 51<br />

CLOSE, Anweisung<br />

Info, 215<br />

com.sybase, Paket<br />

Laufzeitklassen., 97<br />

COMMIT, Anweisung<br />

Autocommit-Modus, 49, 50<br />

Cursor, 52<br />

JDBC, 164<br />

compareTo, Methode<br />

Objektvergleiche, 120<br />

Compiler<br />

unterstützte, 184<br />

COMPUTE, Klausel<br />

CREATE TABLE, 137<br />

CREATE DATABASE, Anweisung<br />

Java in der Datenbank, 99, 100<br />

CREATE PROCEDURE, Anweisung<br />

embedded SQL-Syntax, 243<br />

CS_CSR_ABS, 398<br />

CS_CSR_FIRST, 398<br />

CS_CSR_LAST, 398<br />

CS_CSR_PREV, 398<br />

CS_CSR_REL, 398<br />

CS_DATA_BOUNDARY, 398<br />

CS_DATA_SENSITIVITY, 398<br />

CS_PROTO_DYNPROC, 398<br />

CS_REG_NOTIF, 398


CS_REQ_BCP, 398<br />

ct_command, Funktion<br />

Open Client, 394, 396<br />

CT_CURSOR, Funktion<br />

Open Client, 395<br />

ct_dynamic, Funktion<br />

Open Client, 394<br />

ct_results, Funktion<br />

Open Client, 396<br />

ct_send, Funktion<br />

Open Client, 396<br />

Cursor, 29<br />

abbrechen, 25, 257<br />

abrollende, 23<br />

ADO, 28<br />

aktualisieren, 379, 396<br />

aktualisieren und löschen, 24<br />

anfordern, 27<br />

Arbeitstabellen, 43<br />

Beispiel C-Code, 190<br />

beschreiben, 47<br />

DYNAMIC SCROLL, 21, 26, 39<br />

Dynamisch, 37<br />

eindeutig, 26<br />

Einführung, 15<br />

Embedded SQL, 28, 215<br />

empfindlich, 37<br />

Empfindlichkeit, 30, 31<br />

Empfindlichkeit, Beispiele, 32, 34<br />

Ergebnismengen, 15<br />

Fat, 22<br />

Fetch-Vorgänge <strong>für</strong> mehrere Zeilen, 22<br />

Fetch-Vorgänge <strong>für</strong> Zeilen, 20, 22<br />

gespeicherte Prozeduren, 244<br />

Info, 15<br />

Interna, 30<br />

Isolationsstufe (isolation level), 21<br />

löschen, 396<br />

Mitgliedschaft, 30<br />

nicht-empfindlich, 39<br />

NO SCROLL, 26, 36<br />

ODBC, 28, 299<br />

ODBC-Aktualisierungen, 302<br />

ODBC-Bookmarks, 303<br />

ODBC-Cursor-Merkmale wählen, 299<br />

ODBC-Ergebnismengen, 300<br />

ODBC-Löschungen, 302<br />

OLE DB, 28<br />

Open Client, 395<br />

Performance, 43, 44<br />

Plattformen, 26<br />

positionieren, 20<br />

Reihenfolge, 30<br />

Savepoints, 52<br />

Schlüsselmengen-gesteuert, 40<br />

Schreibschutz, 26<br />

Schritt <strong>für</strong> Schritt, 17<br />

SCROLL, 26, 40<br />

sichtbare Änderungen, 31<br />

Statisch, 36<br />

Transaktionen, 52<br />

unbestimmte Empfindlichkeit, 39<br />

unempfindlich, 26, 36<br />

Verfügbarkeit, 26<br />

verwenden, 15, 20<br />

vorbereitete Anweisungen, 19<br />

Werte, 30<br />

wert-empfindlich, 40<br />

Cursor positionieren<br />

Fehlerbehandlung, 21<br />

D<br />

JDBCExamples.java, 144<br />

Dateien<br />

Namenskonventionen, 416<br />

Standorte <strong>für</strong> die Bereitstellung, 415<br />

Dateinamen<br />

Konventionen, 416<br />

Sprache, 417<br />

Versionsnummer, 416<br />

Daten abrufen<br />

Embedded SQL, 214<br />

Datenbankdesign<br />

Java in der Datenbank, 133<br />

Datenbankeigenschaften<br />

db_get_property-Funktion, 258<br />

Datenbanken<br />

bereitstellen, 439<br />

Java in der Datenbank, 133<br />

Java-aktivieren, 97, 99, 101<br />

URL, 153<br />

D–D<br />

471


D–D<br />

Datenbankoptionen<br />

<strong>für</strong> jConnect eingestellt, 154<br />

Datenbankserver<br />

bereitstellen, 438<br />

Funktionen, 267<br />

Datenbank-Tools, Schnittstelle<br />

a_backup_db-Struktur, 335<br />

a_change_log-Struktur, 337<br />

a_compress_db-Struktur, 339<br />

a_compress_stats-Struktur, 340<br />

a_create_db-Struktur, 341<br />

a_crypt_db-Struktur, 343<br />

a_db_collation-Struktur, 344<br />

a_db_info-Struktur, 345<br />

a_dblic_info-Struktur, 348<br />

a_dbtools_info-Struktur, 349<br />

a_name-Struktur, 351<br />

a_stats_line-Struktur, 352<br />

a_sync-db-Struktur, 352<br />

a_syncpub-Struktur, 355<br />

a_sysinfo-Struktur, 356<br />

a_table_info-Struktur, 356<br />

a_translate_log-Struktur, 357<br />

a_truncate_log-Struktur, 358<br />

a_validate_db-Struktur, 363<br />

a_validate_type-Aufzählungstypen, 369<br />

a_writefile-Struktur, 364<br />

an_erase_db-Struktur, 349<br />

an_expand_db-Struktur, 350<br />

an_unload_db-Struktur, 359<br />

an_upgrade_db-Struktur, 361<br />

Auffüllen mit Leerzeichen, 367<br />

Aufzählungstypen, 367<br />

Ausführlichkeit, 367<br />

DBBackup-Funktion, 323<br />

DBChangeLogName-Funktion, 323<br />

DBChangeWriteFile-Funktion, 324<br />

DBCollate-Funktion, 324<br />

DBCompress-Funktion, 325<br />

DBCreate-Funktion, 325<br />

DBCreateWriteFile-Funktion, 326<br />

DBCrypt-Funktion, 326<br />

DBErase-Funktion, 327<br />

DBExpand-Funktion, 327<br />

DBInfo, Funktion, 327<br />

DBInfoDump-Funktion, 328<br />

DBInfoFree-Funktion, 328<br />

DBLicense-Funktion, 329<br />

DBStatusWriteFile-Funktion, 329<br />

DBToolsFini-Funktion, 330<br />

472<br />

DBToolsInit-Funktion, 331<br />

DBToolsVersion-Funktion, 332<br />

dbtran_userlist_type-Aufzählungstyp, 368<br />

DBTranslateLog-Funktion, 332<br />

DBTruncateLog-Funktion, 332<br />

dbunload-Aufzählungstyp, 368<br />

DBUnload-Funktion, 333<br />

DBUpgrade-Funktion, 333<br />

DBValidate-Funktion, 334<br />

dbxtract, 333<br />

Info, 311<br />

Datentypen<br />

Bereiche, 392<br />

C-Datentypen, 201<br />

dynamische SQL, 228<br />

Embedded SQL, 196<br />

Hostvariable, 201<br />

Java in der Datenbank, 109<br />

Open Client, 391<br />

SQLDA, 230<br />

Zuordnung, 391<br />

Datentypkonvertierung<br />

Indikatorvariable, 206<br />

db_backup, Funktion<br />

Info, 247, 254<br />

DB_BACKUP_CLOSE_FILE, Parameter, 254<br />

DB_BACKUP_END, Parameter, 254<br />

DB_BACKUP_OPEN_FILE, Parameter, 254<br />

DB_BACKUP_READ_PAGE, Parameter, 254<br />

DB_BACKUP_READ_RENAME_LOG,<br />

Parameter, 254<br />

DB_BACKUP_START, Parameter, 254<br />

DB_CALLBACK_CONN_DROPPED, Callback-<br />

Parameter, 262<br />

DB_CALLBACK_DEBUG_MESSAGE, Callback-<br />

Parameter, 262<br />

DB_CALLBACK_FINISH, Callback-Parameter,<br />

262<br />

DB_CALLBACK_MESSAGE, Callback-Parameter,<br />

263<br />

DB_CALLBACK_START, Callback-Parameter,<br />

262


DB_CALLBACK_WAIT, Callback-Parameter, 262<br />

db_cancel_request, Funktion, 257<br />

Anforderungsverwaltung, 247<br />

db_delete_file, Funktion, 257<br />

db_find_engine, Funktion, 258<br />

db_fini, Funktion, 258<br />

db_fini_dll<br />

aufrufen, 188<br />

db_get_property, Funktion<br />

Info, 258<br />

db_init, Funktion, 259<br />

db_init_dll<br />

aufrufen, 188<br />

db_is_working, Funktion, 260<br />

Anforderungsverwaltung, 247<br />

db_locate_servers, Funktion, 260<br />

db_register_a_callback, Funktion, 261<br />

Anforderungsverwaltung, 247<br />

db_start_database, Funktion<br />

Info, 263<br />

db_start_engine, Funktion<br />

Info, 264<br />

db_stop_database, Funktion<br />

Info, 265<br />

db_stop_engine, Funktion<br />

Info, 266<br />

db_string_connect, Funktion<br />

Info, 267<br />

db_string_disconnect, Funktion<br />

Info, 267<br />

db_string_ping_server, Funktion<br />

Info, 268<br />

DBBackup, Funktion, 323<br />

DBChangeLogName, Funktion, 323<br />

DBChangeWriteFile, Funktion, 324<br />

DBCollate, Funktion, 324<br />

DBCompress, Funktion, 325<br />

D–D<br />

dbcon8.dll<br />

Datenbank-Dienstprogramme bereitstellen, 441<br />

Embedded SQL-Clients bereitstellen, 434<br />

ODBC-Clients bereitstellen, 428<br />

OLE DB-Clients bereitstellen, 426<br />

dbconsole, Dienstprogramm<br />

bereitstellen, 437<br />

DBCreate, Funktion, 325<br />

DBCreateWriteFile, Funktion, 326<br />

DBCrypt, Funktion, 326<br />

dbctrs8.dll<br />

Datenbankserver bereitstellen, 438<br />

dbeng8<br />

Datenbankserver bereitstellen, 438<br />

DBErase, Funktion, 327<br />

DBExpand, Funktion, 327<br />

dbextf.dll<br />

Datenbankserver bereitstellen, 438<br />

dbfile.dll<br />

SQL Remote bereitstellen, 442<br />

DBInfo, Funktion, 327<br />

DBInfoDump, Funktion, 328<br />

DBInfoFree, Funktion, 328<br />

dbinit (Dienstprogramm)<br />

Java in der Datenbank, 99, 100<br />

dbipx8.dll<br />

Embedded SQL-Clients bereitstellen, 434<br />

ODBC-Clients bereitstellen, 428<br />

dbjava8.dll<br />

Datenbankserver bereitstellen, 438<br />

dblgen8.dll<br />

Datenbank-Dienstprogramme bereitstellen, 441<br />

Datenbankserver bereitstellen, 438<br />

Embedded SQL-Clients bereitstellen, 434<br />

ODBC-Clients bereitstellen, 428<br />

OLE DB-Clients bereitstellen, 426<br />

SQL Remote bereitstellen, 442<br />

dblib8.dll<br />

Embedded SQL-Clients bereitstellen, 434<br />

Schnittstellenbibliothek, 182<br />

473


D–D<br />

DBLicense, Funktion, 329<br />

dbmapi.dll<br />

SQL Remote bereitstellen, 442<br />

dbmlsync, (Dienstprogramm)<br />

C API <strong>für</strong>, 352<br />

eigenes schreiben, 352<br />

dbodbc8.dll<br />

ODBC-Clients bereitstellen, 428<br />

dbodbc8.lib<br />

Windows CE ODBC-Importbibliothek, 282<br />

dbodbc8.so<br />

UNIX ODBC-Treiber, 283<br />

dboledb8.dll<br />

OLE DB-Clients bereitstellen, 426<br />

dboledba8.dll<br />

OLE DB-Clients bereitstellen, 426<br />

dbremote<br />

SQL Remote bereitstellen, 442<br />

dbserv8.dll<br />

Datenbankserver bereitstellen, 438<br />

dbsmtp.dll<br />

SQL Remote bereitstellen, 442<br />

dbsrv8<br />

Datenbankserver bereitstellen, 438<br />

DBStatusWriteFile, Funktion, 329<br />

DBSynchronizeLog, Funktion, 330<br />

dbtool8.dll<br />

Datenbank-Dienstprogramme bereitstellen, 441<br />

SQL Remote bereitstellen, 442<br />

Windows CE, 312<br />

DBTools, Schnittstelle<br />

beenden, 314<br />

Einführung, 312<br />

Info, 311<br />

starten, 314<br />

Verwendung, 314<br />

DBToolsFini, Funktion, 330<br />

DBToolsInit, Funktion, 331<br />

474<br />

DBTools-Schnittstelle<br />

Beispielprogramm, 319<br />

DBTools-Funktionen aufrufen, 315<br />

Funktionen, 323<br />

DBToolsVersion, Funktion, 332<br />

dbtran_userlist_type, Aufzählungstyp, 368<br />

DBTranslateLog, Funktion, 332<br />

DBTruncateLog, Funktion, 332<br />

dbunload, Aufzählungstyp, 368<br />

dbunload, Dienstprogramm<br />

eigenes schreiben, 359<br />

Header-Datei, 359<br />

DBUnload, Funktion, 333<br />

dbupgrad (Dienstprogramm)<br />

Java in der Datenbank, 100<br />

dbupgrad, (Dienstprogramm)<br />

Java in der Datenbank, 99<br />

DBUpgrade, Funktion, 333<br />

DBValidate, Funktion, 334<br />

dbvim.dll<br />

SQL Remote bereitstellen, 442<br />

dbwtsp8.dll<br />

Datenbank-Dienstprogramme bereitstellen, 441<br />

SQL Remote bereitstellen, 442<br />

dbxtract, (Dienstprogramm)<br />

Datenbank-Tools-Schnittstelle, 333<br />

dbxtract, Dienstprogramm<br />

eigenes schreiben, 359<br />

Header-Datei, 359<br />

DECIMAL, Datentyp<br />

Embedded SQL, 201<br />

DECL_BINARY, Makro, 201<br />

DECL_DECIMAL, Makro, 201<br />

DECL_FIXCHAR, Makro, 201<br />

DECL_LONGBINARY, Makro, 201<br />

DECL_LONGVARCHAR, Makro, 201<br />

DECL_VARCHAR, Makro, 201


DECLARE, Anweisung<br />

Info, 215<br />

Deklarationsabschnitt<br />

Info, 200<br />

Deklarieren<br />

Embedded SQL-Datentypen, 196<br />

Hostvariable, 200<br />

DELETE, Anweisung<br />

Java in der Datenbank-Objekte, 116<br />

positionsbasiert, 24<br />

DESCRIBE, Anweisung<br />

Info, 226<br />

mehrere Ergebnismengen, 246<br />

SQLDA-Felder, 230<br />

sqllen-Felder, 232<br />

sqltype-Feld, 232<br />

Deskriptoren<br />

Ergebnismengen beschreiben, 47<br />

Destruktoren<br />

Java, 72<br />

Dienste<br />

Beispielcode, 195, 286<br />

Windows, 286<br />

Dienstprogramme<br />

bereitstellen, 441<br />

Datenbank-Dienstprogramme bereitstellen, 441<br />

SQL-Präprozessor, 249<br />

DISTINCT, Schlüsselwort<br />

Java in der Datenbank, Spalten, 120<br />

Distributed Transaction Coordinator<br />

dreischichtige Datenverarbeitung, 403<br />

DLL-Eintrittspunkte, 253<br />

DLLs<br />

mehrere SQLCAs, 212<br />

Dokumentation<br />

Konventionen, xi<br />

Dokumentation zu SQL <strong>Anywhere</strong> Studio, viii<br />

Dreischichtige Datenverarbeitung<br />

Architektur, 401<br />

Distributed Transaction Coordinator, 403<br />

EAServer, 403<br />

Info, 399<br />

D–D<br />

Microsoft Transaction Server, 403<br />

Ressourcen-Manager, 402<br />

Ressourcen-Verteiler, 402<br />

verteilte Transaktionen, 402<br />

DT_BIGINT Embedded SQL, Datentyp, 196<br />

DT_BINARY Embedded SQL, Datentyp, 197<br />

DT_BIT Embedded SQL, Datentyp, 196<br />

DT_DATE Embedded SQL, Datentyp, 196<br />

DT_DECIMAL Embedded SQL, Datentyp, 196<br />

DT_DOUBLE Embedded SQL, Datentyp, 196<br />

DT_FIXCHAR Embedded SQL, Datentyp, 197<br />

DT_FLOAT Embedded SQL, Datentyp, 196<br />

DT_INT Embedded SQL, Datentyp, 196<br />

DT_LONGBINARY Embedded SQL, Datentyp,<br />

198<br />

DT_LONGVARCHAR Embedded SQL, Datentyp,<br />

197<br />

DT_SMALLINT Embedded SQL, Datentyp, 196<br />

DT_STRING, Datentyp, 271<br />

DT_TIME Embedded SQL, Datentyp, 196<br />

DT_TIMESTAMP Embedded SQL, Datentyp, 197<br />

DT_TIMESTAMP_STRUCT Embedded SQL,<br />

Datentyp, 198<br />

DT_TINYINT Embedded SQL, Datentyp, 196<br />

DT_UNSINT Embedded SQL, Datentyp, 196<br />

DT_UNSSMALLINT Embedded SQL, Datentyp,<br />

196<br />

DT_VARCHAR Embedded SQL, Datentyp, 197<br />

DT_VARIABLE Embedded SQL, Datentyp, 198,<br />

199<br />

DTC<br />

dreischichtige Datenverarbeitung, 403<br />

DYNAMIC SCROLL, Cursor<br />

Embedded SQL, 28<br />

Fehlerbehandlung, 21<br />

Info, 26, 39<br />

475


E–F<br />

Dynamische Cursor<br />

Beispiel, 193<br />

Info, 37<br />

ODBC, 28<br />

Dynamische SQL<br />

Info, 223<br />

SQLDA, 228<br />

E<br />

EAServer<br />

dreischichtige Datenverarbeitung, 403<br />

Komponenten-Transaktionsattribut, 408<br />

transaction coordinator, 407<br />

Verteilte Transaktionen, 407<br />

Eigenschaften<br />

db_get_property-Funktion, 258<br />

Einbeziehung<br />

verteilte Transaktionen, 402<br />

Eindeutige Cursor<br />

Info, 26<br />

Eindeutige Spalten<br />

Java in der Datenbank, Spalten, 120<br />

Eingebettete Datenbanken<br />

bereitstellen, 441<br />

Einstellen<br />

Werte mit SQLDA, 234<br />

Embedded SQL<br />

autocommit-Modus, 49, 50<br />

Befehlszusammenfassung, 272<br />

Beispielprogramm, 186<br />

Berechtigungen, 251<br />

Cursor, 28, 190, 215<br />

Cursortypen, 26<br />

Daten abrufen, 214<br />

Dynamische Anweisungen, 223<br />

Dynamische Cursor, 193<br />

Einführung, 4<br />

Entwicklung, 182<br />

Funktionen, 253<br />

Header-Dateien, 184<br />

Hostvariable, 200<br />

Importbibliotheken, 185<br />

Info, 181<br />

Kompilieren- und Verknüpfen-Prozess, 183<br />

476<br />

SQL-Anweisungen, 10<br />

statische Anweisungen, 223<br />

Zeichenfolgen, 251<br />

Zeilennummern, 251<br />

Empfindliche Cursor<br />

Beispiele <strong>für</strong> Aktualisieren, 34<br />

Beispiele <strong>für</strong> Löschen, 32<br />

Einführung, 31<br />

Embedded SQL, 28<br />

Info, 37<br />

Empfindlichkeit<br />

Beispiele <strong>für</strong> Aktualisieren, 34<br />

Beispiele <strong>für</strong> Löschen, 32<br />

Cursor, 30, 31<br />

Isolationsstufen und, 45<br />

Entitäten<br />

Java in der Datenbank, 133<br />

Ergebnismengen<br />

ADO-Recordset-Objekt, 377, 379<br />

Cursor, 15<br />

gespeicherte Prozeduren, 244<br />

Java in der Datenbank, Gespeicherte Prozeduren,<br />

125<br />

Java in der Datenbank, Methoden, 125<br />

Metadaten, 47<br />

ODBC, 299, 304<br />

ODBC abrufen, 300<br />

Open Client, 396<br />

verwenden, 20<br />

Escapezeichen<br />

Java in der Datenbank, 80<br />

SQL, 80<br />

EXEC SQL<br />

Entwicklung in Embedded SQL, 187<br />

EXECUTE, Anweisung, 223<br />

Gespeicherte Prozeduren in Embedded SQL, 243<br />

executeQuery, Methode<br />

Info, 169<br />

executeUpdate, JDBC-Methode, 14<br />

Info, 166<br />

F<br />

Fat Cursor, 22


Feedback<br />

geben, xv<br />

Fehler<br />

Codes, 208<br />

SQLCODE, 208<br />

sqlcode SQLCA-Feld, 208<br />

Fehlerbehandlung<br />

Cursor positionieren, 21<br />

Java, 73<br />

Java in der Datenbank, Methoden, 124<br />

ODBC, 306<br />

Fehlermeldungen<br />

Embedded SQL-Funktion, 271<br />

Felder<br />

Instanz, 67<br />

Java in der Datenbank, 66<br />

Klasse, 67<br />

private, 72<br />

protected, 72<br />

public, 72, 83<br />

Festschreiben<br />

Transaktionen aus ODBC, 289<br />

Fetch<br />

ODBC, 300<br />

FETCH, Anweisung<br />

dynamische Abfragen, 226<br />

Info, 214, 215<br />

mehrzeilig, 218<br />

weit, 218<br />

Fetch, Vorgänge<br />

abrollende Cursor, 23<br />

Beschränkungen, 20<br />

Cursor, 22<br />

Mehrere Zeilen, 22<br />

fill_s_sqlda, Funktion<br />

Info, 269<br />

fill_sqlda, Funktion<br />

Info, 269<br />

Finally, Block<br />

Java, 73<br />

FIXCHAR, Datentyp<br />

Embedded SQL, 201<br />

ForceStart, Verbindungsparameter<br />

db_start_engine, 265<br />

Format<br />

Java in der Datenbank, Objekte, 130<br />

free_filled, Funktion<br />

Info, 269<br />

free_sqlda, Funktion<br />

Info, 270<br />

free_sqlda_noind, Funktion<br />

Info, 270<br />

Funktionen<br />

DBTools, 323<br />

DBTools-Funktionen aufrufen, 315<br />

Embedded SQL, 253<br />

G<br />

Gemischte Cursor<br />

ODBC, 28<br />

Gespeicherte Prozeduren<br />

Embedded SQL, 243<br />

Ergebnismengen, 244<br />

in dynamischem SQL ausführen, 243<br />

in dynamischem SQL erstellen, 243<br />

INOUT-Parameter und Java, 127<br />

Java in der Datenbank, 125<br />

OUT-Parameter und Java, 127<br />

getConnection, Methode<br />

Instanzen, 164<br />

getObject, Methode<br />

verwenden, 176<br />

Gleichheit<br />

Java in der Datenbank-Objekte, 119<br />

GNU-Compiler<br />

Unterstützung, 184<br />

GRANT, Anweisung<br />

JDBC, 173<br />

Groß-/Kleinschreibung<br />

Java in der Datenbank und SQL, 78<br />

Java in der Datenbank, Datentypen, 109<br />

GROUP BY, Klausel<br />

Java in der Datenbank, Spalten, 120<br />

G–G<br />

477


H–I<br />

H<br />

Handles<br />

ODBC zuweisen, 288<br />

über ODBC, 287<br />

Header-Dateien<br />

Embedded SQL, 184<br />

ODBC, 280<br />

Heap-Größe<br />

Java in der Datenbank, 141<br />

Hintergrundverarbeitung<br />

Callback-Funktionen, 247<br />

Hinzufügen<br />

JAR-Dateien, 105<br />

Klassen <strong>für</strong> Java in der Datenbank, 104<br />

Hostvariable<br />

benutzen, 203<br />

Datentypen, 201<br />

deklarieren, 200<br />

Info, 200<br />

SQLDA, 230<br />

I<br />

Import, Anweisung<br />

Java, 71<br />

Java in der Datenbank, 81<br />

jConnect, 151<br />

Importbibliotheken<br />

Alternativen, 187<br />

DBTools, 314<br />

Einführung, 183<br />

Embedded SQL, 185<br />

NetWare, 188<br />

ODBC, 280<br />

Windows CE ODBC, 282<br />

INCLUDE, Anweisung<br />

SQLCA, 208<br />

Indikatorvariable<br />

Datentypkonvertierung, 206<br />

Info, 204<br />

kürzen, 206<br />

NULL, 205<br />

SQLDA, 230<br />

Zusammenfassungen der Werte, 206<br />

478<br />

Indizes<br />

Java in der Datenbank, 120, 130, 137<br />

INOUT, Parameter<br />

Java in der Datenbank, 127<br />

INSERT, Anweisung<br />

Java in der Datenbank, 112<br />

JDBC, 166, 168<br />

mehrzeilig, 218<br />

Objekte, 172<br />

Performance, 12<br />

weit, 218<br />

INSTALL, Anweisung<br />

Einführung, 76<br />

Klassenversionen, 132<br />

verwenden, 104, 105<br />

Installation<br />

ohne Dialog, 422<br />

Installationsprogramme<br />

Bereitstellung, 413<br />

Installieren<br />

JAR-Dateien in einer Datenbank, 105<br />

Java-Klassen in einer Datenbank, 103, 104<br />

InstallShield<br />

<strong>Adaptive</strong> Server <strong>Anywhere</strong>-Anwendungen<br />

bereitstellen, 420<br />

Bereitstellung ohne Dialog, 422<br />

Instanz, Felder<br />

Info, 67<br />

Instanz, Methoden<br />

Info, 68<br />

Instanzen<br />

Java-Klassen, 71<br />

Instanziert<br />

Definition, 71<br />

Interactive SQL<br />

bereitstellen, 437<br />

Isolationsstufen<br />

Anwendungen, 51<br />

Cursor, 21<br />

Cursorempfindlichkeit und, 45


J<br />

Jaguar<br />

EAServer, 407<br />

JAR- und ZIP-Datei erstellen<br />

verwenden, 105<br />

JAR, Dateien<br />

aktualisieren, 106<br />

hinzufügen, 105<br />

installieren, 103, 105<br />

Java, 71<br />

löschen, 116<br />

Versionen, 106<br />

Java<br />

Catch-Block, 73<br />

Destruktoren, 72<br />

Fehlerbehandlung, 73<br />

Finally-Block, 73<br />

JDBC, 144<br />

Klassen, 71<br />

Konstruktoren, 72<br />

Objekte abfragen, 174<br />

Schnittstellen, 73<br />

Try-Block, 73<br />

Java 2<br />

unterstützte Versionen, 75<br />

Java in der Datenbank<br />

Abfragen, 117<br />

API, 60, 75<br />

Beispiel-Tabellen, 94<br />

benutzen, 93<br />

bereitstellen, 438<br />

Beständigkeit, 80<br />

compareTo-Methode, 120<br />

Datenbankdesign, 133<br />

Datentypen, 109<br />

die Dokumentation verwenden, 55<br />

die wichtigsten Funktionen, 57<br />

eine Datenbank aktivieren, 99, 101<br />

einfügen, 112<br />

Einführung, 54, 64<br />

Escapezeichen, 80<br />

Fehler, Prozedur nicht gefunden, 124<br />

Felder, 66<br />

Fragen und Antworten, 57<br />

Heap-Größe, 141<br />

in der Datenbank aktivieren, 97<br />

Indizes, 120, 130<br />

Klassen installieren, 103<br />

Klassen kompilieren, 65<br />

Klassen löschen, 116<br />

Klassenversionen, 131<br />

Laufzeitklassen, 97<br />

Laufzeitumgebung, 75, 96<br />

main-Methode, 79, 123<br />

Methoden, 66<br />

Namensbereich, 141<br />

NULL, 109<br />

Objekte, 66<br />

Objekte einfügen, 114<br />

Objekte entladen und wieder laden, 132<br />

Objekte replizieren, 132<br />

Objekte vergleichen, 119<br />

Performance, 130<br />

Praktische Einführung, 84<br />

Primärschlüssel, 120<br />

Sicherheitsmanagement, Info, 128<br />

Spalten aktualisieren, 115<br />

Spalten berechnen, 137<br />

Spalten erstellen, 109<br />

Speicherfragen, 140<br />

Speicherung, 130<br />

Standardwerte, 109<br />

unterstützte Klassen, 61<br />

unterstützte Plattformen, 59<br />

Überblick, 94<br />

Version, 75<br />

Virtual Machine, 57, 58, 141<br />

Werte aktualisieren, 114<br />

Zeilen löschen, 116<br />

Java, Datentypen<br />

abrufen, 172<br />

einfügen, 172<br />

Java, gespeicherte Prozeduren<br />

Beispiel, 126<br />

Info, 125<br />

Java, Paket<br />

Laufzeitklassen., 97<br />

JAVA_HEAP_SIZE, Option, 141<br />

JAVA_NAMESPACE_SIZE, Option<br />

verwenden, 141<br />

Java-Klasse erstellen, Assistant<br />

verwenden, 85<br />

Java-Klasse hinzufügen, Assistant<br />

verwenden, 104, 161<br />

J–J<br />

479


K–K<br />

Java-Klassen<br />

Hinzufügen, 104<br />

installieren, 104<br />

Java-Sicherheitsmanagement<br />

Info, 129<br />

jcatalog.sql, Datei<br />

jConnect, 151<br />

jConnect<br />

CLASSPATH, Umgebungsvariable, 150<br />

Einrichtung der Datenbank, 151<br />

gelieferte Versionen, 150<br />

Info, 150<br />

JDBC-Clients bereitstellen, 435<br />

JDBC-Treiber wählen, 145<br />

laden, 152<br />

Pakete, 151<br />

Systemobjekte, 151<br />

URL, 152<br />

Verbindungen, 157, 161<br />

JDBC<br />

Arten der Benutzung, 144<br />

AutoCommit, 164<br />

Autocommit-Modus, 49, 50<br />

Beispiele, 144<br />

Berechtigungen, 173<br />

Bespiele, 157<br />

clientseitig, 149<br />

Client-Verbindungen, 157<br />

Cursortypen, 26<br />

Datenzugriff, 165<br />

Einführung, 5<br />

Info, 144<br />

INSERT-Anweisung, 166, 168<br />

jConnect, 150<br />

JDBC-Clients bereitstellen, 435<br />

Laufzeitklassen, 97<br />

Nicht-Standardklassen, 146, 147<br />

SELECT-Anweisung, 169<br />

serverseitig, 149<br />

serverseitige Verbindungen, 161<br />

SQL-Anweisungen, 10<br />

Standardwerte <strong>für</strong> die Verbindung, 164<br />

Überblick über die Anwendungen, 145<br />

verbinden, 157<br />

Verbindung mit einer Datenbank, 153<br />

Verbindungen, 149, 157<br />

Verbindungscode, 158<br />

Version, 75, 146, 147<br />

Version 2.0-Funktionen, 146, 147<br />

480<br />

Voraussetzungen, 144<br />

vorbereitete Anweisungen, 171<br />

JDBCExamples, Klasse<br />

Info, 165<br />

JDBC-ODBC-Brücke<br />

erforderliche Dateien, 155<br />

JDBC-Clients bereitstellen, 435<br />

JDBC-Treiber wählen, 145<br />

verbinden, 155<br />

verwenden, 155<br />

JDBC-Treiber<br />

Kompatibilität, 145<br />

Performance, 145<br />

wählen, 145<br />

jdemo.sql<br />

Beispieltabellen, 94<br />

JDK<br />

Definition, 60<br />

Version, 75, 97<br />

K<br />

Kapazitäten<br />

unterstützte, 398<br />

Klassen<br />

aktualisieren, 106<br />

als Datentypen, 109<br />

Beispiel, 111<br />

erstellen, 103<br />

importieren, 176<br />

Info, 64<br />

installieren, 103<br />

Instanzen, 71<br />

Java, 71<br />

kompilieren, 65<br />

Konstruktoren, 66<br />

Laufzeit, 75<br />

unterstützte, 61<br />

Versionen, 106<br />

Klassen, Felder<br />

Info, 67<br />

Klassen, Methoden<br />

Info, 68


Klauseln<br />

WITH HOLD, 21<br />

Kompilieren und Verknüpfen, Prozess, 183<br />

Komponenten<br />

Transaktionsattribut, 408<br />

Konsolendienstprogramm<br />

bereitstellen, 437<br />

Konstruktoren<br />

Daten einfügen, 113<br />

Info, 66<br />

Java, 72<br />

Konventionen<br />

Dateinamen, 416<br />

Dokumentation, xi<br />

Konvertierung<br />

Datentypen, 206<br />

Kürzen<br />

bei FETCH, 206<br />

FETCH-Anweisung, 206<br />

Indikatorvariable, 206<br />

L<br />

Laufzeitklassen<br />

Inhalt, 97<br />

installieren, 97<br />

Laufzeitklassen, Java in der Datenbank, 75<br />

Laufzeitumgebung<br />

Java in der Datenbank, 96<br />

length, SQLDA-Feld<br />

Info, 230, 232<br />

Lesezeichen, 29<br />

LONG BINARY, Datentyp<br />

Embedded SQL, 201, 237<br />

in Embedded SQL abrufen, 238<br />

in Embedded SQL senden, 240<br />

LONG VARCHAR, Datentyp<br />

Embedded SQL, 201, 237<br />

in Embedded SQL abrufen, 238<br />

in Embedded SQL senden, 240<br />

Löschen<br />

JAR-Dateien, 116<br />

Java-Klassen, 116<br />

M<br />

main, Methode<br />

Java in der Datenbank, 79, 123<br />

Makros<br />

_SQL_OS_NETWARE, 188<br />

_SQL_OS_UNIX, 188<br />

_SQL_OS_WINNT, 188<br />

manual commit, Modus<br />

Implementierung, 51<br />

steuern, 50<br />

Transaktionen, 49<br />

MAX, Funktion<br />

Java in der Datenbank, Spalten, 120<br />

Mehrere Ergebnismengen<br />

DESCRIBE-Anweisung, 246<br />

Mehrere Threads in Anwendungen<br />

Embedded SQL, 211<br />

Java in der Datenbank, 124<br />

Mehrfache Ergebnismengen<br />

ODBC, 304<br />

Mehrzeilige Abfragen<br />

Cursor, 215<br />

Mehrzeilige Abrufe, 218<br />

Mehrzeilige Einfügungen, 218<br />

Mehrzeiliges Speichern, 218<br />

Meldungen<br />

Callback, 263<br />

Server, 263<br />

println<br />

Java in der Datenbank, 79<br />

Methoden<br />

>>, 77<br />

deklarieren, 68<br />

Instanz, 68<br />

Java in der Datenbank, 66<br />

Klasse, 68<br />

private, 72<br />

L–M<br />

481


N–O<br />

protected, 72<br />

public, 72<br />

Punktoperator, 77<br />

statisch, 68<br />

void-Rückgabewert, 125<br />

Microsoft Transaction Server<br />

dreischichtige Datenverarbeitung, 403<br />

Microsoft Visual C++<br />

Unterstützung, 184<br />

MIN, Funktion<br />

Java in der Datenbank, Spalten, 120<br />

Mit Leerzeichen aufgefüllt<br />

Zeichenfolgen in Embedded SQL, 196<br />

Mitgliedschaft<br />

Ergebnismengen, 30<br />

mlxtract, Dienstprogramm<br />

eigenes schreiben, 359<br />

Header-Datei, 359<br />

MobiLink, Synchronisationsserver<br />

Bereitstellung, 422<br />

MSDASQL<br />

OLE DB-Provider, 372<br />

N<br />

name, SQLDA-Feld<br />

Info, 230<br />

Namensbereich<br />

Java in der Datenbank, 141<br />

NetWare<br />

Embedded SQL-Programme, 188<br />

Newsgroups<br />

technische Unterstützung, xv<br />

Nicht-empfindlicher Cursor<br />

Beispiele <strong>für</strong> Aktualisieren, 34<br />

Beispiele <strong>für</strong> Löschen, 32<br />

Einführung, 31<br />

Info, 39<br />

NLM<br />

Embedded SQL-Programme, 188<br />

482<br />

NO SCROLL, Cursor<br />

Embedded SQL, 28<br />

Info, 26, 36<br />

ntodbc.h<br />

Info, 280<br />

NULL<br />

Indikatorvariable, 204<br />

Java in der Datenbank, 109<br />

Nullabschlusszeichen <strong>für</strong> Zeichenfolge<br />

Embedded SQL-Datentyp, 196<br />

NULLWERT<br />

dynamische SQL, 228<br />

O<br />

Objekte<br />

abfragen, 174<br />

abrufen, 172<br />

einfügen, 172<br />

entladen und wieder laden, 132<br />

Java in der Datenbank, 66<br />

Klassenversionen, 131<br />

Replikation, 132<br />

Speicherformat, 107<br />

Speicherung von Java in der Datenbank, 130<br />

Typen, 66<br />

Objektorientierte Programmierung<br />

Java in der Datenbank, 70<br />

Stil, 83<br />

ODBC<br />

Abwärts-Kompatibilität, 279<br />

Anwendungen mit mehreren Threads, 293<br />

Autocommit-Modus, 49, 50<br />

Beispielanwendung, 289<br />

Beispielprogramm, 285<br />

bereitstellen, 427<br />

Cursor, 28, 299<br />

Cursortypen, 26<br />

Datenquellen, 431<br />

Einführung, 278<br />

Einführung in die Programmierung, 2<br />

Ergebnismengen, 304<br />

Fehlerprüfung, 306<br />

gespeicherte Prozeduren, 304<br />

Handles, 287<br />

Header-Dateien, 280


Importbibliotheken, 280<br />

kein Treiber-Manager, 284<br />

Kompatibilität, 279<br />

linken, 280<br />

mehrfache Ergebnismengen, 304<br />

programmieren, 277<br />

Registrierungseinträge, 431<br />

SQL-Anweisungen, 10<br />

Treiber bereitstellen, 428<br />

UNIX-Entwicklung, 282, 284<br />

unterstützte Version, 278<br />

Übereinstimmung, 278<br />

vorbereitete Anweisungen, 297<br />

Windows CE, 281, 282<br />

ODBC, Treiber<br />

UNIX, 283<br />

odbc.h<br />

Info, 280<br />

ODBC-Einstellungen<br />

bereitstellen, 428, 430<br />

OLE DB<br />

<strong>Adaptive</strong> Server <strong>Anywhere</strong>, 372<br />

Aktualisierungen, 379<br />

bereitstellen, 426<br />

Cursor, 28, 379<br />

Cursortypen, 26<br />

Einführung in die Programmierung, 3<br />

Info, 372<br />

ODBC und, 372<br />

Provider bereitstellen, 426<br />

unterstützte Plattformen, 372<br />

unterstützte Schnittstellen, 382<br />

OLE, Transaktionen<br />

dreischichtige Datenverarbeitung, 402<br />

Online-Sicherungen<br />

Embedded SQL-Funktionen, 247<br />

Open Client<br />

<strong>Adaptive</strong> Server <strong>Anywhere</strong>-Einschränkungen,<br />

398<br />

Anforderungen, 390<br />

autocommit-Modus, 49, 50<br />

Cursortypen, 26<br />

Datentypbereiche, 392<br />

Datentypen, 391<br />

Datentyp-Kompatibilität, 391<br />

Einführung, 6<br />

Open Client-Anwendungen bereitstellen, 436<br />

SQL, 394<br />

SQL-Anweisungen, 10<br />

OPEN, Anweisung<br />

Info, 215<br />

OpenClient<br />

Einschränkungen, 398<br />

Schnittstelle, 389<br />

ORDER BY, Klausel<br />

Java in der Datenbank, Spalten, 120<br />

OUT, Parameter<br />

Java in der Datenbank, 127<br />

P<br />

Pakete<br />

installieren, 105<br />

Java, 71<br />

Java in der Datenbank, 81<br />

jConnect, 151<br />

Performance<br />

Cursor, 43, 44<br />

Java in der Datenbank, Werte, 130<br />

JDBC, 171<br />

JDBC-Treiber, 145<br />

vorbereitete Anweisungen, 12, 297<br />

Personal Server<br />

bereitstellen, 441<br />

Plattenspeicher<br />

Java in der Datenbank, Werte, 130<br />

Plattformen<br />

Cursor, 26<br />

Java in der Datenbank, 59<br />

Platzhalter<br />

dynamische SQL, 223<br />

Positionsbasierte Lösch-Vorgänge, 24<br />

Positionsbasierte Updates<br />

Info, 21<br />

Positionsbasierte Update-Vorgänge, 24<br />

Präprozessor<br />

ausführen, 184<br />

Info, 182<br />

P–P<br />

483


Q–R<br />

Prefetch<br />

Cursor, 44<br />

Cursor-Performance, 43<br />

PREFETCH, Option<br />

Cursor, 44<br />

Prefetch-Vorgänge<br />

mehrere Zeilen abrufen, 22<br />

PREPARE TRANSACTION, Anweisung<br />

und OpenClient, 398<br />

PREPARE, Anweisung, 223<br />

PreparedStatement, Klasse<br />

setObject-Methode, 114<br />

PreparedStatement, Schnittstelle<br />

Info, 171<br />

prepareStatement, Methode, 14<br />

Primärschlüssel<br />

Java in der Datenbank, Spalten, 120<br />

Private<br />

Java-Zugriff, 72<br />

Programmeinstiegspunkte<br />

DBTools-Funktionen aufrufen, 315<br />

Programmstruktur<br />

Embedded SQL, 187<br />

Protected<br />

Java, 71<br />

Java-Zugriff, 72<br />

Prozedur nicht gefunden, Fehlermeldung<br />

Java-Methoden, 168<br />

Prozeduren<br />

Embedded SQL, 243<br />

Ergebnismengen, 244<br />

ODBC, 304<br />

Public<br />

Java-Zugriff, 72<br />

Public, Felder<br />

Wichtiges, 83<br />

Punkt-Operator<br />

Java und SQL, 77<br />

PUT, Anweisung, 24<br />

mehrzeilig, 218<br />

weit, 218<br />

484<br />

PUT, Vorgang, 24<br />

Q<br />

QUOTED_IDENTIFIER, Option<br />

jConnect-Einstellung, 154<br />

R<br />

Recordset-Objekt<br />

ADO, 377, 379<br />

Registrierung<br />

bereitstellen, 428, 430<br />

ODBC, 431<br />

REMOTEPWD<br />

verwenden, 153<br />

Replikation<br />

Java in der Datenbank, Objekte, 132<br />

Reservierte Wörter<br />

SQL und Java in der Datenbank, 81<br />

Ressourcen-Manager<br />

dreischichtige Datenverarbeitung, 402<br />

Info, 400<br />

Ressourcen-Verteiler<br />

dreischichtige Datenverarbeitung, 402<br />

ROLLBACK TO SAVEPOINT, Anweisung<br />

Cursor, 52<br />

ROLLBACK, Anweisung<br />

Cursor, 52<br />

rt.jar<br />

Laufzeitklassen, 97<br />

Rückgabecodes, 316<br />

ODBC, 306<br />

Rückrufe<br />

DB_CALLBACK_CONN_DROPPED, 262<br />

DB_CALLBACK_FINISH, 262<br />

DB_CALLBACK_MESSAGE, 263<br />

DB_CALLBACK_START, 262<br />

DB_CALLBACK_WAIT, 262


S<br />

Savepoints<br />

Cursor, 52<br />

Schlüsselmengen-gesteuerte Cursor<br />

Info, 40<br />

ODBC, 28<br />

Schlüsselwörter<br />

SQL und Java in der Datenbank, 81<br />

Schnittstelle<br />

Java, 73<br />

Schnittstellenbibliothek<br />

Dateiname, 182<br />

dynamisch laden, 187<br />

Info, 182<br />

Schreibgeschützte Cursor<br />

Info, 26<br />

Schreibschutz<br />

Datenbanken bereitstellen, 439<br />

SCROLL, Cursor<br />

Embedded SQL, 28<br />

Info, 26, 40<br />

SecurityManager, Klasse<br />

Info, 128, 129<br />

SELECT, Anweisung<br />

dynamisch, 226<br />

einzelne Zeilen, 214<br />

Java in der Datenbank, 117<br />

JDBC, 169<br />

Objekte, 172<br />

Serialisierung<br />

Java in der Datenbank, Objekte, 130<br />

Objekte, 175<br />

Objekte in Tabellen, 107<br />

verteilte Datenverarbeitung, 176<br />

Server<br />

suchen, 268<br />

Serveradressen<br />

Embedded SQL-Funktion, 258<br />

setAutocommit, Methode<br />

Info, 164<br />

setObject, Methode<br />

verwenden, 176<br />

Setup-Programm<br />

dialogfreie Installation, 422<br />

Sicherheit<br />

Java in der Datenbank, 128, 129<br />

Sicherungen<br />

DBBackup, DBTools-Funktion, 323<br />

DBTools-Beispiel, 319<br />

Embedded SQL-Funktionen, 247<br />

Sichtbare Änderungen<br />

Cursor, 31<br />

Software<br />

Rückgabecode, 316<br />

Sortieren<br />

Java in der Datenbank-Objekte, 119<br />

sp_tsql_environment, Systemprozedur<br />

Optionen <strong>für</strong> jConnect einstellen, 154<br />

Spalten<br />

Java in der Datenbank aktualisieren, 114<br />

Java in der Datenbank, Datentypen, 109<br />

Speicher<br />

Java in der Datenbank, 140<br />

Speicherung<br />

Java in der Datenbank, Objekte, 130<br />

Sprachen<br />

Dateinamen, 417<br />

Sprachen-DLL<br />

erhalten, 417<br />

spt_mda, gespeicherte Prozedur<br />

Optionen <strong>für</strong> jConnect einstellen, 154<br />

SQL<br />

ADO-Anwendungen, 10<br />

Anwendungen, 10<br />

Embedded SQL-Anwendungen, 10<br />

JDBC-Anwendungen, 10<br />

ODBC-Anwendungen, 10<br />

Open Client-Anwendungen, 10<br />

SQL <strong>Anywhere</strong> Studio<br />

Dokumentation, viii<br />

SQL Remote<br />

bereitstellen, 442<br />

Java in der Datenbank, Objekte, 132<br />

S–S<br />

485


S–S<br />

SQL, Kommunikationsbereich<br />

Info, 208<br />

SQL/92<br />

SQL-Präprozessor, 250<br />

SQL_ATTR_MAX_LENGTH, Attribut<br />

Info, 300<br />

SQL_CALLBACK, Typendeklaration, 261<br />

SQL_CALLBACK_PARM, Typendeklaration, 261<br />

SQL_ERROR<br />

ODBC-Rückgabewert, 306<br />

SQL_INVALID_HANDLE<br />

ODBC-Rückgabewert, 306<br />

SQL_NEED_DATA<br />

ODBC-Rückgabewert, 306<br />

sql_needs_quotes, Funktion<br />

Info, 270<br />

SQL_NO_DATA_FOUND<br />

ODBC-Rückgabewert, 306<br />

SQL_SUCCESS<br />

ODBC-Rückgabewert, 306<br />

SQL_SUCCESS_WITH_INFO<br />

ODBC-Rückgabewert, 306<br />

SQL92<br />

SQL-Präprozessor, 250<br />

SQLAllocHandle, ODBC-Funktion<br />

Anweisungen ausführen, 294<br />

Info, 287<br />

Parameter binden, 295<br />

verwenden, 288<br />

SQL-Anweisungen<br />

ausführen, 394<br />

SQLBindCol, ODBC-Funktion<br />

Info, 299, 300<br />

SQLBindParameter, ODBC-Funktion, 14<br />

gespeicherte Prozeduren, 304<br />

Info, 295<br />

Vorbereitete Anweisungen, 297<br />

SQLBrowseConnect, ODBC-Funktion<br />

Info, 290<br />

486<br />

SQLCA<br />

ändern, 211<br />

Felder, 208<br />

Info, 208<br />

Länge von, 208<br />

mehrere, 211, 212<br />

Threads, 211<br />

sqlcabc SQLCA, Feld<br />

Info, 208<br />

sqlcaid<br />

SQLCA-Feld, 208<br />

sqlcode SQLCA, Feld<br />

Info, 208<br />

SQLConnect, ODBC-Funktion<br />

Info, 290<br />

SQLCOUNT<br />

sqlerror SQLCA-Feldelement, 209<br />

sqld, SQLDA-Feld<br />

Info, 229<br />

SQLDA<br />

Deskriptoren, 48<br />

Felder, 229<br />

freigeben, 269<br />

füllen, 269<br />

Hostvariable, 230<br />

Info, 223, 228<br />

sqllen-Felder, 232<br />

Zeichenfolgen, 269<br />

zuweisen, 253<br />

sqlda_storage, Funktion<br />

Info, 271<br />

sqlda_string_length, Funktion<br />

Info, 271<br />

sqldabc, SQLDA-Feld<br />

Info, 229<br />

sqldaif, SQLDA-Feld<br />

Info, 229<br />

sqldata, SQLDA-Feld<br />

Info, 230<br />

sqldef.h<br />

Datentypen, 196<br />

SQLDriverConnect, ODBC-Funktion<br />

Info, 290


sqlerrd SQLCA, Feld<br />

Info, 209<br />

sqlerrmc SQLCA, Feld<br />

Info, 209<br />

sqlerrml SQLCA, Feld<br />

Info, 209<br />

sqlerror SQLCA, Feld<br />

Elemente, 209<br />

SQLCOUNT, 209<br />

SQLIOCOUNT, 209<br />

SQLIOESTIMATE, 211<br />

SQLError, ODBC-Funktion<br />

Info, 306<br />

sqlerror_message, Funktion<br />

Info, 271<br />

sqlerrp SQLCA, Feld<br />

Info, 209<br />

SQLExecDirect, ODBC-Funktion<br />

gebundene Parameter, 295<br />

Info, 294<br />

SQLExecute, ODBC-Funktion, 14<br />

SQLExtendedFetch, ODBC-Funktion<br />

gespeicherte Prozeduren, 304<br />

Info, 300<br />

SQLFetch, ODBC-Funktion<br />

gespeicherte Prozeduren, 304<br />

Info, 300<br />

SQLFreeHandle, ODBC-Funktion<br />

verwenden, 288<br />

SQLFreeStmt, ODBC-Funktion, 14<br />

SQLGetData, ODBC-Funktion<br />

Info, 299, 300<br />

sqlind, SQLDA-Feld<br />

Info, 230<br />

SQLIOCOUNT<br />

sqlerror SQLCA-Feldelement, 209<br />

SQLIOESTIMATE<br />

sqlerror SQLCA-Feldelement, 211<br />

SQLJ, Standards<br />

Info, 54<br />

sqllen, SQLDA-Feld<br />

DESCRIBE-Anweisung, 232<br />

Info, 230, 232<br />

Werte abrufen, 235<br />

Werte beschreiben, 232<br />

Werte senden, 234<br />

sqlname, SQLDA-Feld<br />

Info, 230<br />

SQLNumResultCols, ODBC-Funktion<br />

gespeicherte Prozeduren, 304<br />

SQLPP<br />

Befehlszeile, 249<br />

Info, 182<br />

SQL-Präprozessor<br />

ausführen, 184<br />

Befehlszeile, 249<br />

Info, 249<br />

SQLPrepare, ODBC-Funktion, 14<br />

Info, 297<br />

SQLRETURN<br />

Typ des ODBC-Rückgabewertes, 306<br />

SQLSetConnectAttr, ODBC-Funktion<br />

Info, 292<br />

SQLSetPos, ODBC-Funktion<br />

Info, 302<br />

SQLSetStmtAttr, ODBC-Funktion<br />

Cursor-Merkmale, 299<br />

sqlstate SQLCA, Feld<br />

Info, 209<br />

SQLtransact, ODBC-Funktion<br />

Info, 289<br />

sqltype, SQLDA-Feld<br />

DESCRIBE-Anweisung, 232<br />

Info, 230<br />

sqlvar, SQLDA-Feld<br />

Info, 229, 230<br />

Inhalt, 230<br />

sqlwarn SQLCA, Feld<br />

Info, 209<br />

Standardausgabe<br />

Java in der Datenbank, 79<br />

S–S<br />

487


T–U<br />

Standards<br />

SQLJ, 54<br />

Standardwerte<br />

Java in der Datenbank, 109<br />

START JAVA, Anweisung<br />

verwenden, 141<br />

Starten<br />

Datenbanken unter Verwendung von jConnect,<br />

153<br />

Statische Methoden<br />

Info, 68<br />

Statische SQL<br />

Info, 223<br />

Statischer Cursor<br />

Info, 36<br />

ODBC, 28<br />

STOP JAVA, Anweisung<br />

verwenden, 141<br />

Strukturverdichten<br />

Header-Dateien, 184<br />

sun, Paket<br />

Laufzeitklassen., 97<br />

<strong>Sybase</strong> Central<br />

bereitstellen, 437<br />

Datenbnak <strong>für</strong> Java aktivieren, 101<br />

JAR-Dateien hinzufügen, 105<br />

Java-Klassen hinzufügen, 104<br />

ZIP-Dateien hinzufügen, 105<br />

sybase.sql, Paket<br />

Laufzeitklassen., 97<br />

sybase.sql.ASA, Paket<br />

JDBC 2.0-Funktionen, 147<br />

<strong>Sybase</strong>-Laufzeitklassen <strong>für</strong> Java<br />

Info, 97<br />

Symbole<br />

in Handbüchern, xii<br />

System Management Server<br />

Systemeinführung, 424<br />

Systemeinführung<br />

ODBC-Einstellungen, 428, 430<br />

Registrierungseinstellungen, 428, 430<br />

System Management Server, 424<br />

488<br />

T<br />

Technische Unterstützung<br />

Newsgroups, xv<br />

this<br />

Java in der Datenbank, Methoden, 125<br />

-gn, Option, 124<br />

Threads<br />

Embedded SQL, 211<br />

Java in der Datenbank, 124<br />

ODBC, 278<br />

ODBC-Anwendungen, 293<br />

UNIX-Entwicklung, 282<br />

TIMESTAMP, Datentyp<br />

Konvertierung, 392<br />

Transaction coordinator<br />

EAServer, 407<br />

Transaktionen<br />

Anwendungsentwicklung, 49<br />

Autocommit-Modus, 49, 50<br />

Cursor, 52<br />

Isolationsstufe, 51<br />

ODBC, 289<br />

verteilt, 400, 405<br />

Transaktionsattribut<br />

Komponente, 408<br />

Try, Block<br />

Java, 73<br />

Typen<br />

Objekte, 66<br />

U<br />

Umgebungs-Handle<br />

ODBC, 287<br />

Unchained, Modus<br />

Implementierung, 51<br />

steuern, 50<br />

Transaktionen, 49<br />

Unempfindliche Cursor<br />

Beispiele <strong>für</strong> Aktualisieren, 34<br />

Beispiele <strong>für</strong> Löschen, 32<br />

Einführung, 31


Embedded SQL, 28<br />

Info, 36<br />

Unempfindlicher Cursor<br />

Info, 26<br />

Unicode<br />

ODBC, 281<br />

Windows CE, 281<br />

UNIX<br />

Anwendungen mit mehreren Threads, 416<br />

Hinweise zu Bereitstellungsmethoden, 415<br />

ODBC, 282, 283<br />

ODBC-Anwendung, 284<br />

Verzeichnisstruktur, 415<br />

unixodbc.h<br />

Info, 280<br />

Unterstützte Plattformen<br />

OLE DB, 372<br />

Unterstützung<br />

Newsgroups, xv<br />

UPDATE, Anweisung<br />

Java in der Datenbank, 114<br />

positionsbasiert, 24<br />

set-Methoden, 115<br />

Upgrade einer Datenbank, Assistant<br />

Datenbank <strong>für</strong> Java aktivieren, 101<br />

URL<br />

Datenbank, 153<br />

jConnect, 152<br />

Ü<br />

Überlauffehler<br />

Datentyp-Konvertierung, 392<br />

V<br />

VARCHAR, Datentyp<br />

Embedded SQL, 201<br />

Veraltete Java-Klassen<br />

Info, 75<br />

Verbindungen<br />

ADO-Verbindungsobjekt, 374<br />

Funktionen, 267<br />

jConnect, 153<br />

jConnect-URL, 152<br />

JDBC, 149<br />

JDBC im Server, 161<br />

JDBC-Beispiel, 157, 161<br />

JDBC-Client-Anwendungen, 157<br />

JDBC-Standardwerte, 164<br />

ODBC, programmieren, 291<br />

ODBC-Attribute, 292<br />

ODBC-Funktionen, 290<br />

Verbindungs-Handle<br />

ODBC, 287<br />

Verbindungsobjekt<br />

ADO, 374<br />

Verfügbarkeit<br />

Verbindungen, 262<br />

Verschlüsselung<br />

DBTools-Schnittstelle, 326<br />

Version<br />

Java in der Datenbank, 75<br />

JDBC, 75<br />

JDK, 75<br />

Versionen<br />

Klassen, 131<br />

Versionsnummer<br />

Dateinamen, 416<br />

Verteilte Anwendungen<br />

Beispiele, 176<br />

Info, 174<br />

Voraussetzungen, 174<br />

Verteilte Transaktionen<br />

Architektur, 402, 404<br />

dreischichtige Datenverarbeitung, 402<br />

EAServer, 407<br />

Einbeziehung, 402<br />

Info, 399, 400, 405<br />

Wiederherstellung, 406<br />

Verzeichnisstruktur<br />

UNIX, 415<br />

Visual C++<br />

Unterstützung, 184<br />

Ü–V<br />

489


W–<br />

VM<br />

Java Virtual Machine, 58<br />

starten, 141<br />

stoppen, 141<br />

void<br />

Java in der Datenbank, Methoden, 66, 125<br />

Vorbereiten<br />

zum Festschreiben, 403<br />

Vorbereitete Anweisungen<br />

Bindungsparameter, 13<br />

Cursor, 19<br />

Java in der Datenbank, Objekte, 114<br />

JDBC, 171<br />

löschen, 13<br />

ODBC, 297<br />

Open Client, 394<br />

verwenden, 12<br />

W<br />

Watcom C/C++<br />

Unterstützung, 184<br />

Weite Abrufe, 22<br />

Info, 218<br />

Weite Einfügungen, 218<br />

Wert-empfindlicher Cursor<br />

Beispiele <strong>für</strong> Aktualisieren, 34<br />

Beispiele <strong>für</strong> Löschen, 32<br />

Einführung, 31<br />

Info, 40<br />

Wiederherstellung<br />

verteilte Transaktionen, 406<br />

490<br />

Windows CE<br />

dbtool8.dll, 312<br />

Java in der Datenbank nicht unterstützt, 59<br />

ODBC, 281, 282<br />

OLE DB, 372<br />

unterstützte Versionen, 372<br />

Windows-Dienste<br />

Beispielcode, 195<br />

WITH HOLD, Klausel<br />

Cursor, 21<br />

Write-Dateien<br />

bereitstellen, 418<br />

Z<br />

Zeichenfolgen, 251<br />

Datentyp, 271<br />

DT_STRING wird mit Leerzeichen aufgefüllt,<br />

196<br />

Java in der Datenbank, 78<br />

Zeichensatzkonvertierung<br />

JDBC-ODBC-Brücke, 156<br />

Zeilenlänge<br />

SQL-Präprozessor-Ausgabe, 250<br />

Zeilennummern<br />

SQL-Präprozessor, 251<br />

Zip, Dateien<br />

Java, 71<br />

Zugriffsmodifizierer<br />

Java, 72<br />

Zwei-Phasen-Commit<br />

dreischichtige Datenverarbeitung, 402, 403<br />

und OpenClient, 398

Hurra! Ihre Datei wurde hochgeladen und ist bereit für die Veröffentlichung.

Erfolgreich gespeichert!

Leider ist etwas schief gelaufen!