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