Home

Grundsätzliches
Installation
Konfiguration
Erste Schritte
Laufzeitschalter
Textdateien
Systemfunktionen
Tabellenfunktionen
Indexfunktionen
Volltext-Indizierung
Memos und Blobs
Semaphoren-Konzept

Support Datenbank
Einführungskurs

Datenbank-Funktionen

Erzeugen einer Tabelle

MakeDB(Tabellenname, Paßwort, Verschlüsselungscode, Strukturdefinition [,Quelle]) : Fehlercode

Die Strukturdefinition ist der Name einer Textdatei, die folgendermaßen aufgebaut ist:
 
[STRUCTURE]
field_1=fieldspec
field_2=fieldspec
...
[INDEX]
id=indexdef
index_1=ind-name:ind-desc
index_2=ind-name:ind-desc
...

Der Abschnitt unter [INDEX] ist nur erforderlich, wenn die Tabelle automatisch numeriert wird.

Eine Feldspezifikation fieldspec hat folgende Struktur:
 
Feldbezeichner,Typdefinition[,(Importfeld)]

Als Feldbezeichner sind alle Bezeichner zugelassen, die mit einem Buchstaben oder Unterstrich beginnen und nur aus Buchstaben, Ziffern und Unterstrich bestehen. Die maximale Länge beträgt 35 Zeichen.

Folgende Typdefinitionen sind zugelassen:

Zeichenketten:
 
STRING,Länge (Länge von 1 bis 255) Stringfeld mit der angegeben Maximallänge

Zahlen:
 
NUMBER,NumCode[,Nachkommastellen][,U] numerisches Feld je nach NumCode

 
NumCode Typ Wertbereich
1 Byte Ganze Zahlen von 0 bis 255
2 16-Bit-Integer Ganze Zahlen von 32768 bis + 32767
4* 32-Bit Integer Ganze Zahlen von - 2147483648 bis + 2147483647
6** 6-Byte REAL (altes Borland-Format) Fließkommazahlen von -2.9 x 10^39 bis +1.7 x 10^38 bei 11-12 sign. Stellen
8*** 8-Byte-REAL Fließkommazahlen (ANSI double) Fließkommazahlen von -5.0 x 10^324 bis +1.7 x 10^308 bei 15-16 sign. Stellen 

*) nur tdbengine, nicht kompatibel zur VDP oder TurboDatenbank
**) kompatibel zu allen VDP- und TurboDatenbank-Versionen
***) nur tdbengine und VDP (ab 2.5)

Nachkommstellen werden nur bei den REAL-Typen berücksichtig. Sie sind wesentlich für den Datentransfer mit den Funktionen GetField und SetField sowie beim Export in andere Datenbankformate. Intern werden alle REAL-Typen immer mir der optimalen Genauigkeit gespeichert.

Wird der Parameter U angegeben, so wird in Selektion zwischen dem Wert 0 und "undefiniert" unterschieden.

Memos und Blobs
 
MEMO ergibt ein Memofeld

Der Inhalt eines Memofeldes ist ein Verweis auf eine zusätzliche Memodatei. In Memodateien werden auschließlich unformatierte Texte gespeichert.
 
BLOB [,blocksize] ergibt ein Blobfeld

Der Inhalt eines Blobfeldes ist ein Verweis auf eine zusätzliche Blobdatei In Blobdateien werden beliebige Daten gespeichert. Mit blocksize kann die Größe der Cluster in der Blobdatei festgelegt werden (Minimum = 64, Maximum = 8192, Default = 4096). Pro Eintrag in die Blobdatei wird im Schnitt ein halber Cluster verschwendet, aber zu kleine Cluster verlängern die Zugriffszeiten.

AUTO-INCREMENT
 
AUTO[,Startnummer] Autonummern-Feld (AUTO INCREMENT) 

Die Zählung beginnt (in einer neuen Tabelle) mit der Startnummer (bzw 1, falls keine angegeben wurde)

Datum und Zeit
 
DATE Datumsfeld (dd.mm.yyyy)
TIME Zeitfeld (hh:mm) 

Aufzählung
 
SELECT,Wert1,Wert2,Wert3,... Auswahlfeld mit dem angegebenen Wertbereich

Verknüfungen
 
REL Relationsfeld zwischen den angegebenen Tabellen 
Achtung: Die tdbengine erzeugt nicht automatsich die zugehörige Relationstabelle. Hierfür steht die Funktion GenRel zur Verfügung.
LINK,Tabelle  ADL-Linkfeld zur angegebenen Tabelle 
Es wird nicht gepüft, ob die Tabelle existiert oder ob die automatisch numeriert wird.

Importfelder festlegen

Ist in GenTable eine Quelle angegeben, so wird das spezifizierte Feld durch den Inhalt des angegebenen Importfeldes der Quelle ersetzt. Ist kein Importfeld angegeben, so wird der spezifizierte Feldname verwendet.

Wird als Quelle der gleiche Dateiname wie unter Ziel angegeben, so wird die Tabelle entsprechend restrukturiert. Als Abkürzung für den gleichen Dateinamen ist das Zeichen "@" erlaubt.

Hinweis: Die Strukturdefinition ist eigentlich eine Maschinendatei, die von einem Hilfsprogramm durch Interaktion mit dem Anwender erzeugt wird. Wenn Sie eine Strukturdefinition von Hand erstellen, sollten Sie unbedingt folgendes beachten:

  • Die Numerierung der Felder muß lückenlos sein.
  • Keine Feldnummer darf doppelt vorkommen.
  • Fügen Sie neue Felder immer am Ende an, da die Reihenfolge nicht wesentlich ist.
  • Wenn Sie im Zuge einer Umstrukturierung einen Feldbezeichner ändern wollen, so vergessen Sie nicht, den bisherigen Bezeichner als Importfeld anzugeben, da andernfalls der Feldinhalt verloren ist.
Die Umstrukturierung einer Tabelle ist immer ein kritischer Vorgang, wenn die Tabelle bereits Informationen enthält. Sie können zur Datensicherheit beitragen, indem Sie auf die direkte Umstrukturierung verzichten, und statt dessen die bisherige Tabelle mit RenTable umbenennen und die umbenannte Tabelle als Quelle angeben. Falls irgendetwas schiefgeht, können Sie immer noch auf die bisherige Tabelle zugreifen.

Tabellenstruktur ermitteln

GetDef(db : REAL; structfile : STRING) : REAL

db : Tabellenhandle von OpenDB
structdef : Pfad zu einer Textdatei, in die die Strukturdefinition geschrieben wird.

Rückgabewert: 0 = ok, sonst Fehlercode

Die Tabellenstruktur der geöffneten Tabelle db wird in die angegebene Datei geschrieben. Diese kann dann wiederum zum Erzeugen neuer Tabellen verwendet werden. Als Ziel sind auch Ramtexte zulässig.

Beispiel: Leere Kopie einer geöffneten Tabelle db erzeugen

GetDef(db,'ramtext:text:structure')
MakeDB('kopie_von'+DBName(db),'',0,'ramtext:text:structure')

Löschen einer Tabelle

DelDB(Tabellenname, Paßwort : STRING; Code : REAL) : Fehlercode

Löscht die Tabelle inklusiver aller Zusatzdateien wie Memo, Blob und Indizes.

Umbenennen einer Tabelle

RenDB(Datename,Paßwort,Code,NeuerName) : Fehlercode

Benennt die Tabelle mit dem angegeben Datenamen und den neuen Namen um. Es werden ebenfalls Memo, Blob und Indexdateien bei Bedarf umbenannt.

Tabellen öffnen und Schließen

OpenDB(Dateiname[,Paßword[,Code[,Modus]]]) : Tabellennummer

Modus ist ein Addition der einzelner Grundmodi, mit denen die gewünschte Zugriffsart gekennzeichnet wird:

0 : (Vorgabe) Es dürfen keine Veränderungen an der Tabelle vorgenommen werden.
1 : Es dürfen neue Datensätze erzeugt werden
2 : Es dürfen bestehende Datensätze überschrieben werden
4 : Es dürfen Datensätze gelöscht werden
8 : Es dürfen Indizes erzeugt und gelöscht werden

Der Modus 15 erlaubt somit sämtliche Modifikationen an de Tabelle.

Hinweis: Tritt beim Öffnen der Tabelle ein Fehler auf, so wird das Programm normalerweise mit einer entsprechenden Fehlermeldung beendet. Wenn die interne Fehlerbehandlung abgeschaltet wurde, ist der Rückgabewert der Funktion 0, und der Fehler kann mit TDB_ErrorCode ermittelt werden.

Beispiel:
 
VARDEF d : REAL
.EC 1
IF d:=OpenDB("database/adressen.dat")=0 THEN
  CGIWriteHtml("Beim Öffnen der Tabelle ist folgender Fehler aufgetreten: ")
  CGIWriteHtml(TDB_ErrorStr(TDB_LastError))
ELSE
  CGIWriteHtml(str(FileSize(d))+" Datensätze stehen zu Ihrer Verfügung")
END

Anders als die TurboDatenbank öffnet die tdbengine über L- oder R-Felder verknüpfte Tabellen nicht automatisch, sondern diese müssen bei Bedarf separat mit OpenDB geöffnet werden. Dabei ist zu beachten, daß immer die zuletzt geöffnete Tabelle in die bisherige Relationsstruktur eingebaut wird. Das bedeutet beispielsweise, daß Relationstabellen immer erst nach den Tabellen, zwischen denen sie die Verknüpfung definiert, geöffnet werden darf. Wird eine Tabelle mit einem L-Feld geöffnet, muß die zugehörige Link-Tabelle schon geöffnet sein, damit die Verknüpfung aktiv wird.

CloseDB(Tabellennummer)

Eine geöffnete Tabelle kann jederzeit mit CloseDB(Tabellennummer) wieder geschlossen werden.

Am Programmende wird automatisch CloseDB für aller geöffneten Tabellen ausgeführt.

Hinweis: Im Zuge eines guten Programmierstils sollten Sie alle Tabellen, die von Ihrem Programm geöffnet werden, auch wieder schließen.
 

Tabellengröße ermitteln

FileSize(Tabellennummer[,Modus] : REAL) : REAL

Liefert die Anzahl der Datensätze in der Tabelle.

Modus = 0 (Vorgabe) Standard -> Anzahl der Datensätze in der zugehörigen .dat (bzw. -1 bei Volltext-Stichwort-Listen).
Modus =1 Erweitert ->
  Anzahl der ID-Einträge im ID-Index bei Stichwortlisten, die mittels ScanRecs und Modus=4 erzeugt wurden
  Anzahl der Einträge im IN2-Index bei REL-Dateien, die mittels ScanRecs im Modus=4 erzeugt wurden.


Datensätze lesen, schreiben und löschen

Die tdbengine stellt für jede Tabelle einen Datensatzpuffer zur Verfügung. Alle Datenfeld-Funktionen beziehen sich auf diesen Datensatzpuffer.

ReadRec(Tabellennummer,Satznummer) : REAL

Liest den Datensatz mit der Satznummer in den Datensatzpuffer der Tabelle mit der angegebenen Tabellennummer. Falls Satznummer=0, wird ein leerer Datensatz bereitgestellt. Das Funktionergebnis ist die Satznummer, wenn der Datensatz gelesen werden konnte, andernfalls 0.

Bei einer illegalen Satznummer wird ein Laufzeitfehler ausgelöst.

WriteRec(Tabellenummer,Satznummer) : REAL

Schreibt den aktuelen Datensatzpuffer an der abgegeben Satznummer in die Tabelle. Zulässige Satznummern sind 1..FileSize(Tabellennummer)+1.

Illegale Satznummern führen zu einem Laufzeitfehler.

Liegt die Satznummer zwischen 1 und FileSize(Tabellennummer) so wird der entsprechende Datensatz überschrieben, andernfalls wird die Tabelle um einen Datensatz erweitert.

DelRec(Tabellennummer,Satznummer) : REAL

Löscht den Datensatz mit der angegebenen Satznummer. Die tdbengine geht beim Löschen eines Datensatzes so vor:

  • Der Datensatz wird aus sämtlichen Indizes der Tabelle gelöscht.
  • Handelt es sich um den letzen Datensatz der Tabelle, so wird die Tabelle um einen Eintrag verkürzt.
  • Andernfalls wird der letzte Eintrag der Tabelle an die Position des zu löschenden Datensatzes kopiert, alle Indizes entsprechend geändert und schließlich die Tabelle um einen Eintrag verkürzt.
Dieses Vorgehen hat zwar den Vorteil, daß die Tabelle immer nur aktuelle Datensätze enthält. Vorsicht ist jedoch geboten, wenn sich Funktionen auf physikalische Satznummern beziehen. Zwar liefert RecNo(Tabellennummer) immer die aktuelle Satznummer (auch wenn sich diese infolge Löschungen verschoben haben). Bei CGI-Programmen ist jedoch darauf zu achten, daß die Verbindung immer wieder abgebrochen wird, und die Informationen über CGI-Variable an den nächsten Aufruf übergeben wird. Hier kann der Bezug auf physikalische Satznummern fatale Folgen haben, denn die kann sich von einem Aufruf zum nächsten bereits geändert haben.

Abhile schafft der Bezug auf die Autonummern der Tabelle. Dazu stellt die tdbengine zwei neue Funktionen zur Verfügung, mit der die Umwandlung von Satznummern und Autonummern stark vereinfacht wird: AutoField und FindAuto.

AutoField(Tabellennummer) : REAL

liefert die Nummer des AUTO-Feldes (bzw. 0, wenn nicht automatisch numeriert).

GetRField(Tabellenummer,AutoField(Tabellennummer)) liefert so die Autonummer eines Satzes der Tabelle. Dafür gibt es die Funktion

AutoRecNo(db : REAL) : REAL

db : Tabellenhandle von OpenDB

Rückgabewert:

  RecNo(db)    wenn kein AUTO-INCREMENT-Feld in db
  GetRField(db,AutoField(db))  sonst

FindAuto(db,x : REAL) : REAL

db : Tabellenhandle von OpenDB
x : (Auto-)Nummer

Rückgabewert:

x   wenn kein AUTO-INCREMENT-Feld in db
FindRec(db,str(x),0,1)  sonst

Wann immer es möglich ist (also eine Autonummer in der Tabelle enthalten ist), sollte die Information über einen Datensatz als Autonummer zwischen CGI-Programmen erfolgen.

Eine andere Problematik steckt in der Verwendung von Volltext-Indizes, die ja auch auf physikalische Satznummern zurückgreifen. Ein Volltextindex wird nicht automatisch aktualisiert, wenn ein Datensatz gelöscht wird. Das ist auch garnicht möglich, da Volltextindizes kein Bestandteil der Tabelle sind, die tdbengine demnach auch keine Information darüber haben kann.

Ein Ausweg besteht darin, einen Volltextindex nach dem Löschen in einer Tabelle neu zu erzeugen. Bei kleiner Tabellen ist diese Vorgehensweise aufgrund der hohen Geschwindigkeit der tdbengine auch durchaus praktizierbar. Der andere, aufwendigere und auch elegantere Ausweg besteht darin, den Volltextindex dynamisch mit der Tabelle mitzuführen. Mit ScanRec und UnScanRec stehen dazu die benötigten Funktionen zur Verfügung. Hier nur das Grundgerüst für das Löschen eines Datensatzes mit Volltext-Index-Nachführung:
 
PROCEDURE DelRecWithFullText(TheTableHdl, TheRecNo : REAL) 
  Readrec(TheTableHdl,TheRecNo) // auf gewünschtem Datensatz positionieren
  UnScanRec(...) // Volltextindex für diesen Satz löschen
  IF TheRecNo<=FileSize(TheTableHdl) 
    ReadRec(TheTableHdl,FileSize(TheTableHdl)) // auf letzten Datensatz positionieren 
    UnScanRec(...) // Volltextindex für den letzten Satz löschen 
    DelRec(TheTableHandle,TheRecNo) // Letzter Satz wird hierher verschoben 
    ScanRec(...) // und wird neu Volltext-indiziert 
  ELSE
    DelRec(TheTableHdl,TheRecNo) 
  END 
ENDPROC

Datensätze suchen und markieren

FindRec
FirstRec
LastRec
NextRec
FindAndMark

Der Zugriff auf Datenfelder

GetField(Tabellenummer, Feld) : STRING
GetRField(Tabellennummer,Feld) : REAL
SetField(Tabellennummer, Feld) : REAL
SetRField(Tabellennummer, Feld) : REAL
 

Markierungsfunktionen

GetMarks
PutMarks
FirstMark
NextMark
DelMarks