Adaptive Server® Anywhere Handbuch für Programmierer - Sybase
Adaptive Server® Anywhere Handbuch für Programmierer - Sybase
Adaptive Server® Anywhere Handbuch für Programmierer - Sybase
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