Diese Seite wurde maschinell übersetzt. Lesen Sie das englische Original. English

IBSurgeon-Bibliothek

Datentypen

NOTICE: Dieses Dokument ist ein Kapitel aus dem Buch “The InterBase World”, das von Alexey Kovyazin und Serg Vostrikov geschrieben wurde.

Trotz der Tatsache, dass Datentypen in der Dokumentation ausführlich beschrieben sind (siehe [1, Kapitel 4.), ist es notwendig, eine Reihe von Begriffen zu betrachten, die in den folgenden Kapiteln dieses Buches häufig verwendet werden. Neben allgemeinen Informationen werden auch mehrere Beispiele für die Verwendung von Datentypen in InterBase-Datenbanken sowie Empfehlungen zu deren Verwendung und Konvertierung behandelt. Wir werden die Unterschiede bei den Datentypen, die im 1. und 3. InterBase-Datenbankdialekt bestehen, im Detail betrachten.

Über Daten

Datentypen sind grundlegende Elemente jeder Programmiersprache oder jedes DBMS-Servers. InterBase ist keine Ausnahme. Wenn wir sagen, dass eine Datenbank einige Informationen speichert, müssen wir uns darüber im Klaren sein, dass diese Informationen nicht an einem Ort gespeichert werden können. Im Gegenteil, Daten müssen sortiert und auf ihr “Regal” gelegt werden. Datentypen definieren, was auf ein bestimmtes “Regal” gelegt werden kann und was nicht. Wenn wir über das “Regal” sprechen, meinen wir in erster Linie Felder von Datenbanktabellen (siehe Kapitel “Tabellen. Primärschlüssel und Generatoren” (Teil 1)) sowie Variablen innerhalb von Triggern und gespeicherten Prozeduren usw. Jeder Datentyp hat eine Reihe von Operationen, die über die Werte dieses Typs ausgeführt werden können. Daher ist es wichtig, den richtigen Datentyp beim Entwurf einer Datenbank zu wählen. Dies hilft, viele Probleme bei der Entwicklung von Client-Programmen zu vermeiden. In InterBase gibt es 12 Datentypen, die die Anforderungen des Entwicklers an die Speicherung von Daten erfüllen können. Diese Typen werden bedingt in die folgenden 6 Gruppen unterteilt:

  • zum Speichern von Ganzzahlen - INTEGER und SMALLINT;
  • zum Speichern von reellen Zahlen - FLOAT und DOUBLE PRECISION;
  • zum Speichern von Zahlen mit fester Genauigkeit - NUMERIC und DECIMAL;
  • zum Speichern von Datum, Zeit und Zeitstempel - DATE, TIME und TIMESTAMP;
  • zum Speichern von Zeichen - CHARACTER (in abgekürzter Form - CHAR) und VARYING CHARACTER (VARCHAR);
  • zum Speichern von dynamisch erweiterbaren Daten - BLOB

Darüber hinaus ist es möglich, Arrays von Werten primitiver Typen zu definieren, d.h. alle aufgeführten Typen außer BLOB.

Die meisten InterBase-Datentypen entsprechen den im SQL92-Standard definierten Typen, jedoch gibt es darüber hinaus eigene Besonderheiten - Arrays von primitiven Datentypen und BLOB. Arrays in InterBase können eine Menge von Daten desselben Typs in einem Feld enthalten. Zum Beispiel können wir ein Array von Werten des Typs INTEGER definieren. Arrays können mehrere Dimensionen haben. Der BLOB-Datentyp ist ein dynamisch erweiterbarer Datentyp, dessen Name oft als Binary Large OBject entschlüsselt wird. Es sollte gesagt werden, dass BLOB eine Erfindung der InterBase-Entwickler ist, die sich später verbreitete und in allen zeitgenössischen SQL-Servern etablierte.

Syntax zur Definition von Datentypen

Datentypen werden verwendet, um Felder in Tabellen, Variablen in Triggern und gespeicherten Prozeduren zu beschreiben. Die allgemeine Syntax zur Definition aller möglichen Datentypen in InterBase ist unten angegeben.

< datatype> =

{SMALLINT | INTEGER | FLOAT | DOUBLE PRECISION}[ ]

| {DATE | TIME | TIMESTAMP} [ ]

| {DECIMAL | NUMERIC} [( precision [, scale])] [ ]

| {CHAR | CHARACTER | CHARACTER VARYING | VARCHAR} [( int)

[ ] [CHARACTER SET charname]

| {NCHAR | NATIONAL CHARACTER | NATIONAL CHAR}

[VARYING] [( int)] [ ]

| BLOB [SUB_TYPE { int | subtype_name}] [SEGMENT SIZE int]

[CHARACTER SET charname]

| BLOB [(seglen [, subtype])]

Die Eigenschaften von Datentypen wie Größe, Genauigkeit und ein Bereich möglicher Werte sind in Tabelle 4.1 in [1. ausführlich beschrieben, daher werden wir uns hier nicht wiederholen. Lassen Sie uns nun kurz die wichtigsten Besonderheiten der Datentypen betrachten und uns auf ihre mögliche Anwendung konzentrieren.

Ganzzahltypen

SMALLINT und INTEGER gehören zu den Ganzzahltypen. Ich sollte sagen, dass SMALLINT eine verkümmerte Version von INTEGER darstellt. Seine Länge beträgt 2 Bytes im Gegensatz zu 4, die für die Speicherung von INTEGER vorgesehen sind. Normalerweise sollte man nicht am Speicherplatz sparen. Aus diesem Grund ist es besser, den Typ INTEGER zum Speichern von Ganzzahlwerten zu verwenden.

Der Anwendungsbereich von Ganzzahltypen ist offensichtlich: Sie sind für Felder notwendig, die nur Ganzzahlen enthalten - zum Speichern von Zählern, Nummern usw. Normalerweise haben auch die Felder, die Primärschlüssel enthalten, den Typ INTEGER.

Reelle Datentypen

Die Typen FLOAT und DOUBLE PRECISION gehören zu den reellen Typen (sie werden auch Zahlentypen mit Gleitkomma genannt). Zunächst möchte ich den Leser vor der Verwendung des Typs FLOAT warnen - seine Genauigkeit reicht nicht aus, um die meisten Bruchwerte zu speichern. Besonders wird nicht empfohlen, Geldwerte darin zu speichern - in FLOAT-Variablen treten sehr schnell Rundungsfehler auf, und das könnte einen Buchhalter bei Berechnungen überraschen. Der beste Weg, Zahlen mit Gleitkomma (z.B. in Buchhaltungssystemen und Systemen für wissenschaftliche Berechnungen) in einer Datenbank zu speichern, ist die Speicherung im Typ DOUBLE PRECISION.

Sie sollten berücksichtigen, dass es im 3. InterBase-Dialekt einen Mechanismus zur Speicherung von Typen mit einem Festkomma von 64 Bytes gibt. Dieser Mechanismus wird zum Speichern von Geldwerten verwendet. Die Verwendung dieser Typen bietet die beste Genauigkeit.

Datentypen mit Festkomma

NUMERIC und DECIMAL gehören zu diesen Datentypen. Die Frage nach dem Unterschied zwischen NUMERIC und DECIMAL wird sehr oft gestellt. Beide Typen haben eine identische Stellenzahl - von 1 bis 18 Zeichen, identische Genauigkeit - von null bis zur Stellenzahl.

Erinnern wir uns daran, dass: die Stellenzahl die Gesamtzahl der Ziffern ist, und die Genauigkeit - die Anzahl der Zeichen nach dem Komma.

Das Lustigste ist, dass sich diese Typen laut Dokumentation in der maximalen Stellenzahl unterscheiden, aber tatsächlich werden sie praktisch gleich realisiert und es gibt keinen Unterschied zwischen ihnen.

Sie können dies leicht überprüfen, indem Sie das Dienstprogramm isql starten und die unten beschriebene Befehlsfolge ausführen. Wir erstellen die Tabelle mit folgender Ansicht:

SQL> CREATE TABLE test (

CON> Num_field NUMERIC(15,2),

CON> Dec_field DECIMAL(15,2));

Dann geben wir einen Befehl, um die Struktur der Tabelle anzuzeigen:

SQL> show tables test;

Und wir sehen Folgendes:

NUM_FIELD NUMERIC(15, 2) Nullable

DEC_FIELD NUMERIC(15, 2) Nullable

Wie Sie sehen können, teilt InterBase mit, dass beide angegebenen Spalten den Typ NUMERIC haben. Die Gründe für ein solches Verhalten liegen in der Realisierung von Datentypen mit Festkomma. Die Sache ist die, dass InterBase nur drei Mechanismen zum Speichern eines beliebigen ganzzahligen Ausdrucks hat, und alle Typen, wie auch immer sie genannt werden, werden gemäß diesen Varianten realisiert.

Hier ist die Tabelle aus [1., die veranschaulicht, wie verschiedene Ganzzahltypen (Tabelle 1.1) gespeichert werden. Wie Sie sehen können, unterscheidet sich die Speicherung der Daten im 3. Dialekt für Zahlen mit großer Stellenzahl:

Tabelle 1.1. Speicherung von Zahlen mit Festkomma

Stellenzahl Dialekt 1 Dialekt 3
von 1 bis 4 SMALLINT für NUMERIC
INTEGER für DECIMAL
SMALLINT
von 5 bis 9 INTEGER INTEGER
von 10 bis 18 DOUBLE PRECISION INT64

Jetzt können wir sicher sagen, was die Hauptunterschiede zwischen den Typen NUMERIC und DECIMAL sind: Bei der Definition eines Feldes (einer Variablen) mit kleiner Stellenzahl (bis zu vier) wird der erste als 2-Byte-Ganzzahl SMALLINT gespeichert, und der zweite - als 4-Byte-INTEGER. Wenn die Stellenzahl also mehr als vier beträgt, sind die Typen DECIMAL und NUMERIC äquivalent.

Beachten Sie den Unterschied in der Realisierung von Typen mit großer Stellenzahl im ersten und dritten Dialekt. Im ersten Dialekt wurde die Zahl mit Festkomma von einer Ganzzahl in eine reelle Zahl umgewandelt, wobei Rundungsmechanismen angewendet wurden. Im dritten Dialekt wurde diese Besonderheit beseitigt - die großen Ganzzahlen werden tatsächlich als Ganzzahlen gespeichert - unter Verwendung des INT64-Mechanismus, der 64-Bit-Zahlen in einem Bereich von +/-2^32 speichern kann. Daher wäre es besser, die Daten über Geldmittel in Datenbanken zu speichern, die mit dem 3. Dialekt erstellt wurden. Nur die Verwendung des INT64-Mechanismus garantiert die Sicherheit der kleinen Geldreste.

Typen zum Speichern von Datum und Zeit

Die Typen zum Speichern von Datum und Zeit haben sich in Version InterBase 6.x und ihren Klonen im Vergleich zu 4.x und 5.x geändert. Um uns nicht in historischen Verstrickungen mit diesen Typen zu verlieren, betrachten wir die Situation in InterBase 6. Version. Dann werden wir auf dieser Grundlage kurz erwähnen, was früher war. Dies geschieht für diejenigen Benutzer, die noch mit frühen Versionen von InterBase arbeiten. Es gibt also 3 Typen in InterBase 6.x zum Speichern von Datum und Zeit - DATE, TIME und TIMESTAMP.

  • Typ DATE speichert Daten bis auf einen Tag genau. Ein Bereich möglicher Werte - vom 1. Januar 100 n. Chr. bis zum 29. Februar 32768.
  • Typ TIME speichert die Daten über die Zeit bis auf ein Zehntausendstel einer Sekunde genau. Ein Bereich möglicher Werte - von 00:00 Uhr bis 23:59.9999 Uhr.
  • Typ TIMESTAMP stellt eine Kombination der Typen DATE und TIME dar.

Wie arbeitet man mit Daten? Wenn es um die Arbeit auf Serverebene in gespeicherten Prozeduren oder Triggern geht, ist alles ziemlich einfach - wir können immer eine Variable des erforderlichen Typs deklarieren und sie aus den Tabellen setzen und umgekehrt. Es ist jedoch notwendig, die Daten von einer Datenbank an die Anwendung und zurück zu übertragen. In diesem Fall gibt es zwei Ansätze: Bibliotheken zu verwenden, die ein ursprüngliches Format der InterBase-Daten für den Zugriff auf Objekte dieser Typen anwenden und dieses Format in gewöhnliche sprachinterne Datums-/Zeittypen konvertieren (FIBPlus ist ein Beispiel für eine solche Bibliothek), oder den in InterBase eingebetteten Mechanismus zur Umwandlung von Daten in Zeichenfolgen zu verwenden.

Was tun Sie, wenn Sie nur das Jahr oder den Monat aus dem vollständigen Datum ausschneiden müssen? Sie müssen dafür eine Gruppe von Funktionen EXTRACT verwenden (in allen Klonen von InterBase 6.x verfügbar), die es Ihnen ermöglicht, nur den erforderlichen Teil aus dem Datum zu extrahieren. Diese Funktionen werden wie folgt verwendet:

EXTRACT (MONTH FROM DATE_FIELD)

EXTRACT (YEAR FROM DATE_FIELD)

Die vollständige Liste der Parameter in der Funktion EXTRACT ist die folgende: YEAR, MONTH, DAY, HOUR, MINUTE, SECOND, WEEKDAY, YEARDAY. Ihre Funktion folgt aus ihrem Namen, daher werden wir sie hier nicht interpretieren.

Datentypen zum Speichern von Text

Es gibt zwei Typen in InterBase, die zum Speichern von Textinformationen bestimmt sind - CHAR und VARCHAR. Ihre vollständigen Namen - CHARACTER und CHARACTER VARYING, jedoch gibt es keinen Grund, lange Namen zu verwenden - selbst der Befehl Show tables im Dienstprogramm isql gibt kurze Namen der Typen an.

Um ein Feld oder eine Variable eines symbolischen Typs zu definieren, ist es notwendig, in Klammern nach dem Namen des Typs eine Anzahl von Symbolen anzugeben, die in einem definierten Objekt verwendet werden, oder die Anzahl der Symbole wegzulassen - dadurch wird ein Feld mit einer Länge von 1 Symbol erstellt.

CREATE TABLE testCHARLen(

Field1 CHAR(255),

Field2 CHAR);

Wenn diese Tabelle erstellt wird, hat Field1 eine Länge von 255 Symbolen und Field2 - 1 Symbol.

Die Typen CHAR und VARCHAR sind in vielerlei Hinsicht ähnlich - beide können bis zu 32768 Symbole enthalten, jedoch gibt es einige Unterschiede. Obwohl beide Typen in einer Datenbank auf die gleiche Weise gespeichert werden, arbeitet InterBase auf unterschiedliche Weise mit ihnen. Das folgende Beispiel demonstriert dies:

SQL> create table testCHAR ( c1 char(10), c2 varchar(10));

SQL> insert into testCHAR(c1,c2) values(‘Test’,‘Test’);

SQL> SELECT ‘(’||c1.|’)’, ‘(’||c2.|’)’ from testCHAR;

Als Ergebnis erhalten wir Folgendes:

(Test ) (Test)

Wie Sie sehen können, gab es nach dem Wert ‘Test’, der aus einem Feld c1 ausgewählt wurde, Leerzeichen. Das bedeutet, dass beim Auswählen der Daten aus einem Feld vom Typ CHAR der zurückgegebene Wert mit Leerzeichen bis zur vollen Länge eines Feldes ergänzt wird. Es ist schwer anzunehmen, warum ein solches Verhalten, das zu einem erheblichen Anstieg des Netzwerkverkehrs (Belastung des Netzwerks) führt, notwendig ist. In jedem Fall ist VARCHAR ein symbolischer Typ, der zur Verwendung empfohlen wird.

Eine der wichtigsten Eigenschaften des symbolischen Typs ist sein Zeichensatz - CHARACTER SET. Der Zeichensatz wird für die gesamte Datenbank definiert und standardmäßig für alle symbolischen Felder verwendet, wenn er nicht explizit beim Erstellen eines Feldes neu definiert wird. Um ein symbolisches Feld mit der expliziten Angabe eines Zeichensatzes zu erstellen, ist es notwendig, die Beschreibung eines Zeichensatzes in der Beschreibung einer Spalte hinzuzufügen (in den Sätzen CREATE TABLE oder ALTER TABLE). Der Zeichensatz WIN1251 wird normalerweise für die Unterstützung von Russisch verwendet (wenn Sie Details über die Verwendung von Russisch in InterBase erfahren möchten, siehe Kapitel “InterBase-Russifizierung” (Teil 1)). Hier ist ein Beispiel für eine Tabelle, die ein symbolisches Feld mit dem explizit beschriebenen Zeichensatz WIN1251 enthält:

CREATE TABLE TestCHARSET(

Field1 VARCHAR(255),

Field2 VARCHAR(255) CHARACTER SET win1251);

Здесь Field1 - это поле без явного указания набора символов, поэтому для него будет использоваться набор символов, заданный при создании базы данных. Для поля Field2 очевидно определено, что оно будет хранить символы в кодировке WIN1251.

Помимо указания набора символов для символьных полей, можно также задать порядок сортировки (collation), который определяет, как будут сортироваться символы этого набора данных. Для русского языка существует два варианта сортировки - WIN1251 и PXW_CYRL. Более подробно об использовании COLLATION ORDER см. главу «Русификация InterBase».

Полный список наборов символов и применяемых для них COLLATION ORDER можно найти в документации [1, глава 13..

Внимание! Согласно документации по InterBase 6 существует 4 символьных типа: помимо вышеупомянутых типов данных существуют еще 2 - NCHAR и NCHAR VARYING, однако в той же документации ниже объясняется, что последние два типа - это те же типы, что и CHAR и VARCHAR, только с набором символов ISO8859.1 по умолчанию. Это означает, что фактически использование псевдотипа NCHAR эквивалентно применению CHAR DEFAULT CHARACTER SET ISO8859.1. Аналогично для NCHAR VARYING, только вместо CHAR используется VARCHAR. Очевидно, что применение этих псевдотипов предназначено для пользователей в Западной Европе и США, где набор символов ISO8859.1 создан для поддержки языков.

Тип данных BLOB

Тип данных BLOB предназначен для хранения большого количества данных переменного размера. Тип BLOB позволяет хранить данные, которые нельзя разместить в полях других типов, - например, изображения, музыкальные файлы, видеофрагменты и т. д. Требования к определению простейшего поля типа BLOB в таблице такие же, как и к определению поля любого элементарного типа:

CREATE TABLE testBLOB(

myBlobField BLOB);

В результате будет создано поле myBlobField, в котором можно хранить данные значительного размера. Несмотря на то, что поля BLOB не отличаются от других по способу определения, их реализация внутри базы данных сильно отличается. Не-BLOB-поля располагаются на странице данных (см. главу «Структура базы данных InterBase» (часть 4)) рядом друг с другом, а на странице данных хранится только идентификатор BLOB, сам же BLOB размещается на специальной странице. Такая структура данных позволяет хранить данные нефиксированного размера.

Тип BLOB предоставляет возможность определить набор нескольких подтипов и специальных процедур, называемых фильтрами (BLOB filters), для работы с этими подтипами. В InterBase встроено несколько предопределенных подтипов BLOB. Все эти подтипы имеют неотрицательные номера, например подтип 0 - данные неопределенного типа, подтип 1 - текст, подтип 2 - BLR (Binary Language Representation, см. глоссарий и главу «Структура базы данных InterBase») и т. д. Пользователь также может определять подтипы BLOB, которые могут иметь отрицательные значения. Фильтр может применяться к каждому типу. Он преобразует поле одного подтипа в другой.

Следует отметить, что использование BLOB-полей обычно является альтернативой хранению внешних по отношению к базе данных файлов. Что касается BLOB-фильтров, они используются довольно редко из-за ориентации на узкую категорию задач.

Массивы

СУБД InterBase была одной из первых, в которых появились массивы. Поддержка массивов в базе данных является расширением традиционной реляционной модели. Наличие массивов позволяет упростить работу с наборами данных одного типа.

Массив - это коллекция значений одного типа, имеющая общее имя и позволяющая обращаться к любому элементу массива по его номеру. Массивы в InterBase могут быть одномерными и многомерными.

Чтобы создать в таблице поле массива чисел INTEGER, следует написать примерно следующее:

CREATE TABLE test(

myOneDimArray INTEGER[12.,

myTwoDimArray INTEGER[5,4.,

myThreeDimArray INTEGER[2,10,8.);

Таким образом, будут созданы три поля типа массив: myOneDimArray - поле, содержащее одномерный массив из 12 чисел, myTwoDimArray - поле, содержащее двумерный массив (матрицу) - 5х4 целых чисел, и myThreeDimArray - поле, содержащее трехмерный массив 2х10х8. Следует отметить, что при таком определении элементы массива нумеруются начиная с «единицы», т. е. первый элемент имеет номер 1, второй - номер 2 и т. д. Если кто-то хочет задать границы массива самостоятельно, например от 0 до 5, следует указать определение поля следующим образом:

myArray INTEGER[0:5.

Массивы реализованы на основе полей типа BLOB, поэтому не стоит опасаться, что многомерный массив «засорит» вашу таблицу большим количеством данных: InterBase аккуратно разместит данные массива на отдельных страницах для оптимизации операций ввода-вывода в этих полях. Как использовать массивы? Они предоставляют удобный механизм для хранения объектов одного типа. Однако в 80 % случаев вместо массивов разработчики предпочитают хранить множественные данные в подчиненных (детальных) таблицах, поэтому массивы не так часто используются в клиентских приложениях СУБД InterBase. Это происходит потому, что библиотеки доступа, поставляемые с Delphi и C ++ Builder, такие как BDE и IBX, не умеют работать с массивами. Согласно документации по InterBase, с массивами можно работать с помощью препроцессора gpre, однако это не самый удобный способ для разработчика на Delphi/C ++ Builder. К счастью, в библиотеке FIBPlus есть поддержка полей-массивов в InterBase. Подробно об этом можно прочитать в главе «Особые возможности FIBPlus». Клиентская библиотека IBProvider, позволяющая создавать клиентские приложения для InterBase с использованием средств разработки компании Microsoft, также поддерживает работу с массивами (см. главу «Разработка клиентских приложений СУБД InterBase с использованием технологии Microsoft OLE DB» (часть 3)).

Заключение

Следует отметить, что невозможно рассказать о типах данных, не забегая вперед, поскольку они проникают во все ключевые области, связанные с разработкой приложений баз данных. Поэтому при чтении этой книги лучше использовать данную главу как краткий справочник, к которому можно обращаться всякий раз, когда нужно освежить основы InterBase.