Unter Embedded SQL versteht man die Einbettung von SQL-Befehlen innerhalb eines Anwendungsprogramms. Das Anwendungsprogramm heißt Host Programm, die in ihm verwendete Sprache heißt Host-Sprache.
Der Microsoft SQL-Server unterstützt Embedded SQL im Zusammenspiel mit den Programmiersprachen C und C++ durch einen Pre-Compiler. Abbildung 9.9 zeigt den prinzipiellen Ablauf: Das mit eingebetteten SQL-Statements formulierte Host-Programm beispiel.sqc wird zunächst durch den Pre-Compiler unter Verwendung von SQL-spezifischen Include-Dateien in ein ANSI-C-Programm beispiel.c überführt. Diese Datei übersetzt ein konventioneller C-Compiler unter Verwendung der üblichen C-Include-Files in ein Objekt-File beispiel.o. Unter Verwendung der Runtime Library wird daraus das ausführbare Programm beispiel.exe gebunden.
Listing 9.2 zeigt ein Embedded-SQL-Programm, die davon erzeugte Ausgabe zeigt Abb. 9.10.
Eingebettete SQL-Statements werden durch ein vorangestelltes EXEC SQL gekennzeichnet und ähneln ansonsten ihrem interaktiven Gegenstück. Die Kommunikation zwischen dem Host-Programm und der Datenbank geschieht über sogenannte Host-Variablen, die im C-Programm deklariert werden. Eine Input-Host-Variable überträgt Daten des Hostprogramms an die Datenbank, eine Output-Host-Variable überträgt Datenbankwerte und Statusinformationen an das Host-Programm. Hostvariablen werden innerhalb von SQL-Statements durch einen vorangestellten Doppelpunkt (:) gekennzeichnet.
Für Hostvariablen, die Datenbankattributen vom Typ VARCHAR entsprechen, empfiehlt sich eine Definition nach folgendem Beispiel:
char fachgebiet[20];Mit einer Hostvariable kann eine optionale Indikator-Variable assoziiert sein, welche Null-Werte überträgt oder entdeckt. Folgende Zeilen definieren alle Hostvariablen zum Aufnehmen eines Datensatzes der Tabelle Professoren sowie eine Indikator-Variable raum_ind zum Aufnehmen von Status-Information zur Raumangabe.
int persnr; char name [20]; char rang [3]; int raum; short raum_ind;Folgende Zeilen transferieren einen einzelnen Professoren-Datensatz in die Hostvariablen persnr, name, rang, raum und überprüfen mit Hilfe der Indikator-Variable raum_ind, ob eine Raumangabe vorhanden war.
EXEC SQL SELECT PersNr, Name, Rang, Raum
INTO :persnr, :name, :rang, :raum INDICATOR :raum_ind
FROM Professoren
WHERE PersNr = 2125;
if (raum_ind == -1) printf("PersNr %d ohne Raum \n", persnr);
Oft liefert eine SQL-Query kein skalares Objekt
zurück, sondern eine Menge von Zeilen. Diese Treffer
werden in einer sogenannten private SQL area verwaltet
und mit Hilfe eines Cursors
sequentiell verarbeitet.
EXEC SQL DECLARE C1 CURSOR FOR
SELECT PersNr, Name, Rang, Raum
FROM Professoren
WHERE Rang='C4';
EXEC SQL OPEN C1;
EXEC SQL FETCH C1 into :persnr, :name, :rang, :raum
while (SQLCODE ==0){
printf("Verarbeite Personalnummer %d\n", persnr);
EXEC SQL FETCH C1 into :persnr, :name, :rang, :raum
}
EXEC SQL CLOSE C1;
#include <stddef.h> // Standardheader
#include <stdio.h> // Standardheader
void ErrorHandler (void) { // im Fehlerfalle
printf("%li %li %li\n", SQLCODE, SQLERRD1, SQLERRMC); // Ausgabe von
} // Fehlermeldungen
int main ( int argc, char** argv, char** envp) {
EXEC SQL BEGIN DECLARE SECTION; // Deklarationen-Start
char server[] = "arnold.uni"; // Server + DB
char loginPasswort[] = "erika.mustermann"; // User + Passwort
int persnr; // Personalnummer
char name[20]; // Name
char rang[3]; // Rang
int raum; // Raum
char gebdatum[17]; // Geburtsdatum
short raum_ind; // Raum-Indikator
char eingaberang[3]; // Eingabe vom User
EXEC SQL END DECLARE SECTION; // Deklarationen-Ende
EXEC SQL WHENEVER SQLERROR CALL ErrorHandler(); // Fehlermarke
EXEC SQL CONNECT TO :server USER :loginPasswort; // Verbindung aufbauen
if (SQLCODE == 0) printf("Verbindung aufgebaut!\n");// Erfolg
else { printf("Keine Verbindung\n"); return (1); } // Misserfolg
printf("Bitte Rang eingeben: "); // gewuenschten Rang
scanf("%s", eingaberang); // vom user holen
printf("Mit Rang %s gespeichert:\n", eingaberang);
EXEC SQL DECLARE C1 CURSOR FOR // Cursor vereinbaren
SELECT PersNr, Name, Rang, Raum, Gebdatum // SQL-Statement
FROM Professoren
WHERE Rang = :eingaberang;
EXEC SQL OPEN C1; // Cursor oeffnen
EXEC SQL FETCH C1 INTO :persnr, :name, :rang, // Versuche eine Zeile
:raum INDICATOR :raum_ind, :gebdatum; // zu lesen
while (SQLCODE == 0){ // SOLANGE erfolgreich
printf("%d %s %s", persnr, name, rang); // Tupel ausgeben
if(raum_ind == -1) printf(" ???"); // Platzhalter drucken
else printf("%4d", raum); // SONST Raumnr
printf(" %s\n", gebdatum); // letztes Attribut
EXEC SQL FETCH C1 INTO :persnr, :name, :rang, // naechste Zeile lesen
:raum INDICATOR :raum_ind, :gebdatum;
}
EXEC SQL CLOSE C1; // Cursor schliessen
EXEC SQL DISCONNECT ALL; // Verbindung beenden
return (0);
}
|
vom Präprozessor aus beispiel.sqc erzeugtes C-Programm beispiel.c